All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get
@ 2017-01-04 18:56 Andrew Lunn
  2017-01-04 21:11 ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2017-01-04 18:56 UTC (permalink / raw)
  To: David Miller
  Cc: volodymyr.bendiuga, Vivien Didelot, Florian Fainelli, netdev,
	Andrew Lunn

Lookup in the ATU can be performed starting from a given MAC
address. This is faster than starting with the first possible MAC
address and iterating all entries.

Entries are returned in numeric order. So if the MAC address returned
is bigger than what we are searching for, we know it is not in the
ATU.

Using the benchmark provided by Volodymyr Bendiuga
<volodymyr.bendiuga@gmail.com>,

https://www.spinics.net/lists/netdev/msg411550.html

on an Marvell Armada 370 RD, the test to add a number of static fdb
entries went from 1.616531 seconds to 0.312052 seconds.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---

Cc: netdev this time.

 drivers/net/dsa/mv88e6xxx/chip.c |  5 ++--
 include/linux/etherdevice.h      | 60 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index f7222dc6581d..4cdb0f09788b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2023,7 +2023,8 @@ static int mv88e6xxx_atu_get(struct mv88e6xxx_chip *chip, int fid,
 	struct mv88e6xxx_atu_entry next;
 	int err;
 
-	eth_broadcast_addr(next.mac);
+	memcpy(next.mac, addr, ETH_ALEN);
+	eth_addr_dec(next.mac);
 
 	err = _mv88e6xxx_atu_mac_write(chip, next.mac);
 	if (err)
@@ -2041,7 +2042,7 @@ static int mv88e6xxx_atu_get(struct mv88e6xxx_chip *chip, int fid,
 			*entry = next;
 			return 0;
 		}
-	} while (!is_broadcast_ether_addr(next.mac));
+	} while (ether_addr_greater(addr, next.mac));
 
 	memset(entry, 0, sizeof(*entry));
 	entry->fid = fid;
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 6fec9e81bd70..42add77ae47d 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -397,6 +397,66 @@ static inline bool ether_addr_equal_masked(const u8 *addr1, const u8 *addr2,
 }
 
 /**
+ * ether_addr_to_u64 - Convert an Ethernet address into a u64 value.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return a u64 value of the address
+ */
+static inline u64 ether_addr_to_u64(const u8 *addr)
+{
+	u64 u = 0;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		u = u << 8 | addr[i];
+
+	return u;
+}
+
+/**
+ * u64_to_ether_addr - Convert a u64 to an Ethernet address.
+ * @u: u64 to convert to an Ethernet MAC address
+ * @addr: Pointer to a six-byte array to contain the Ethernet address
+ */
+static inline void u64_to_ether_addr(u64 u, u8 *addr)
+{
+	int i;
+
+	for (i = ETH_ALEN - 1; i >= 0; i--) {
+		addr[i] = u & 0xff;
+		u = u >> 8;
+	}
+}
+
+/**
+ * eth_addr_dec - Decrement the given MAC address
+ *
+ * @addr: Pointer to a six-byte array containing Ethernet address to decrement
+ */
+static inline void eth_addr_dec(u8 *addr)
+{
+	u64 u = ether_addr_to_u64(addr);
+
+	u--;
+	u64_to_ether_addr(u, addr);
+}
+
+/**
+ * ether_addr_greater - Compare two Ethernet addresses
+ * @addr1: Pointer to a six-byte array containing the Ethernet address
+ * @addr2: Pointer other six-byte array containing the Ethernet address
+ *
+ * Compare two Ethernet addresses, returns true addr1 is greater than addr2
+ */
+static inline bool ether_addr_greater(const u8 *addr1, const u8 *addr2)
+{
+	u64 u1 = ether_addr_to_u64(addr1);
+	u64 u2 = ether_addr_to_u64(addr2);
+
+	return u1 > u2;
+}
+
+/**
  * is_etherdev_addr - Tell if given Ethernet address belongs to the device.
  * @dev: Pointer to a device structure
  * @addr: Pointer to a six-byte array containing the Ethernet address
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get
  2017-01-04 18:56 [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get Andrew Lunn
@ 2017-01-04 21:11 ` David Miller
  2017-01-04 21:19   ` Andrew Lunn
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2017-01-04 21:11 UTC (permalink / raw)
  To: andrew; +Cc: volodymyr.bendiuga, vivien.didelot, f.fainelli, netdev

From: Andrew Lunn <andrew@lunn.ch>
Date: Wed,  4 Jan 2017 19:56:24 +0100

> +static inline u64 ether_addr_to_u64(const u8 *addr)
> +{
> +	u64 u = 0;
> +	int i;
> +
> +	for (i = 0; i < ETH_ALEN; i++)
> +		u = u << 8 | addr[i];
> +
> +	return u;
> +}
 ...
> +static inline void u64_to_ether_addr(u64 u, u8 *addr)
> +{
> +	int i;
> +
> +	for (i = ETH_ALEN - 1; i >= 0; i--) {
> +		addr[i] = u & 0xff;
> +		u = u >> 8;
> +	}
> +}

I think these two routines behave differently on big vs little
endian.  And I doubt this was your intention.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get
  2017-01-04 21:11 ` David Miller
@ 2017-01-04 21:19   ` Andrew Lunn
  2017-01-04 21:27     ` Florian Fainelli
  2017-01-04 21:27     ` David Miller
  0 siblings, 2 replies; 6+ messages in thread
From: Andrew Lunn @ 2017-01-04 21:19 UTC (permalink / raw)
  To: David Miller; +Cc: volodymyr.bendiuga, vivien.didelot, f.fainelli, netdev

On Wed, Jan 04, 2017 at 04:11:03PM -0500, David Miller wrote:
> From: Andrew Lunn <andrew@lunn.ch>
> Date: Wed,  4 Jan 2017 19:56:24 +0100
> 
> > +static inline u64 ether_addr_to_u64(const u8 *addr)
> > +{
> > +	u64 u = 0;
> > +	int i;
> > +
> > +	for (i = 0; i < ETH_ALEN; i++)
> > +		u = u << 8 | addr[i];
> > +
> > +	return u;
> > +}
>  ...
> > +static inline void u64_to_ether_addr(u64 u, u8 *addr)
> > +{
> > +	int i;
> > +
> > +	for (i = ETH_ALEN - 1; i >= 0; i--) {
> > +		addr[i] = u & 0xff;
> > +		u = u >> 8;
> > +	}
> > +}
> 
> I think these two routines behave differently on big vs little
> endian.  And I doubt this was your intention.

I don't have a big endian system to test on.

I tried to avoid the usual pitfalls. I don't cast a collection of
bytes to a u64, which i know has no chance of working. Accessing a MAC
address as a byte array should be endian safe. The shift operation
should also be endian safe.

What exactly do you think will behave differently?

     Andrew

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get
  2017-01-04 21:19   ` Andrew Lunn
@ 2017-01-04 21:27     ` Florian Fainelli
  2017-01-04 21:27     ` David Miller
  1 sibling, 0 replies; 6+ messages in thread
From: Florian Fainelli @ 2017-01-04 21:27 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: volodymyr.bendiuga, vivien.didelot, netdev

On 01/04/2017 01:19 PM, Andrew Lunn wrote:
> On Wed, Jan 04, 2017 at 04:11:03PM -0500, David Miller wrote:
>> From: Andrew Lunn <andrew@lunn.ch>
>> Date: Wed,  4 Jan 2017 19:56:24 +0100
>>
>>> +static inline u64 ether_addr_to_u64(const u8 *addr)
>>> +{
>>> +	u64 u = 0;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < ETH_ALEN; i++)
>>> +		u = u << 8 | addr[i];
>>> +
>>> +	return u;
>>> +}
>>  ...
>>> +static inline void u64_to_ether_addr(u64 u, u8 *addr)
>>> +{
>>> +	int i;
>>> +
>>> +	for (i = ETH_ALEN - 1; i >= 0; i--) {
>>> +		addr[i] = u & 0xff;
>>> +		u = u >> 8;
>>> +	}
>>> +}
>>
>> I think these two routines behave differently on big vs little
>> endian.  And I doubt this was your intention.
> 
> I don't have a big endian system to test on.

You could build the driver for e.g: a MIPS Malta board and use the
qemu-system-mips to validate this, there could be a way to do that on
ARM too although it's a different kind of BE (BE8 vs. BE32) AFAIR.

> 
> I tried to avoid the usual pitfalls. I don't cast a collection of
> bytes to a u64, which i know has no chance of working. Accessing a MAC
> address as a byte array should be endian safe. The shift operation
> should also be endian safe.
> 
> What exactly do you think will behave differently?
> 
>      Andrew
> 


-- 
Florian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get
  2017-01-04 21:19   ` Andrew Lunn
  2017-01-04 21:27     ` Florian Fainelli
@ 2017-01-04 21:27     ` David Miller
  2017-01-04 21:45       ` Andrew Lunn
  1 sibling, 1 reply; 6+ messages in thread
From: David Miller @ 2017-01-04 21:27 UTC (permalink / raw)
  To: andrew; +Cc: volodymyr.bendiuga, vivien.didelot, f.fainelli, netdev

From: Andrew Lunn <andrew@lunn.ch>
Date: Wed, 4 Jan 2017 22:19:57 +0100

> On Wed, Jan 04, 2017 at 04:11:03PM -0500, David Miller wrote:
>> From: Andrew Lunn <andrew@lunn.ch>
>> Date: Wed,  4 Jan 2017 19:56:24 +0100
>> 
>> > +static inline u64 ether_addr_to_u64(const u8 *addr)
>> > +{
>> > +	u64 u = 0;
>> > +	int i;
>> > +
>> > +	for (i = 0; i < ETH_ALEN; i++)
>> > +		u = u << 8 | addr[i];
>> > +
>> > +	return u;
>> > +}
>>  ...
>> > +static inline void u64_to_ether_addr(u64 u, u8 *addr)
>> > +{
>> > +	int i;
>> > +
>> > +	for (i = ETH_ALEN - 1; i >= 0; i--) {
>> > +		addr[i] = u & 0xff;
>> > +		u = u >> 8;
>> > +	}
>> > +}
>> 
>> I think these two routines behave differently on big vs little
>> endian.  And I doubt this was your intention.
> 
> I don't have a big endian system to test on.
> 
> I tried to avoid the usual pitfalls. I don't cast a collection of
> bytes to a u64, which i know has no chance of working. Accessing a MAC
> address as a byte array should be endian safe. The shift operation
> should also be endian safe.
> 
> What exactly do you think will behave differently?

Maybe I over-reacted.

I just ran some test programs in userspace on both little and big
endian and they checked out.

Sorry for the false alarm.

I'll apply this, thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get
  2017-01-04 21:27     ` David Miller
@ 2017-01-04 21:45       ` Andrew Lunn
  0 siblings, 0 replies; 6+ messages in thread
From: Andrew Lunn @ 2017-01-04 21:45 UTC (permalink / raw)
  To: David Miller; +Cc: volodymyr.bendiuga, vivien.didelot, f.fainelli, netdev

> Maybe I over-reacted.

I'm happy somebody other than me is thinking about this.

> I just ran some test programs in userspace on both little and big
> endian and they checked out.

Great, thanks for testing.

       Andrew

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-01-04 21:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-04 18:56 [PATCH repost net-next] dsa: mv88e6xxx: Optimise atu_get Andrew Lunn
2017-01-04 21:11 ` David Miller
2017-01-04 21:19   ` Andrew Lunn
2017-01-04 21:27     ` Florian Fainelli
2017-01-04 21:27     ` David Miller
2017-01-04 21:45       ` Andrew Lunn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.