realtek: fix flooding of unsnoopable multicast addresses
RFC4541, section 2.1.2 says:
Packets with a destination IP (DIP) address in the 224.0.0.X range
which are not IGMP must be forwarded on all ports.
And section 3 says:
In IPv6, the data forwarding rules are more straight forward because
MLD is mandated for addresses with scope 2 (link-scope) or greater.
The only exception is the address FF02::1 which is the all hosts
link-scope address for which MLD messages are never sent. Packets
with the all hosts link-scope address should be forwarded on all
ports.
However, currently when a listener on FF12::1 or FF12:🔢0:1 for
example joins then not only packets to these addresses but also for
FF02::1 won't be flooded to all ports anymore, too. Which violates
RFC4541.
This happens because A): They all map to the same ethernet multicast
address, that is 33:33:00:00:00:01. And B) the VLAN profile L2
unknown MC flood setting will only apply flooding of 33:33:00:00:00:01
if there is no specific listener registered for it.
So to fix this, avoid registering an MDB entry in the switch for
33:33:00:00:00:01 at all.
The downside of this is that FF12::1, FF12:🔢0:1 etc.
will always be flooded, too. However fixing the handling of 224.0.0.X
and FF02::1 and adhering to RFC4541 must have priority to avoid
undesired packetloss, to avoid breaking IPv4/IPv6.
Tested-on: ZyXEL GS1900-24HP v1
Fixes: cde31976e3
("realtek: Add support for Layer 2 Multicast")
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
Link: https://github.com/openwrt/openwrt/pull/18769
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
86a6c550b9
commit
64ad16993d
1 changed files with 41 additions and 0 deletions
|
@ -7,6 +7,15 @@
|
|||
|
||||
#include "rtl83xx.h"
|
||||
|
||||
static const u8 ipv4_ll_mcast_addr_base[ETH_ALEN] =
|
||||
{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
|
||||
static const u8 ipv4_ll_mcast_addr_mask[ETH_ALEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
|
||||
static const u8 ipv6_all_hosts_mcast_addr_base[ETH_ALEN] =
|
||||
{ 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 };
|
||||
static const u8 ipv6_all_hosts_mcast_addr_mask[ETH_ALEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
static void rtl83xx_init_stats(struct rtl838x_switch_priv *priv)
|
||||
|
@ -1752,6 +1761,24 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool rtl83xx_mac_is_unsnoop(const unsigned char *addr)
|
||||
{
|
||||
/*
|
||||
* RFC4541, section 2.1.2.2 + section 3:
|
||||
* Unsnoopable address ranges must always be flooded.
|
||||
*
|
||||
* mapped MAC for 224.0.0.x -> 01:00:5e:00:00:xx
|
||||
* mapped MAC for ff02::1 -> 33:33:00:00:00:01
|
||||
*/
|
||||
if (ether_addr_equal_masked(addr, ipv4_ll_mcast_addr_base,
|
||||
ipv4_ll_mcast_addr_mask) ||
|
||||
ether_addr_equal_masked(addr, ipv6_all_hosts_mcast_addr_base,
|
||||
ipv6_all_hosts_mcast_addr_mask))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
const struct dsa_db db)
|
||||
|
@ -1774,6 +1801,13 @@ static int rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rtl83xx_mac_is_unsnoop(mdb->addr)) {
|
||||
dev_dbg(priv->dev,
|
||||
"%s: %pM might belong to an unsnoopable IP. ignore\n",
|
||||
__func__, mdb->addr);
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
idx = rtl83xx_find_l2_hash_entry(priv, seed, false, &e);
|
||||
|
@ -1847,6 +1881,13 @@ int rtl83xx_port_mdb_del(struct dsa_switch *ds, int port,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (rtl83xx_mac_is_unsnoop(mdb->addr)) {
|
||||
dev_dbg(priv->dev,
|
||||
"%s: %pM might belong to an unsnoopable IP. ignore\n",
|
||||
__func__, mdb->addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
idx = rtl83xx_find_l2_hash_entry(priv, seed, true, &e);
|
||||
|
|
Loading…
Reference in a new issue