From: Linus Lüssing Date: Wed, 7 Mar 2018 10:05:41 +0100 Subject: batman-adv: multicast TT fixes and cleanups The first one adds a fix that might potentially result in multicast packet loss once we would enable multicast_mode again. The second one avoids some small but unnecessary overhead. More importantly though, it is supposed to ease further multicast improvements later (e.g. no need for a multicast sending node to determine overlap between WANT_ALL_IPV4/6 flags and TT entries while on fast-path). Signed-off-by: Linus Lüssing diff --git a/batman-adv/patches/0002-batman-adv-Fix-multicast-packet-loss-with-a-single-W.patch b/batman-adv/patches/0002-batman-adv-Fix-multicast-packet-loss-with-a-single-W.patch new file mode 100644 index 0000000000000000000000000000000000000000..138ff7568548d87b9e31efd6c122527102ab2b48 --- /dev/null +++ b/batman-adv/patches/0002-batman-adv-Fix-multicast-packet-loss-with-a-single-W.patch @@ -0,0 +1,44 @@ +From 25b61cec1f45008040d8eb5a5e6c8a4ea027b138 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Linus=20L=C3=BCssing?= +Date: Sun, 4 Mar 2018 13:08:17 +0100 +Subject: [PATCH] batman-adv: Fix multicast packet loss with a single + WANT_ALL_IPV4/6 flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As the kernel doc describes too the code is supposed to skip adding +multicast TT entries if both the WANT_ALL_IPV4 and WANT_ALL_IPV6 flags +are present. + +Unfortunately, the current code even skips adding multicast TT entries +if only either the WANT_ALL_IPV4 or WANT_ALL_IPV6 is present. + +This could lead to IPv6 multicast packet loss if only an IGMP but not an +MLD querier is present for instance or vice versa. + +Fixes: 391b59cdb111 ("batman-adv: Add multicast optimization support for bridged setups") +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann +--- + net/batman-adv/multicast.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c +index 6eaffe50..15a7b314 100644 +--- a/net/batman-adv/multicast.c ++++ b/net/batman-adv/multicast.c +@@ -543,8 +543,8 @@ static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) + bat_priv->mcast.enabled = true; + } + +- return !(mcast_data.flags & +- (BATADV_MCAST_WANT_ALL_IPV4 | BATADV_MCAST_WANT_ALL_IPV6)); ++ return !(mcast_data.flags & BATADV_MCAST_WANT_ALL_IPV4 && ++ mcast_data.flags & BATADV_MCAST_WANT_ALL_IPV6); + } + + /** +-- +2.11.0 + diff --git a/batman-adv/patches/0003-batman-adv-Avoid-redundant-multicast-TT-entries.patch b/batman-adv/patches/0003-batman-adv-Avoid-redundant-multicast-TT-entries.patch new file mode 100644 index 0000000000000000000000000000000000000000..b960052ac63c304454f1988cec76d10ac398d2ca --- /dev/null +++ b/batman-adv/patches/0003-batman-adv-Avoid-redundant-multicast-TT-entries.patch @@ -0,0 +1,139 @@ +From e6a1e766956e66cbc5b2068896a8e55d4e49d894 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Linus=20L=C3=BCssing?= +Date: Sun, 4 Mar 2018 21:02:18 +0100 +Subject: [PATCH] batman-adv: Avoid redundant multicast TT entries +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If a node signals that it wants all traffic for a specific protocol +family then there is no need to announce individual multicast addresses +via TT. + +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann +--- + net/batman-adv/multicast.c | 56 ++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 52 insertions(+), 4 deletions(-) + +diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c +index 15a7b314..17ad1933 100644 +--- a/net/batman-adv/multicast.c ++++ b/net/batman-adv/multicast.c +@@ -102,7 +102,36 @@ static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface) + } + + /** ++ * batadv_mcast_addr_is_ipv4() - check if multicast MAC is IPv4 ++ * @addr: the MAC address to check ++ * ++ * Return: True, if MAC address is one reserved for IPv4 multicast, false ++ * otherwise. ++ */ ++static bool batadv_mcast_addr_is_ipv4(const u8 *addr) ++{ ++ static const u8 prefix[] = {0x01, 0x00, 0x5E}; ++ ++ return memcmp(prefix, addr, sizeof(prefix)) == 0; ++} ++ ++/** ++ * batadv_mcast_addr_is_ipv6() - check if multicast MAC is IPv6 ++ * @addr: the MAC address to check ++ * ++ * Return: True, if MAC address is one reserved for IPv6 multicast, false ++ * otherwise. ++ */ ++static bool batadv_mcast_addr_is_ipv6(const u8 *addr) ++{ ++ static const u8 prefix[] = {0x33, 0x33}; ++ ++ return memcmp(prefix, addr, sizeof(prefix)) == 0; ++} ++ ++/** + * batadv_mcast_mla_softif_get() - get softif multicast listeners ++ * @bat_priv: the bat priv with all the soft interface information + * @dev: the device to collect multicast addresses from + * @mcast_list: a list to put found addresses into + * +@@ -119,9 +148,12 @@ static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface) + * Return: -ENOMEM on memory allocation error or the number of + * items added to the mcast_list otherwise. + */ +-static int batadv_mcast_mla_softif_get(struct net_device *dev, ++static int batadv_mcast_mla_softif_get(struct batadv_priv *bat_priv, ++ struct net_device *dev, + struct hlist_head *mcast_list) + { ++ bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4; ++ bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6; + struct net_device *bridge = batadv_mcast_get_bridge(dev); + struct netdev_hw_addr *mc_list_entry; + struct batadv_hw_addr *new; +@@ -129,6 +161,12 @@ static int batadv_mcast_mla_softif_get(struct net_device *dev, + + netif_addr_lock_bh(bridge ? bridge : dev); + netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) { ++ if (all_ipv4 && batadv_mcast_addr_is_ipv4(mc_list_entry->addr)) ++ continue; ++ ++ if (all_ipv6 && batadv_mcast_addr_is_ipv6(mc_list_entry->addr)) ++ continue; ++ + new = kmalloc(sizeof(*new), GFP_ATOMIC); + if (!new) { + ret = -ENOMEM; +@@ -193,6 +231,7 @@ static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src) + + /** + * batadv_mcast_mla_bridge_get() - get bridged-in multicast listeners ++ * @bat_priv: the bat priv with all the soft interface information + * @dev: a bridge slave whose bridge to collect multicast addresses from + * @mcast_list: a list to put found addresses into + * +@@ -204,10 +243,13 @@ static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src) + * Return: -ENOMEM on memory allocation error or the number of + * items added to the mcast_list otherwise. + */ +-static int batadv_mcast_mla_bridge_get(struct net_device *dev, ++static int batadv_mcast_mla_bridge_get(struct batadv_priv *bat_priv, ++ struct net_device *dev, + struct hlist_head *mcast_list) + { + struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list); ++ bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4; ++ bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6; + struct br_ip_list *br_ip_entry, *tmp; + struct batadv_hw_addr *new; + u8 mcast_addr[ETH_ALEN]; +@@ -221,6 +263,12 @@ static int batadv_mcast_mla_bridge_get(struct net_device *dev, + goto out; + + list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) { ++ if (all_ipv4 && br_ip_entry->addr.proto == htons(ETH_P_IP)) ++ continue; ++ ++ if (all_ipv6 && br_ip_entry->addr.proto == htons(ETH_P_IPV6)) ++ continue; ++ + batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr); + if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list)) + continue; +@@ -568,11 +616,11 @@ static void __batadv_mcast_mla_update(struct batadv_priv *bat_priv) + if (!batadv_mcast_mla_tvlv_update(bat_priv)) + goto update; + +- ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list); ++ ret = batadv_mcast_mla_softif_get(bat_priv, soft_iface, &mcast_list); + if (ret < 0) + goto out; + +- ret = batadv_mcast_mla_bridge_get(soft_iface, &mcast_list); ++ ret = batadv_mcast_mla_bridge_get(bat_priv, soft_iface, &mcast_list); + if (ret < 0) + goto out; + +-- +2.11.0 +