Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: add cross-chip multicast support

Similarly to how cross-chip VLAN works, define a bitmap of multicast
group members for a switch, now including its DSA ports, so that
multicast traffic can be sent to all switches of the fabric.

A switch may drop the frames if no user port is a member.

This brings support for multicast in a multi-chip environment.
As of now, all switches of the fabric must support the multicast
operations in order to program a single fabric port.

Reported-by: Jason Cobham <jcobham@questertangent.com>
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Tested-by: Jason Cobham <jcobham@questertangent.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vivien Didelot and committed by
David S. Miller
a1a6b7ea 6a2fb0e9

+20 -10
+20 -10
net/dsa/switch.c
··· 122 122 { 123 123 const struct switchdev_obj_port_mdb *mdb = info->mdb; 124 124 struct switchdev_trans *trans = info->trans; 125 + DECLARE_BITMAP(group, ds->num_ports); 126 + int port, err; 125 127 126 - /* Do not care yet about other switch chips of the fabric */ 127 - if (ds->index != info->sw_index) 128 - return 0; 128 + /* Build a mask of Multicast group members */ 129 + bitmap_zero(group, ds->num_ports); 130 + if (ds->index == info->sw_index) 131 + set_bit(info->port, group); 132 + for (port = 0; port < ds->num_ports; port++) 133 + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) 134 + set_bit(port, group); 129 135 130 136 if (switchdev_trans_ph_prepare(trans)) { 131 137 if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) 132 138 return -EOPNOTSUPP; 133 139 134 - return ds->ops->port_mdb_prepare(ds, info->port, mdb, trans); 140 + for_each_set_bit(port, group, ds->num_ports) { 141 + err = ds->ops->port_mdb_prepare(ds, port, mdb, trans); 142 + if (err) 143 + return err; 144 + } 135 145 } 136 146 137 - ds->ops->port_mdb_add(ds, info->port, mdb, trans); 147 + for_each_set_bit(port, group, ds->num_ports) 148 + ds->ops->port_mdb_add(ds, port, mdb, trans); 138 149 139 150 return 0; 140 151 } ··· 155 144 { 156 145 const struct switchdev_obj_port_mdb *mdb = info->mdb; 157 146 158 - /* Do not care yet about other switch chips of the fabric */ 159 - if (ds->index != info->sw_index) 160 - return 0; 161 - 162 147 if (!ds->ops->port_mdb_del) 163 148 return -EOPNOTSUPP; 164 149 165 - return ds->ops->port_mdb_del(ds, info->port, mdb); 150 + if (ds->index == info->sw_index) 151 + return ds->ops->port_mdb_del(ds, info->port, mdb); 152 + 153 + return 0; 166 154 } 167 155 168 156 static int dsa_switch_vlan_add(struct dsa_switch *ds,