netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] improve multicast join group performance
@ 2024-10-07 14:17 Jonas Rebmann
  2024-10-07 14:17 ` [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash Jonas Rebmann
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Jonas Rebmann @ 2024-10-07 14:17 UTC (permalink / raw)
  To: David S. Miller, David Ahern, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Madalin Bucur, Sean Anderson
  Cc: netdev, linux-kernel, kernel, Jonas Rebmann

This series seeks to improve performance on updating igmp group
memberships such as with IP_ADD_MEMBERSHIP or MCAST_JOIN_SOURCE_GROUP.

Our use case was to add 2000 multicast memberships on a TQMLS1046A which
took about 3.6 seconds for the membership additions alone. Our userspace
reproducer tool was instrumented to log runtimes of the individual
setsockopt invocations which clearly indicated quadratic complexity of
setting up the membership with regard to the total number of multicast
groups to be joined. We used perf to locate the hotspots and
subsequently optimized the most costly sections of code.

This series includes a patch to Linux igmp handling as well as a patch
to the DPAA/Freescale driver. With both patches applied, our memberships can
be set up in only about 87 miliseconds, which corresponds to a speedup
of around 40.

While we have acheived practically linear run-time complexity on the
kernel side, a small quadratic factor remains in parts of the freescale
driver code which we haven't yet optimized. We have by now payed little
attention to the optimization potential in dropping group memberships,
yet the dpaa patch applies to joining and leaving groups alike.

Overall, this patch series brings great improvements in use cases
involving large numbers of multicast groups, particularly when using the
fsl_dpa driver, without noteworthy drawbacks in other scenarios.

Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
Jonas Rebmann (2):
      net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash
      net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode()

 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c   | 20 +++++++++--
 drivers/net/ethernet/freescale/fman/fman_dtsec.c |  1 -
 drivers/net/ethernet/freescale/fman/fman_memac.c |  1 -
 drivers/net/ethernet/freescale/fman/fman_tgec.c  |  1 -
 drivers/net/ethernet/freescale/fman/mac.c        | 42 ------------------------
 drivers/net/ethernet/freescale/fman/mac.h        |  2 --
 net/ipv4/igmp.c                                  | 26 ++++++++++++---
 7 files changed, 39 insertions(+), 54 deletions(-)
---
base-commit: 8b641b5e4c782464c8818a71b443eeef8984bf34
change-id: 20241007-igmp-speedup-2ca0c7b9189d

Best regards,
-- 
Jonas Rebmann <jre@pengutronix.de>


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

* [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash
  2024-10-07 14:17 [PATCH 0/2] improve multicast join group performance Jonas Rebmann
@ 2024-10-07 14:17 ` Jonas Rebmann
  2024-10-07 19:06   ` Eric Dumazet
  2024-10-07 14:17 ` [PATCH 2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode() Jonas Rebmann
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Jonas Rebmann @ 2024-10-07 14:17 UTC (permalink / raw)
  To: David S. Miller, David Ahern, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Madalin Bucur, Sean Anderson
  Cc: netdev, linux-kernel, kernel, Jonas Rebmann

The runtime cost of joining a single multicast group in the current
implementation of ____ip_mc_inc_group grows linearly with the number of
existing memberships. This is caused by the linear search for an
existing group record in the multicast address list.

This linear complexity results in quadratic complexity when successively
adding memberships, which becomes a performance bottleneck when setting
up large numbers of multicast memberships.

If available, use the existing multicast hash map mc_hash to quickly
search for an existing group membership record. This leads to
near-constant complexity on the addition of a new multicast record,
significantly improving performance for workloads involving many
multicast memberships.

On profiling with a loopback device, this patch presented a speedup of
around 6 when successively setting up 2000 multicast groups using
setsockopt without measurable drawbacks on smaller numbers of
multicast groups.

Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
 net/ipv4/igmp.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 9bf09de6a2e77c32f5eed565db8fd6c14bc7ea86..6a238398acc9d5684ec3d6305ef2a74834f5a3b3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1437,16 +1437,32 @@ static void ip_mc_hash_remove(struct in_device *in_dev,
 static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
 				unsigned int mode, gfp_t gfp)
 {
+	struct ip_mc_list __rcu **mc_hash;
 	struct ip_mc_list *im;
 
 	ASSERT_RTNL();
 
-	for_each_pmc_rtnl(in_dev, im) {
-		if (im->multiaddr == addr) {
-			im->users++;
-			ip_mc_add_src(in_dev, &addr, mode, 0, NULL, 0);
-			goto out;
+	mc_hash = rtnl_dereference(in_dev->mc_hash);
+	if (mc_hash) {
+		u32 hash = hash_32((__force u32)addr, MC_HASH_SZ_LOG);
+
+		for (im = rtnl_dereference(mc_hash[hash]);
+		     im;
+		     im = rtnl_dereference(im->next_hash)) {
+			if (im->multiaddr == addr)
+				break;
 		}
+	} else {
+		for_each_pmc_rtnl(in_dev, im) {
+			if (im->multiaddr == addr)
+				break;
+		}
+	}
+
+	if  (im) {
+		im->users++;
+		ip_mc_add_src(in_dev, &addr, mode, 0, NULL, 0);
+		goto out;
 	}
 
 	im = kzalloc(sizeof(*im), gfp);

-- 
2.39.5


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

* [PATCH 2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode()
  2024-10-07 14:17 [PATCH 0/2] improve multicast join group performance Jonas Rebmann
  2024-10-07 14:17 ` [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash Jonas Rebmann
@ 2024-10-07 14:17 ` Jonas Rebmann
  2024-10-07 14:50   ` Sean Anderson
  2024-10-07 14:30 ` [PATCH 0/2] improve multicast join group performance Jonas Rebmann
  2024-10-09 12:00 ` patchwork-bot+netdevbpf
  3 siblings, 1 reply; 8+ messages in thread
From: Jonas Rebmann @ 2024-10-07 14:17 UTC (permalink / raw)
  To: David S. Miller, David Ahern, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Madalin Bucur, Sean Anderson
  Cc: netdev, linux-kernel, kernel, Jonas Rebmann

The original driver first unregisters then re-registers all multicast
addresses in the struct net_device_ops::ndo_set_rx_mode() callback.

As the networking stack calls ndo_set_rx_mode() if a single multicast
address change occurs, a significant amount of time may be used to first
unregister and then re-register unchanged multicast addresses. This
leads to performance issues when tracking large numbers of multicast
addresses.

Replace the unregister and register loop and the hand crafted
mc_addr_list list handling with __dev_mc_sync(), to only update entries
which have changed.

On profiling with an fsl_dpa NIC, this patch presented a speedup of
around 40 when successively setting up 2000 multicast groups using
setsockopt(), without drawbacks on smaller numbers of multicast groups.

Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c   | 20 +++++++++--
 drivers/net/ethernet/freescale/fman/fman_dtsec.c |  1 -
 drivers/net/ethernet/freescale/fman/fman_memac.c |  1 -
 drivers/net/ethernet/freescale/fman/fman_tgec.c  |  1 -
 drivers/net/ethernet/freescale/fman/mac.c        | 42 ------------------------
 drivers/net/ethernet/freescale/fman/mac.h        |  2 --
 6 files changed, 18 insertions(+), 49 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 6b9b6d72db98c22b9c104833b3c8c675931fd1aa..ac06b01fe93401b0416cd6a654bac2cb40ce12aa 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -463,6 +463,22 @@ static int dpaa_set_mac_address(struct net_device *net_dev, void *addr)
 	return 0;
 }
 
+static int dpaa_addr_sync(struct net_device *net_dev, const u8 *addr)
+{
+	const struct dpaa_priv *priv = netdev_priv(net_dev);
+
+	return priv->mac_dev->add_hash_mac_addr(priv->mac_dev->fman_mac,
+						(enet_addr_t *)addr);
+}
+
+static int dpaa_addr_unsync(struct net_device *net_dev, const u8 *addr)
+{
+	const struct dpaa_priv *priv = netdev_priv(net_dev);
+
+	return priv->mac_dev->remove_hash_mac_addr(priv->mac_dev->fman_mac,
+						   (enet_addr_t *)addr);
+}
+
 static void dpaa_set_rx_mode(struct net_device *net_dev)
 {
 	const struct dpaa_priv	*priv;
@@ -490,9 +506,9 @@ static void dpaa_set_rx_mode(struct net_device *net_dev)
 				  err);
 	}
 
-	err = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
+	err = __dev_mc_sync(net_dev, dpaa_addr_sync, dpaa_addr_unsync);
 	if (err < 0)
-		netif_err(priv, drv, net_dev, "mac_dev->set_multi() = %d\n",
+		netif_err(priv, drv, net_dev, "dpaa_addr_sync() = %d\n",
 			  err);
 }
 
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 3088da7adf0f846744079107f7f72fea74114f4a..85617bb94959f3789d75766bce8f3e11a7b321d5 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1415,7 +1415,6 @@ int dtsec_initialization(struct mac_device *mac_dev,
 	mac_dev->set_exception		= dtsec_set_exception;
 	mac_dev->set_allmulti		= dtsec_set_allmulti;
 	mac_dev->set_tstamp		= dtsec_set_tstamp;
-	mac_dev->set_multi		= fman_set_multi;
 	mac_dev->enable			= dtsec_enable;
 	mac_dev->disable		= dtsec_disable;
 
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 796e6f4e583d18be6069f78af15fbedf9557378e..3925441143fac9eecc40ea45d05f36be63b16a78 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -1087,7 +1087,6 @@ int memac_initialization(struct mac_device *mac_dev,
 	mac_dev->set_exception		= memac_set_exception;
 	mac_dev->set_allmulti		= memac_set_allmulti;
 	mac_dev->set_tstamp		= memac_set_tstamp;
-	mac_dev->set_multi		= fman_set_multi;
 	mac_dev->enable			= memac_enable;
 	mac_dev->disable		= memac_disable;
 
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index c2261d26db5b9374a5e52bac41c25ed8831f4822..fecfca6eba03e571cfb569b8aad20dc3fa8dc1c7 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -771,7 +771,6 @@ int tgec_initialization(struct mac_device *mac_dev,
 	mac_dev->set_exception		= tgec_set_exception;
 	mac_dev->set_allmulti		= tgec_set_allmulti;
 	mac_dev->set_tstamp		= tgec_set_tstamp;
-	mac_dev->set_multi		= fman_set_multi;
 	mac_dev->enable			= tgec_enable;
 	mac_dev->disable		= tgec_disable;
 
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 43f4ad29eadd495ce7f4861b3e635e22379ddc72..974d2e7e131c087ddbb41dcb906f6144a150db46 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -32,8 +32,6 @@ MODULE_DESCRIPTION("FSL FMan MAC API based driver");
 struct mac_priv_s {
 	u8				cell_index;
 	struct fman			*fman;
-	/* List of multicast addresses */
-	struct list_head		mc_addr_list;
 	struct platform_device		*eth_dev;
 	u16				speed;
 };
@@ -57,44 +55,6 @@ static void mac_exception(struct mac_device *mac_dev,
 		__func__, ex);
 }
 
-int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
-{
-	struct mac_priv_s	*priv;
-	struct mac_address	*old_addr, *tmp;
-	struct netdev_hw_addr	*ha;
-	int			err;
-	enet_addr_t		*addr;
-
-	priv = mac_dev->priv;
-
-	/* Clear previous address list */
-	list_for_each_entry_safe(old_addr, tmp, &priv->mc_addr_list, list) {
-		addr = (enet_addr_t *)old_addr->addr;
-		err = mac_dev->remove_hash_mac_addr(mac_dev->fman_mac, addr);
-		if (err < 0)
-			return err;
-
-		list_del(&old_addr->list);
-		kfree(old_addr);
-	}
-
-	/* Add all the addresses from the new list */
-	netdev_for_each_mc_addr(ha, net_dev) {
-		addr = (enet_addr_t *)ha->addr;
-		err = mac_dev->add_hash_mac_addr(mac_dev->fman_mac, addr);
-		if (err < 0)
-			return err;
-
-		tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
-		if (!tmp)
-			return -ENOMEM;
-
-		ether_addr_copy(tmp->addr, ha->addr);
-		list_add(&tmp->list, &priv->mc_addr_list);
-	}
-	return 0;
-}
-
 static DEFINE_MUTEX(eth_lock);
 
 static struct platform_device *dpaa_eth_add_device(int fman_id,
@@ -181,8 +141,6 @@ static int mac_probe(struct platform_device *_of_dev)
 	mac_dev->priv = priv;
 	mac_dev->dev = dev;
 
-	INIT_LIST_HEAD(&priv->mc_addr_list);
-
 	/* Get the FM node */
 	dev_node = of_get_parent(mac_node);
 	if (!dev_node) {
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index fe747915cc73792b66d8bfe4339894476fc841af..be9d48aad5ef16d6826e0dc3c93b8c456cdfa925 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -39,8 +39,6 @@ struct mac_device {
 	int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr);
 	int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
 	int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
-	int (*set_multi)(struct net_device *net_dev,
-			 struct mac_device *mac_dev);
 	int (*set_exception)(struct fman_mac *mac_dev,
 			     enum fman_mac_exceptions exception, bool enable);
 	int (*add_hash_mac_addr)(struct fman_mac *mac_dev,

-- 
2.39.5


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

* Re: [PATCH 0/2] improve multicast join group performance
  2024-10-07 14:17 [PATCH 0/2] improve multicast join group performance Jonas Rebmann
  2024-10-07 14:17 ` [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash Jonas Rebmann
  2024-10-07 14:17 ` [PATCH 2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode() Jonas Rebmann
@ 2024-10-07 14:30 ` Jonas Rebmann
  2024-10-07 15:30   ` Jakub Kicinski
  2024-10-09 12:00 ` patchwork-bot+netdevbpf
  3 siblings, 1 reply; 8+ messages in thread
From: Jonas Rebmann @ 2024-10-07 14:30 UTC (permalink / raw)
  To: David S. Miller, David Ahern, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Madalin Bucur, Sean Anderson
  Cc: netdev, linux-kernel, kernel

On 07/10/2024 16.17, Jonas Rebmann wrote:
> This series seeks to improve performance on updating igmp group
> memberships such as with IP_ADD_MEMBERSHIP or MCAST_JOIN_SOURCE_GROUP.

Sorry, I forgot: This should have been tagged for net-next. Will be 
fixed in v2.

Regards,
Jonas

-- 
Pengutronix e.K.                           | Jonas Rebmann               |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-9    |

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

* Re: [PATCH 2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode()
  2024-10-07 14:17 ` [PATCH 2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode() Jonas Rebmann
@ 2024-10-07 14:50   ` Sean Anderson
  0 siblings, 0 replies; 8+ messages in thread
From: Sean Anderson @ 2024-10-07 14:50 UTC (permalink / raw)
  To: Jonas Rebmann, David S. Miller, David Ahern, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Madalin Bucur
  Cc: netdev, linux-kernel, kernel

On 10/7/24 10:17, Jonas Rebmann wrote:
> The original driver first unregisters then re-registers all multicast
> addresses in the struct net_device_ops::ndo_set_rx_mode() callback.
>
> As the networking stack calls ndo_set_rx_mode() if a single multicast
> address change occurs, a significant amount of time may be used to first
> unregister and then re-register unchanged multicast addresses. This
> leads to performance issues when tracking large numbers of multicast
> addresses.
>
> Replace the unregister and register loop and the hand crafted
> mc_addr_list list handling with __dev_mc_sync(), to only update entries
> which have changed.
>
> On profiling with an fsl_dpa NIC, this patch presented a speedup of
> around 40 when successively setting up 2000 multicast groups using
> setsockopt(), without drawbacks on smaller numbers of multicast groups.
>
> Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
> ---
>  drivers/net/ethernet/freescale/dpaa/dpaa_eth.c   | 20 +++++++++--
>  drivers/net/ethernet/freescale/fman/fman_dtsec.c |  1 -
>  drivers/net/ethernet/freescale/fman/fman_memac.c |  1 -
>  drivers/net/ethernet/freescale/fman/fman_tgec.c  |  1 -
>  drivers/net/ethernet/freescale/fman/mac.c        | 42 ------------------------
>  drivers/net/ethernet/freescale/fman/mac.h        |  2 --
>  6 files changed, 18 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index 6b9b6d72db98c22b9c104833b3c8c675931fd1aa..ac06b01fe93401b0416cd6a654bac2cb40ce12aa 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -463,6 +463,22 @@ static int dpaa_set_mac_address(struct net_device *net_dev, void *addr)
>         return 0;
>  }
>
> +static int dpaa_addr_sync(struct net_device *net_dev, const u8 *addr)
> +{
> +       const struct dpaa_priv *priv = netdev_priv(net_dev);
> +
> +       return priv->mac_dev->add_hash_mac_addr(priv->mac_dev->fman_mac,
> +                                               (enet_addr_t *)addr);
> +}
> +
> +static int dpaa_addr_unsync(struct net_device *net_dev, const u8 *addr)
> +{
> +       const struct dpaa_priv *priv = netdev_priv(net_dev);
> +
> +       return priv->mac_dev->remove_hash_mac_addr(priv->mac_dev->fman_mac,
> +                                                  (enet_addr_t *)addr);
> +}
> +
>  static void dpaa_set_rx_mode(struct net_device *net_dev)
>  {
>         const struct dpaa_priv  *priv;
> @@ -490,9 +506,9 @@ static void dpaa_set_rx_mode(struct net_device *net_dev)
>                                   err);
>         }
>
> -       err = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
> +       err = __dev_mc_sync(net_dev, dpaa_addr_sync, dpaa_addr_unsync);
>         if (err < 0)
> -               netif_err(priv, drv, net_dev, "mac_dev->set_multi() = %d\n",
> +               netif_err(priv, drv, net_dev, "dpaa_addr_sync() = %d\n",
>                           err);
>  }
>
> diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
> index 3088da7adf0f846744079107f7f72fea74114f4a..85617bb94959f3789d75766bce8f3e11a7b321d5 100644
> --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
> +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
> @@ -1415,7 +1415,6 @@ int dtsec_initialization(struct mac_device *mac_dev,
>         mac_dev->set_exception          = dtsec_set_exception;
>         mac_dev->set_allmulti           = dtsec_set_allmulti;
>         mac_dev->set_tstamp             = dtsec_set_tstamp;
> -       mac_dev->set_multi              = fman_set_multi;
>         mac_dev->enable                 = dtsec_enable;
>         mac_dev->disable                = dtsec_disable;
>
> diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
> index 796e6f4e583d18be6069f78af15fbedf9557378e..3925441143fac9eecc40ea45d05f36be63b16a78 100644
> --- a/drivers/net/ethernet/freescale/fman/fman_memac.c
> +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
> @@ -1087,7 +1087,6 @@ int memac_initialization(struct mac_device *mac_dev,
>         mac_dev->set_exception          = memac_set_exception;
>         mac_dev->set_allmulti           = memac_set_allmulti;
>         mac_dev->set_tstamp             = memac_set_tstamp;
> -       mac_dev->set_multi              = fman_set_multi;
>         mac_dev->enable                 = memac_enable;
>         mac_dev->disable                = memac_disable;
>
> diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
> index c2261d26db5b9374a5e52bac41c25ed8831f4822..fecfca6eba03e571cfb569b8aad20dc3fa8dc1c7 100644
> --- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
> +++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
> @@ -771,7 +771,6 @@ int tgec_initialization(struct mac_device *mac_dev,
>         mac_dev->set_exception          = tgec_set_exception;
>         mac_dev->set_allmulti           = tgec_set_allmulti;
>         mac_dev->set_tstamp             = tgec_set_tstamp;
> -       mac_dev->set_multi              = fman_set_multi;
>         mac_dev->enable                 = tgec_enable;
>         mac_dev->disable                = tgec_disable;
>
> diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
> index 43f4ad29eadd495ce7f4861b3e635e22379ddc72..974d2e7e131c087ddbb41dcb906f6144a150db46 100644
> --- a/drivers/net/ethernet/freescale/fman/mac.c
> +++ b/drivers/net/ethernet/freescale/fman/mac.c
> @@ -32,8 +32,6 @@ MODULE_DESCRIPTION("FSL FMan MAC API based driver");
>  struct mac_priv_s {
>         u8                              cell_index;
>         struct fman                     *fman;
> -       /* List of multicast addresses */
> -       struct list_head                mc_addr_list;
>         struct platform_device          *eth_dev;
>         u16                             speed;
>  };
> @@ -57,44 +55,6 @@ static void mac_exception(struct mac_device *mac_dev,
>                 __func__, ex);
>  }
>
> -int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
> -{
> -       struct mac_priv_s       *priv;
> -       struct mac_address      *old_addr, *tmp;
> -       struct netdev_hw_addr   *ha;
> -       int                     err;
> -       enet_addr_t             *addr;
> -
> -       priv = mac_dev->priv;
> -
> -       /* Clear previous address list */
> -       list_for_each_entry_safe(old_addr, tmp, &priv->mc_addr_list, list) {
> -               addr = (enet_addr_t *)old_addr->addr;
> -               err = mac_dev->remove_hash_mac_addr(mac_dev->fman_mac, addr);
> -               if (err < 0)
> -                       return err;
> -
> -               list_del(&old_addr->list);
> -               kfree(old_addr);
> -       }
> -
> -       /* Add all the addresses from the new list */
> -       netdev_for_each_mc_addr(ha, net_dev) {
> -               addr = (enet_addr_t *)ha->addr;
> -               err = mac_dev->add_hash_mac_addr(mac_dev->fman_mac, addr);
> -               if (err < 0)
> -                       return err;
> -
> -               tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
> -               if (!tmp)
> -                       return -ENOMEM;
> -
> -               ether_addr_copy(tmp->addr, ha->addr);
> -               list_add(&tmp->list, &priv->mc_addr_list);
> -       }
> -       return 0;
> -}
> -
>  static DEFINE_MUTEX(eth_lock);
>
>  static struct platform_device *dpaa_eth_add_device(int fman_id,
> @@ -181,8 +141,6 @@ static int mac_probe(struct platform_device *_of_dev)
>         mac_dev->priv = priv;
>         mac_dev->dev = dev;
>
> -       INIT_LIST_HEAD(&priv->mc_addr_list);
> -
>         /* Get the FM node */
>         dev_node = of_get_parent(mac_node);
>         if (!dev_node) {
> diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
> index fe747915cc73792b66d8bfe4339894476fc841af..be9d48aad5ef16d6826e0dc3c93b8c456cdfa925 100644
> --- a/drivers/net/ethernet/freescale/fman/mac.h
> +++ b/drivers/net/ethernet/freescale/fman/mac.h
> @@ -39,8 +39,6 @@ struct mac_device {
>         int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr);
>         int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
>         int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
> -       int (*set_multi)(struct net_device *net_dev,
> -                        struct mac_device *mac_dev);
>         int (*set_exception)(struct fman_mac *mac_dev,
>                              enum fman_mac_exceptions exception, bool enable);
>         int (*add_hash_mac_addr)(struct fman_mac *mac_dev,
>
> --
> 2.39.5
>

Reviewed-by: Sean Anderson <sean.anderson@seco.com>

[EmbeddedWorldNorthAmerica2024, SECO SpA]<https://s2.goeshow.com/nmna/ew/2024/registration_form.cfm>

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

* Re: [PATCH 0/2] improve multicast join group performance
  2024-10-07 14:30 ` [PATCH 0/2] improve multicast join group performance Jonas Rebmann
@ 2024-10-07 15:30   ` Jakub Kicinski
  0 siblings, 0 replies; 8+ messages in thread
From: Jakub Kicinski @ 2024-10-07 15:30 UTC (permalink / raw)
  To: Jonas Rebmann
  Cc: David S. Miller, David Ahern, Eric Dumazet, Paolo Abeni,
	Madalin Bucur, Sean Anderson, netdev, linux-kernel, kernel

On Mon, 7 Oct 2024 16:30:47 +0200 Jonas Rebmann wrote:
> On 07/10/2024 16.17, Jonas Rebmann wrote:
> > This series seeks to improve performance on updating igmp group
> > memberships such as with IP_ADD_MEMBERSHIP or MCAST_JOIN_SOURCE_GROUP.  
> 
> Sorry, I forgot: This should have been tagged for net-next. Will be 
> fixed in v2.

No need to repost just for that.

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

* Re: [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash
  2024-10-07 14:17 ` [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash Jonas Rebmann
@ 2024-10-07 19:06   ` Eric Dumazet
  0 siblings, 0 replies; 8+ messages in thread
From: Eric Dumazet @ 2024-10-07 19:06 UTC (permalink / raw)
  To: Jonas Rebmann
  Cc: David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
	Madalin Bucur, Sean Anderson, netdev, linux-kernel, kernel

On Mon, Oct 7, 2024 at 4:17 PM Jonas Rebmann <jre@pengutronix.de> wrote:
>
> The runtime cost of joining a single multicast group in the current
> implementation of ____ip_mc_inc_group grows linearly with the number of
> existing memberships. This is caused by the linear search for an
> existing group record in the multicast address list.
>
> This linear complexity results in quadratic complexity when successively
> adding memberships, which becomes a performance bottleneck when setting
> up large numbers of multicast memberships.
>
> If available, use the existing multicast hash map mc_hash to quickly
> search for an existing group membership record. This leads to
> near-constant complexity on the addition of a new multicast record,
> significantly improving performance for workloads involving many
> multicast memberships.
>
> On profiling with a loopback device, this patch presented a speedup of
> around 6 when successively setting up 2000 multicast groups using
> setsockopt without measurable drawbacks on smaller numbers of
> multicast groups.
>
> Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
> ---

Reviewed-by: Eric Dumazet <edumazet@google.com>

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

* Re: [PATCH 0/2] improve multicast join group performance
  2024-10-07 14:17 [PATCH 0/2] improve multicast join group performance Jonas Rebmann
                   ` (2 preceding siblings ...)
  2024-10-07 14:30 ` [PATCH 0/2] improve multicast join group performance Jonas Rebmann
@ 2024-10-09 12:00 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-10-09 12:00 UTC (permalink / raw)
  To: Jonas Rebmann
  Cc: davem, dsahern, edumazet, kuba, pabeni, madalin.bucur,
	sean.anderson, netdev, linux-kernel, kernel

Hello:

This series was applied to netdev/net-next.git (main)
by David S. Miller <davem@davemloft.net>:

On Mon, 07 Oct 2024 16:17:10 +0200 you wrote:
> This series seeks to improve performance on updating igmp group
> memberships such as with IP_ADD_MEMBERSHIP or MCAST_JOIN_SOURCE_GROUP.
> 
> Our use case was to add 2000 multicast memberships on a TQMLS1046A which
> took about 3.6 seconds for the membership additions alone. Our userspace
> reproducer tool was instrumented to log runtimes of the individual
> setsockopt invocations which clearly indicated quadratic complexity of
> setting up the membership with regard to the total number of multicast
> groups to be joined. We used perf to locate the hotspots and
> subsequently optimized the most costly sections of code.
> 
> [...]

Here is the summary with links:
  - [1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash
    https://git.kernel.org/netdev/net-next/c/69a3272d787c
  - [2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode()
    https://git.kernel.org/netdev/net-next/c/298f70b37144

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2024-10-09 12:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-07 14:17 [PATCH 0/2] improve multicast join group performance Jonas Rebmann
2024-10-07 14:17 ` [PATCH 1/2] net: ipv4: igmp: optimize ____ip_mc_inc_group() using mc_hash Jonas Rebmann
2024-10-07 19:06   ` Eric Dumazet
2024-10-07 14:17 ` [PATCH 2/2] net: dpaa: use __dev_mc_sync in dpaa_set_rx_mode() Jonas Rebmann
2024-10-07 14:50   ` Sean Anderson
2024-10-07 14:30 ` [PATCH 0/2] improve multicast join group performance Jonas Rebmann
2024-10-07 15:30   ` Jakub Kicinski
2024-10-09 12:00 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).