net: hsr: Add support for MC filtering at the slave device
authorMurali Karicheri <m-karicheri2@ti.com>
Tue, 21 Nov 2023 05:37:53 +0000 (11:07 +0530)
committerDavid S. Miller <davem@davemloft.net>
Wed, 22 Nov 2023 10:51:32 +0000 (10:51 +0000)
When MC (multicast) list is updated by the networking layer due to a
user command and as well as when allmulti flag is set, it needs to be
passed to the enslaved Ethernet devices. This patch allows this
to happen by implementing ndo_change_rx_flags() and ndo_set_rx_mode()
API calls that in turns pass it to the slave devices using
existing API calls.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/hsr/hsr_device.c

index 306f942c3b28af226435c34ff1c68b7eb31d77e0..7ceb9ac6e7309372a5931f92c9b8adcc390af5f4 100644 (file)
@@ -173,7 +173,24 @@ static int hsr_dev_open(struct net_device *dev)
 
 static int hsr_dev_close(struct net_device *dev)
 {
-       /* Nothing to do here. */
+       struct hsr_port *port;
+       struct hsr_priv *hsr;
+
+       hsr = netdev_priv(dev);
+       hsr_for_each_port(hsr, port) {
+               if (port->type == HSR_PT_MASTER)
+                       continue;
+               switch (port->type) {
+               case HSR_PT_SLAVE_A:
+               case HSR_PT_SLAVE_B:
+                       dev_uc_unsync(port->dev, dev);
+                       dev_mc_unsync(port->dev, dev);
+                       break;
+               default:
+                       break;
+               }
+       }
+
        return 0;
 }
 
@@ -404,12 +421,60 @@ void hsr_del_ports(struct hsr_priv *hsr)
                hsr_del_port(port);
 }
 
+static void hsr_set_rx_mode(struct net_device *dev)
+{
+       struct hsr_port *port;
+       struct hsr_priv *hsr;
+
+       hsr = netdev_priv(dev);
+
+       hsr_for_each_port(hsr, port) {
+               if (port->type == HSR_PT_MASTER)
+                       continue;
+               switch (port->type) {
+               case HSR_PT_SLAVE_A:
+               case HSR_PT_SLAVE_B:
+                       dev_mc_sync_multiple(port->dev, dev);
+                       dev_uc_sync_multiple(port->dev, dev);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+static void hsr_change_rx_flags(struct net_device *dev, int change)
+{
+       struct hsr_port *port;
+       struct hsr_priv *hsr;
+
+       hsr = netdev_priv(dev);
+
+       hsr_for_each_port(hsr, port) {
+               if (port->type == HSR_PT_MASTER)
+                       continue;
+               switch (port->type) {
+               case HSR_PT_SLAVE_A:
+               case HSR_PT_SLAVE_B:
+                       if (change & IFF_ALLMULTI)
+                               dev_set_allmulti(port->dev,
+                                                dev->flags &
+                                                IFF_ALLMULTI ? 1 : -1);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
 static const struct net_device_ops hsr_device_ops = {
        .ndo_change_mtu = hsr_dev_change_mtu,
        .ndo_open = hsr_dev_open,
        .ndo_stop = hsr_dev_close,
        .ndo_start_xmit = hsr_dev_xmit,
+       .ndo_change_rx_flags = hsr_change_rx_flags,
        .ndo_fix_features = hsr_fix_features,
+       .ndo_set_rx_mode = hsr_set_rx_mode,
 };
 
 static struct device_type hsr_type = {