aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mscc/ocelot.h
diff options
context:
space:
mode:
authorGravatar Vladimir Oltean <vladimir.oltean@nxp.com> 2020-10-29 04:27:38 +0200
committerGravatar Jakub Kicinski <kuba@kernel.org> 2020-10-30 18:25:56 -0700
commite5d1f896fd1a347be6e58b873280798233bdf15e (patch)
tree88abb93ab7a1e68631e2615dbb498e85c3da67ef /drivers/net/ethernet/mscc/ocelot.h
parentnet: mscc: ocelot: make entry_type a member of struct ocelot_multicast (diff)
downloadlinux-e5d1f896fd1a347be6e58b873280798233bdf15e.tar.gz
linux-e5d1f896fd1a347be6e58b873280798233bdf15e.tar.bz2
linux-e5d1f896fd1a347be6e58b873280798233bdf15e.zip
net: mscc: ocelot: support L2 multicast entries
There is one main difference in mscc_ocelot between IP multicast and L2 multicast. With IP multicast, destination ports are encoded into the upper bytes of the multicast MAC address. Example: to deliver the address 01:00:5E:11:22:33 to ports 3, 8, and 9, one would need to program the address of 00:03:08:11:22:33 into hardware. Whereas for L2 multicast, the MAC table entry points to a Port Group ID (PGID), and that PGID contains the port mask that the packet will be forwarded to. As to why it is this way, no clue. My guess is that not all port combinations can be supported simultaneously with the limited number of PGIDs, and this was somehow an issue for IP multicast but not for L2 multicast. Anyway. Prior to this change, the raw L2 multicast code was bogus, due to the fact that there wasn't really any way to test it using the bridge code. There were 2 issues: - A multicast PGID was allocated for each MDB entry, but it wasn't in fact programmed to hardware. It was dummy. - In fact we don't want to reserve a multicast PGID for every single MDB entry. That would be odd because we can only have ~60 PGIDs, but thousands of MDB entries. So instead, we want to reserve a multicast PGID for every single port combination for multicast traffic. And since we can have 2 (or more) MDB entries delivered to the same port group (and therefore PGID), we need to reference-count the PGIDs. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/mscc/ocelot.h')
-rw-r--r--drivers/net/ethernet/mscc/ocelot.h16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 7f8b34c49971..291d39d49c4e 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -79,13 +79,27 @@ enum macaccess_entry_type {
ENTRYTYPE_MACv6,
};
+/* A (PGID) port mask structure, encoding the 2^ocelot->num_phys_ports
+ * possibilities of egress port masks for L2 multicast traffic.
+ * For a switch with 9 user ports, there are 512 possible port masks, but the
+ * hardware only has 46 individual PGIDs that it can forward multicast traffic
+ * to. So we need a structure that maps the limited PGID indices to the port
+ * destinations requested by the user for L2 multicast.
+ */
+struct ocelot_pgid {
+ unsigned long ports;
+ int index;
+ refcount_t refcount;
+ struct list_head list;
+};
+
struct ocelot_multicast {
struct list_head list;
enum macaccess_entry_type entry_type;
unsigned char addr[ETH_ALEN];
u16 vid;
u16 ports;
- int pgid;
+ struct ocelot_pgid *pgid;
};
int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,