diff --git a/patches/packages/routing/0002-batman-adv-mesh-wide-multi-target-multicast-to-unicast-support.patch b/patches/packages/routing/0002-batman-adv-mesh-wide-multi-target-multicast-to-unicast-support.patch new file mode 100644 index 00000000..0d4eaa5e --- /dev/null +++ b/patches/packages/routing/0002-batman-adv-mesh-wide-multi-target-multicast-to-unicast-support.patch @@ -0,0 +1,971 @@ +From: Linus Lüssing +Date: Thu, 29 Mar 2018 20:44:01 +0200 +Subject: batman-adv: mesh-wide, multi-target multicast-to-unicast support + +We already have multicast-to-unicast support between client and node. +And batman-adv has multicast-to-unicast conversion capabilities if there +is only one receiver. Now this patchset adds node-to-node +multicast-to-unicast support to multiple targets as well. + +This should save airtime for ICMPv6 Router Solicitations, for instance. +Here we have multiple targets for the same IPv6 multicast destination +address. However, the number of destination nodes is still rather small +in this case, i.e. all gateways, making multiple unicast transmissions +less costly than flooding a packet through the whole mesh. + +Also, this allows playing with multicast streaming to a limited set of +destination nodes (default setting: 16). + +Also, nearly all nodes should be running a batman-adv version which +was compiled with CONFIG_BATMAN_ADV_MCAST=y (e.g. Gluon v2018.1 or +later) for this feature to take effect. + +Signed-off-by: Linus Lüssing + +diff --git a/batman-adv/files/etc/config/batman-adv b/batman-adv/files/etc/config/batman-adv +index 6e6017a31468c8e595ec13b09e27529f28f3eaec..8a4e881537ca48dc8e611bab9e22918a8dd02fe4 100644 +--- a/batman-adv/files/etc/config/batman-adv ++++ b/batman-adv/files/etc/config/batman-adv +@@ -12,9 +12,11 @@ config 'mesh' 'bat0' + option 'bridge_loop_avoidance' + option 'distributed_arp_table' + option 'multicast_mode' ++ option 'multicast_fanout' + option 'network_coding' + option 'hop_penalty' + option 'isolation_mark' ++ option 'noflood_mark' + + # yet another batX instance + # config 'mesh' 'bat5' +diff --git a/batman-adv/files/lib/batman-adv/config.sh b/batman-adv/files/lib/batman-adv/config.sh +index 3a746a3c0e280b9a01ae67ea27bde65619b77ebc..d45c4009d24d0d2c416d23134aed755bc36b9413 100644 +--- a/batman-adv/files/lib/batman-adv/config.sh ++++ b/batman-adv/files/lib/batman-adv/config.sh +@@ -12,8 +12,8 @@ bat_config() + { + local mesh="$1" + local aggregated_ogms ap_isolation bonding bridge_loop_avoidance distributed_arp_table fragmentation +- local gw_bandwidth gw_mode gw_sel_class isolation_mark hop_penalty multicast_mode network_coding log_level +- local orig_interval ++ local gw_bandwidth gw_mode gw_sel_class isolation_mark hop_penalty multicast_fanout multicast_mode ++ local network_coding noflood_mark log_level orig_interval + + config_get aggregated_ogms "$mesh" aggregated_ogms + config_get ap_isolation "$mesh" ap_isolation +@@ -26,8 +26,10 @@ bat_config() + config_get gw_sel_class "$mesh" gw_sel_class + config_get hop_penalty "$mesh" hop_penalty + config_get isolation_mark "$mesh" isolation_mark ++ config_get multicast_fanout "$mesh" multicast_fanout + config_get multicast_mode "$mesh" multicast_mode + config_get network_coding "$mesh" network_coding ++ config_get noflood_mark "$mesh" noflood_mark + config_get log_level "$mesh" log_level + config_get orig_interval "$mesh" orig_interval + +@@ -44,8 +46,10 @@ bat_config() + [ -n "$gw_sel_class" ] && echo $gw_sel_class > /sys/class/net/$mesh/mesh/gw_sel_class + [ -n "$hop_penalty" ] && echo $hop_penalty > /sys/class/net/$mesh/mesh/hop_penalty + [ -n "$isolation_mark" ] && echo $isolation_mark > /sys/class/net/$mesh/mesh/isolation_mark ++ [ -n "$multicast_fanout" ] && echo $multicast_fanout > /sys/class/net/$mesh/mesh/multicast_fanout 2>&- + [ -n "$multicast_mode" ] && echo $multicast_mode > /sys/class/net/$mesh/mesh/multicast_mode 2>&- + [ -n "$network_coding" ] && echo $network_coding > /sys/class/net/$mesh/mesh/network_coding 2>&- ++ [ -n "$noflood_mark" ] && echo $noflood_mark > /sys/class/net/$mesh/mesh/noflood_mark + [ -n "$log_level" ] && echo $log_level > /sys/class/net/$mesh/mesh/log_level 2>&- + [ -n "$orig_interval" ] && echo $orig_interval > /sys/class/net/$mesh/mesh/orig_interval + } +diff --git a/batman-adv/patches/0024-batman-adv-Avoid-old-nodes-disabling-multicast-optim.patch b/batman-adv/patches/0024-batman-adv-Avoid-old-nodes-disabling-multicast-optim.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..f08b4d665c222a0362cfe6c232bd38d03280e301 +--- /dev/null ++++ b/batman-adv/patches/0024-batman-adv-Avoid-old-nodes-disabling-multicast-optim.patch +@@ -0,0 +1,117 @@ ++From a250a536f3672d354bc3c47adf7d721137673314 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Linus=20L=C3=BCssing?= ++Date: Sat, 24 Mar 2018 23:39:11 +0100 ++Subject: [PATCH] batman-adv: Avoid old nodes disabling multicast optimizations ++ completely ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Instead of disabling multicast optimizations mesh-wide once a node with ++no multicast optimizations capabilities joins the mesh, do the ++following: ++ ++Just insert such nodes into the WANT_ALL_IPV4/IPV6 lists. This is ++sufficient to avoid multicast packet loss to such unsupportive nodes. ++ ++Signed-off-by: Linus Lüssing ++--- ++ net/batman-adv/multicast.c | 29 ++++++----------------------- ++ net/batman-adv/soft-interface.c | 1 - ++ net/batman-adv/types.h | 3 --- ++ 3 files changed, 6 insertions(+), 27 deletions(-) ++ ++diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c ++index a35f597e..86725d79 100644 ++--- a/net/batman-adv/multicast.c +++++ b/net/batman-adv/multicast.c ++@@ -815,9 +815,6 @@ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, ++ if (!atomic_read(&bat_priv->multicast_mode)) ++ return -EINVAL; ++ ++- if (atomic_read(&bat_priv->mcast.num_disabled)) ++- return -EINVAL; ++- ++ switch (ntohs(ethhdr->h_proto)) { ++ case ETH_P_IP: ++ return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb, ++@@ -1183,33 +1180,23 @@ static void batadv_mcast_tvlv_ogm_handler(struct batadv_priv *bat_priv, ++ { ++ bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND); ++ u8 mcast_flags = BATADV_NO_FLAGS; ++- bool orig_initialized; ++ ++ if (orig_mcast_enabled && tvlv_value && ++ tvlv_value_len >= sizeof(mcast_flags)) ++ mcast_flags = *(u8 *)tvlv_value; ++ +++ if (!orig_mcast_enabled) { +++ mcast_flags |= BATADV_MCAST_WANT_ALL_IPV4; +++ mcast_flags |= BATADV_MCAST_WANT_ALL_IPV6; +++ } +++ ++ spin_lock_bh(&orig->mcast_handler_lock); ++- orig_initialized = test_bit(BATADV_ORIG_CAPA_HAS_MCAST, ++- &orig->capa_initialized); ++ ++- /* If mcast support is turned on decrease the disabled mcast node ++- * counter only if we had increased it for this node before. If this ++- * is a completely new orig_node no need to decrease the counter. ++- */ ++ if (orig_mcast_enabled && ++ !test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities)) { ++- if (orig_initialized) ++- atomic_dec(&bat_priv->mcast.num_disabled); ++ set_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities); ++- /* If mcast support is being switched off or if this is an initial ++- * OGM without mcast support then increase the disabled mcast ++- * node counter. ++- */ ++ } else if (!orig_mcast_enabled && ++- (test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities) || ++- !orig_initialized)) { ++- atomic_inc(&bat_priv->mcast.num_disabled); +++ test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities)) { ++ clear_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities); ++ } ++ ++@@ -1595,10 +1582,6 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig) ++ ++ spin_lock_bh(&orig->mcast_handler_lock); ++ ++- if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities) && ++- test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capa_initialized)) ++- atomic_dec(&bat_priv->mcast.num_disabled); ++- ++ batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); ++ batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS); ++ batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS); ++diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c ++index d3f540ba..8fd8d806 100644 ++--- a/net/batman-adv/soft-interface.c +++++ b/net/batman-adv/soft-interface.c ++@@ -809,7 +809,6 @@ static int batadv_softif_init_late(struct net_device *dev) ++ bat_priv->mcast.querier_ipv6.shadowing = false; ++ bat_priv->mcast.flags = BATADV_NO_FLAGS; ++ atomic_set(&bat_priv->multicast_mode, 1); ++- atomic_set(&bat_priv->mcast.num_disabled, 0); ++ atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); ++ atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); ++ atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); ++diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h ++index 476b052a..0174f79e 100644 ++--- a/net/batman-adv/types.h +++++ b/net/batman-adv/types.h ++@@ -1212,9 +1212,6 @@ struct batadv_priv_mcast { ++ /** @bridged: whether the soft interface has a bridge on top */ ++ bool bridged; ++ ++- /** @num_disabled: number of nodes that have no mcast tvlv */ ++- atomic_t num_disabled; ++- ++ /** ++ * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP ++ * traffic ++-- ++2.11.0 ++ +diff --git a/batman-adv/patches/0025-batman-adv-Add-multicast-to-unicast-support-for-mult.patch b/batman-adv/patches/0025-batman-adv-Add-multicast-to-unicast-support-for-mult.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..c0df317107061e8781fa1a1a90eb3b1602aa8f65 +--- /dev/null ++++ b/batman-adv/patches/0025-batman-adv-Add-multicast-to-unicast-support-for-mult.patch +@@ -0,0 +1,497 @@ ++From 8d0866c33c2f0b49bd6faf2cb7b9d935fc969918 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Linus=20L=C3=BCssing?= ++Date: Thu, 1 Mar 2018 02:32:47 +0100 ++Subject: [PATCH] batman-adv: Add multicast-to-unicast support for multiple ++ targets ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++With this patch multicast packets with a limited number of destinations ++(current default: 16) will be split and transmitted by the originator as ++individual unicast transmissions. ++ ++Wifi broadcasts with their low bitrate are still a costly undertaking. ++In a mesh network this cost multiplies with the overall size of the mesh ++network. Therefore using multiple unicast transmissions instead of ++broadcast flooding is almost always less burdensome for the mesh ++network. ++ ++The maximum amount of unicast packets can be configured via the newly ++introduced multicast_fanout parameter. If this limit is exceeded ++distribution will fall back to classic broadcast flooding. ++ ++The multicast-to-unicast conversion is performed on the initial ++multicast sender node and counts on a final destination node, mesh-wide ++basis (and not next hop, neighbor node basis). ++ ++Signed-off-by: Linus Lüssing ++--- ++ Documentation/ABI/testing/sysfs-class-net-mesh | 9 + ++ net/batman-adv/multicast.c | 242 ++++++++++++++++++++++++- ++ net/batman-adv/multicast.h | 18 ++ ++ net/batman-adv/soft-interface.c | 8 +- ++ net/batman-adv/sysfs.c | 3 + ++ net/batman-adv/translation-table.c | 6 +- ++ net/batman-adv/translation-table.h | 4 + ++ net/batman-adv/types.h | 6 + ++ 8 files changed, 290 insertions(+), 6 deletions(-) ++ ++diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh ++index c2b956d4..18734a36 100644 ++--- a/Documentation/ABI/testing/sysfs-class-net-mesh +++++ b/Documentation/ABI/testing/sysfs-class-net-mesh ++@@ -76,6 +76,15 @@ Description: ++ is used to classify clients as "isolated" by the ++ Extended Isolation feature. ++ +++What: /sys/class/net//mesh/multicast_fanout +++Date: Feb 2018 +++Contact: Linus Lüssing +++Description: +++ Defines the maximum number of packet copies that may +++ be generated for a multicast-to-unicast conversion. +++ Once this limit is exceeded distribution will fall +++ back to broadcast. +++ ++ What: /sys/class/net//mesh/multicast_mode ++ Date: Feb 2014 ++ Contact: Linus Lüssing ++diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c ++index 86725d79..4e18ca6c 100644 ++--- a/net/batman-adv/multicast.c +++++ b/net/batman-adv/multicast.c ++@@ -66,6 +66,7 @@ ++ #include "hash.h" ++ #include "log.h" ++ #include "netlink.h" +++#include "send.h" ++ #include "soft-interface.h" ++ #include "translation-table.h" ++ #include "tvlv.h" ++@@ -992,6 +993,7 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ++ int ret, tt_count, ip_count, unsnoop_count, total_count; ++ bool is_unsnoopable = false; ++ struct ethhdr *ethhdr; +++ unsigned int mcast_fanout; ++ ++ ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable); ++ if (ret == -ENOMEM) ++@@ -1025,8 +1027,246 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ++ case 0: ++ return BATADV_FORW_NONE; ++ default: ++- return BATADV_FORW_ALL; +++ mcast_fanout = atomic_read(&bat_priv->multicast_fanout); +++ +++ if (!unsnoop_count && total_count <= mcast_fanout) +++ return BATADV_FORW_SOME; ++ } +++ +++ return BATADV_FORW_ALL; +++} +++ +++/** +++ * batadv_mcast_forw_tt_send() - send a packet to multicast listeners +++ * @bat_priv: the bat priv with all the soft interface information +++ * @skb: the multicast packet to transmit +++ * @vid: the vlan identifier +++ * @limit: number of remaining, maximum transmissions +++ * +++ * Sends copies of a frame with multicast destination to any multicast +++ * listener registered in the translation table. A transmission is performed +++ * via a batman-adv unicast packet for each such destination node. +++ * +++ * Return: NET_XMIT_DROP if limit was reached or on memory allocation failure, +++ * NET_XMIT_SUCCESS otherwise. +++ */ +++static int +++batadv_mcast_forw_tt_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +++ unsigned short vid, unsigned int *limit) +++{ +++ unsigned int limit_tmp = *limit; +++ int ret = NET_XMIT_SUCCESS; +++ struct sk_buff *newskb; +++ +++ struct batadv_tt_orig_list_entry *orig_entry; +++ +++ struct batadv_tt_global_entry *tt_global; +++ const u8 *addr = eth_hdr(skb)->h_dest; +++ +++ tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid); +++ if (!tt_global) +++ goto out; +++ +++ rcu_read_lock(); +++ hlist_for_each_entry_rcu(orig_entry, &tt_global->orig_list, list) { +++ if (!limit_tmp) { +++ ret = NET_XMIT_DROP; +++ break; +++ } +++ +++ newskb = skb_copy(skb, GFP_ATOMIC); +++ if (!newskb) { +++ ret = NET_XMIT_DROP; +++ break; +++ } +++ +++ batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, +++ orig_entry->orig_node, vid); +++ limit_tmp--; +++ } +++ rcu_read_unlock(); +++ +++ batadv_tt_global_entry_put(tt_global); +++ *limit = limit_tmp; +++ +++out: +++ return ret; +++} +++ +++/** +++ * batadv_mcast_forw_want_all_ipv4_send() - send to nodes with want-all-ipv4 +++ * @bat_priv: the bat priv with all the soft interface information +++ * @skb: the multicast packet to transmit +++ * @vid: the vlan identifier +++ * @limit: number of remaining, maximum transmissions +++ * +++ * Sends copies of a frame with multicast destination to any node with a +++ * BATADV_MCAST_WANT_ALL_IPV4 flag set. A transmission is performed via a +++ * batman-adv unicast packet for each such destination node. +++ * +++ * Return: NET_XMIT_DROP if limit was reached or on memory allocation failure, +++ * NET_XMIT_SUCCESS otherwise. +++ */ +++static int +++batadv_mcast_forw_want_all_ipv4_send(struct batadv_priv *bat_priv, +++ struct sk_buff *skb, unsigned short vid, +++ unsigned int *limit) +++{ +++ struct batadv_orig_node *orig_node; +++ unsigned int limit_tmp = *limit; +++ int ret = NET_XMIT_SUCCESS; +++ struct sk_buff *newskb; +++ +++ rcu_read_lock(); +++ hlist_for_each_entry_rcu(orig_node, +++ &bat_priv->mcast.want_all_ipv4_list, +++ mcast_want_all_ipv4_node) { +++ if (!limit_tmp) { +++ ret = NET_XMIT_DROP; +++ break; +++ } +++ +++ newskb = skb_copy(skb, GFP_ATOMIC); +++ if (!newskb) { +++ ret = NET_XMIT_DROP; +++ break; +++ } +++ +++ batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, +++ orig_node, vid); +++ limit_tmp--; +++ } +++ rcu_read_unlock(); +++ +++ *limit = limit_tmp; +++ return ret; +++} +++ +++/** +++ * batadv_mcast_forw_want_all_ipv6_send() - send to nodes with want-all-ipv6 +++ * @bat_priv: the bat priv with all the soft interface information +++ * @skb: The multicast packet to transmit +++ * @vid: the vlan identifier +++ * @limit: number of remaining, maximum transmissions +++ * +++ * Sends copies of a frame with multicast destination to any node with a +++ * BATADV_MCAST_WANT_ALL_IPV6 flag set. A transmission is performed via a +++ * batman-adv unicast packet for each such destination node. +++ * +++ * Return: NET_XMIT_DROP if limit was reached or on memory allocation failure, +++ * NET_XMIT_SUCCESS otherwise. +++ */ +++static int +++batadv_mcast_forw_want_all_ipv6_send(struct batadv_priv *bat_priv, +++ struct sk_buff *skb, unsigned short vid, +++ unsigned int *limit) +++{ +++ struct batadv_orig_node *orig_node; +++ unsigned int limit_tmp = *limit; +++ int ret = NET_XMIT_SUCCESS; +++ struct sk_buff *newskb; +++ +++ rcu_read_lock(); +++ hlist_for_each_entry_rcu(orig_node, +++ &bat_priv->mcast.want_all_ipv6_list, +++ mcast_want_all_ipv6_node) { +++ if (!limit_tmp) { +++ ret = NET_XMIT_DROP; +++ break; +++ } +++ +++ newskb = skb_copy(skb, GFP_ATOMIC); +++ if (!newskb) { +++ ret = NET_XMIT_DROP; +++ break; +++ } +++ +++ batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, +++ orig_node, vid); +++ limit_tmp--; +++ } +++ rcu_read_unlock(); +++ +++ *limit = limit_tmp; +++ return ret; +++} +++ +++/** +++ * batadv_mcast_forw_want_all_send() - send packet to nodes in a want-all list +++ * @bat_priv: the bat priv with all the soft interface information +++ * @skb: the multicast packet to transmit +++ * @vid: the vlan identifier +++ * @limit: number of remaining, maximum transmissions +++ * +++ * Sends copies of a frame with multicast destination to any node with a +++ * BATADV_MCAST_WANT_ALL_IPV4 or BATADV_MCAST_WANT_ALL_IPV6 flag set. A +++ * transmission is performed via a batman-adv unicast packet for each such +++ * destination node. +++ * +++ * Return: NET_XMIT_DROP if limit was reached, on memory allocation failure +++ * or if the protocol family is neither IPv4 nor IPv6. NET_XMIT_SUCCESS +++ * otherwise. +++ */ +++static int +++batadv_mcast_forw_want_all_send(struct batadv_priv *bat_priv, +++ struct sk_buff *skb, unsigned short vid, +++ unsigned int *limit) +++{ +++ switch (ntohs(eth_hdr(skb)->h_proto)) { +++ case ETH_P_IP: +++ return batadv_mcast_forw_want_all_ipv4_send(bat_priv, skb, vid, +++ limit); +++ case ETH_P_IPV6: +++ return batadv_mcast_forw_want_all_ipv6_send(bat_priv, skb, vid, +++ limit); +++ default: +++ /* we shouldn't be here... */ +++ return NET_XMIT_DROP; +++ } +++} +++ +++/** +++ * batadv_mcast_forw_send() - send packet to any detected multicast recpient +++ * @bat_priv: the bat priv with all the soft interface information +++ * @skb: the multicast packet to transmit +++ * @vid: the vlan identifier +++ * @limit: number of remaining, maximum transmissions +++ * +++ * Sends copies of a frame with multicast destination to any node that signaled +++ * interest in it, that is either via the translation table or the according +++ * want-all flags. A transmission is performed via a batman-adv unicast packet +++ * for each such destination node. +++ * +++ * The given skb is consumed/freed. +++ * +++ * Return: NET_XMIT_DROP if limit was reached, on memory allocation failure +++ * or if the protocol family is neither IPv4 nor IPv6. NET_XMIT_SUCCESS +++ * otherwise. +++ */ +++int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +++ unsigned short vid) +++{ +++ /* The previous forw mode check will try to limit to the configured +++ * fanout. Here, we allow a little bit of flexibility in case some +++ * new listeners might have joined between these function calls. +++ */ +++ unsigned int limit = 2 * atomic_read(&bat_priv->multicast_fanout); +++ int ret; +++ +++ ret = batadv_mcast_forw_tt_send(bat_priv, skb, vid, &limit); +++ if (ret != NET_XMIT_SUCCESS) { +++ kfree_skb(skb); +++ return ret; +++ } +++ +++ ret = batadv_mcast_forw_want_all_send(bat_priv, skb, vid, &limit); +++ if (ret != NET_XMIT_SUCCESS) { +++ kfree_skb(skb); +++ return ret; +++ } +++ +++ consume_skb(skb); +++ return ret; ++ } ++ ++ /** ++diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h ++index 3b04ab13..825472c7 100644 ++--- a/net/batman-adv/multicast.h +++++ b/net/batman-adv/multicast.h ++@@ -36,6 +36,13 @@ enum batadv_forw_mode { ++ BATADV_FORW_ALL, ++ ++ /** +++ * @BATADV_FORW_SOME: forward the packet to some nodes (currently via +++ * a multicast-to-unicast conversion and the BATMAN unicast routing +++ * protocol) +++ */ +++ BATADV_FORW_SOME, +++ +++ /** ++ * @BATADV_FORW_SINGLE: forward the packet to a single node (currently ++ * via the BATMAN unicast routing protocol) ++ */ ++@@ -51,6 +58,9 @@ enum batadv_forw_mode ++ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ++ struct batadv_orig_node **mcast_single_orig); ++ +++int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +++ unsigned short vid); +++ ++ void batadv_mcast_init(struct batadv_priv *bat_priv); ++ ++ int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset); ++@@ -73,6 +83,14 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ++ return BATADV_FORW_ALL; ++ } ++ +++static inline int +++batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +++ unsigned short vid) +++{ +++ kfree_skb(skb); +++ return NET_XMIT_DROP; +++} +++ ++ static inline int batadv_mcast_init(struct batadv_priv *bat_priv) ++ { ++ return 0; ++diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c ++index 8fd8d806..e43b38c3 100644 ++--- a/net/batman-adv/soft-interface.c +++++ b/net/batman-adv/soft-interface.c ++@@ -209,7 +209,7 @@ static int batadv_interface_tx(struct sk_buff *skb, ++ unsigned short vid; ++ u32 seqno; ++ int gw_mode; ++- enum batadv_forw_mode forw_mode; +++ enum batadv_forw_mode forw_mode = BATADV_FORW_SINGLE; ++ struct batadv_orig_node *mcast_single_orig = NULL; ++ int network_offset = ETH_HLEN; ++ ++@@ -308,7 +308,8 @@ static int batadv_interface_tx(struct sk_buff *skb, ++ if (forw_mode == BATADV_FORW_NONE) ++ goto dropped; ++ ++- if (forw_mode == BATADV_FORW_SINGLE) +++ if (forw_mode == BATADV_FORW_SINGLE || +++ forw_mode == BATADV_FORW_SOME) ++ do_bcast = false; ++ } ++ } ++@@ -368,6 +369,8 @@ static int batadv_interface_tx(struct sk_buff *skb, ++ ret = batadv_send_skb_unicast(bat_priv, skb, ++ BATADV_UNICAST, 0, ++ mcast_single_orig, vid); +++ } else if (forw_mode == BATADV_FORW_SOME) { +++ ret = batadv_mcast_forw_send(bat_priv, skb, vid); ++ } else { ++ if (batadv_dat_snoop_outgoing_arp_request(bat_priv, ++ skb)) ++@@ -809,6 +812,7 @@ static int batadv_softif_init_late(struct net_device *dev) ++ bat_priv->mcast.querier_ipv6.shadowing = false; ++ bat_priv->mcast.flags = BATADV_NO_FLAGS; ++ atomic_set(&bat_priv->multicast_mode, 1); +++ atomic_set(&bat_priv->multicast_fanout, 16); ++ atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); ++ atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); ++ atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); ++diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c ++index 09427fc6..57b728b3 100644 ++--- a/net/batman-adv/sysfs.c +++++ b/net/batman-adv/sysfs.c ++@@ -697,6 +697,8 @@ static BATADV_ATTR(gw_bandwidth, 0644, batadv_show_gw_bwidth, ++ batadv_store_gw_bwidth); ++ #ifdef CONFIG_BATMAN_ADV_MCAST ++ BATADV_ATTR_SIF_BOOL(multicast_mode, 0644, NULL); +++BATADV_ATTR_SIF_UINT(multicast_fanout, multicast_fanout, 0644, 1, INT_MAX, +++ NULL); ++ #endif ++ #ifdef CONFIG_BATMAN_ADV_DEBUG ++ BATADV_ATTR_SIF_UINT(log_level, log_level, 0644, 0, BATADV_DBG_ALL, NULL); ++@@ -718,6 +720,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { ++ #endif ++ #ifdef CONFIG_BATMAN_ADV_MCAST ++ &batadv_attr_multicast_mode, +++ &batadv_attr_multicast_fanout, ++ #endif ++ &batadv_attr_fragmentation, ++ &batadv_attr_routing_algo, ++diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c ++index d21624c4..a6fe45bf 100644 ++--- a/net/batman-adv/translation-table.c +++++ b/net/batman-adv/translation-table.c ++@@ -61,6 +61,7 @@ ++ #include "log.h" ++ #include "netlink.h" ++ #include "originator.h" +++#include "send.h" ++ #include "soft-interface.h" ++ #include "tvlv.h" ++ ++@@ -205,7 +206,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const u8 *addr, ++ * Return: a pointer to the corresponding tt_global_entry struct if the client ++ * is found, NULL otherwise. ++ */ ++-static struct batadv_tt_global_entry * +++struct batadv_tt_global_entry * ++ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr, ++ unsigned short vid) ++ { ++@@ -300,8 +301,7 @@ static void batadv_tt_global_entry_release(struct kref *ref) ++ * possibly release it ++ * @tt_global_entry: tt_global_entry to be free'd ++ */ ++-static void ++-batadv_tt_global_entry_put(struct batadv_tt_global_entry *tt_global_entry) +++void batadv_tt_global_entry_put(struct batadv_tt_global_entry *tt_global_entry) ++ { ++ kref_put(&tt_global_entry->common.refcount, ++ batadv_tt_global_entry_release); ++diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h ++index 01b6c8ea..0981db6c 100644 ++--- a/net/batman-adv/translation-table.h +++++ b/net/batman-adv/translation-table.h ++@@ -41,6 +41,10 @@ int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb); ++ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, ++ struct batadv_orig_node *orig_node, ++ s32 match_vid, const char *message); +++struct batadv_tt_global_entry * +++batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr, +++ unsigned short vid); +++void batadv_tt_global_entry_put(struct batadv_tt_global_entry *tt_global_entry); ++ int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, ++ const u8 *addr, unsigned short vid); ++ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, ++diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h ++index 0174f79e..47690038 100644 ++--- a/net/batman-adv/types.h +++++ b/net/batman-adv/types.h ++@@ -1552,6 +1552,12 @@ struct batadv_priv { ++ * node's sender/originating side ++ */ ++ atomic_t multicast_mode; +++ +++ /** +++ * @multicast_fanout: Maximum number of packet copies to generate for a +++ * multicast-to-unicast conversion +++ */ +++ atomic_t multicast_fanout; ++ #endif ++ ++ /** @orig_interval: OGM broadcast interval in milliseconds */ ++-- ++2.11.0 ++ +diff --git a/batman-adv/patches/0026-batman-adv-Introduce-no-noflood-mark.patch b/batman-adv/patches/0026-batman-adv-Introduce-no-noflood-mark.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..091f4347597e67a2aa1cf64d937f3cd2f45e65a9 +--- /dev/null ++++ b/batman-adv/patches/0026-batman-adv-Introduce-no-noflood-mark.patch +@@ -0,0 +1,262 @@ ++From 6a729232b4d46cc8b99eb0ed89547de2dddfc33f Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Linus=20L=C3=BCssing?= ++Date: Sat, 31 Mar 2018 03:36:19 +0200 ++Subject: [PATCH] batman-adv: Introduce no noflood mark ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This mark prevents a multicast packet being flooded through the whole ++mesh. The advantage of marking certain multicast packets via e.g. ++ebtables instead of dropping is then the following: ++ ++This allows an administrator to let specific multicast packets pass as ++long as they are forwarded to a limited number of nodes only and are ++therefore creating no burdon to unrelated nodes. ++ ++Signed-off-by: Linus Lüssing ++--- ++ Documentation/ABI/testing/sysfs-class-net-mesh | 8 ++ ++ net/batman-adv/soft-interface.c | 20 +++++ ++ net/batman-adv/sysfs.c | 103 +++++++++++++++++++++---- ++ net/batman-adv/types.h | 12 +++ ++ 4 files changed, 128 insertions(+), 15 deletions(-) ++ ++diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh ++index 18734a36..477287c4 100644 ++--- a/Documentation/ABI/testing/sysfs-class-net-mesh +++++ b/Documentation/ABI/testing/sysfs-class-net-mesh ++@@ -76,6 +76,14 @@ Description: ++ is used to classify clients as "isolated" by the ++ Extended Isolation feature. ++ +++What: /sys/class/net//mesh/noflood_mark +++Date: Mar 2018 +++Contact: Linus Lüssing +++Description: +++ Defines the noflood mark (and its bitmask) which +++ will drop frames with a matching mark if they were +++ to be flooded. +++ ++ What: /sys/class/net//mesh/multicast_fanout ++ Date: Feb 2018 ++ Contact: Linus Lüssing ++diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c ++index e43b38c3..ac272cbe 100644 ++--- a/net/batman-adv/soft-interface.c +++++ b/net/batman-adv/soft-interface.c ++@@ -188,6 +188,23 @@ static void batadv_interface_set_rx_mode(struct net_device *dev) ++ { ++ } ++ +++/** +++ * batadv_send_skb_has_noflood_mark() - check if packet has a noflood mark +++ * @bat_priv: the bat priv with all the soft interface information +++ * @skb: the packet to check +++ * +++ * Return: True if the skb's mark matches a configured noflood mark and +++ * noflood mark mask. False otherwise. +++ */ +++static bool +++batadv_skb_has_noflood_mark(struct batadv_priv *bat_priv, struct sk_buff *skb) +++{ +++ u32 match_mark = skb->mark & bat_priv->noflood_mark_mask; +++ +++ return bat_priv->noflood_mark_mask && +++ match_mark == bat_priv->noflood_mark; +++} +++ ++ static int batadv_interface_tx(struct sk_buff *skb, ++ struct net_device *soft_iface) ++ { ++@@ -329,6 +346,9 @@ static int batadv_interface_tx(struct sk_buff *skb, ++ if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) ++ brd_delay = msecs_to_jiffies(ARP_REQ_DELAY); ++ +++ if (batadv_skb_has_noflood_mark(bat_priv, skb)) +++ goto dropped; +++ ++ if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) ++ goto dropped; ++ ++diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c ++index 57b728b3..0e164c15 100644 ++--- a/net/batman-adv/sysfs.c +++++ b/net/batman-adv/sysfs.c ++@@ -627,28 +627,24 @@ static ssize_t batadv_show_isolation_mark(struct kobject *kobj, ++ } ++ ++ /** ++- * batadv_store_isolation_mark() - parse and store the isolation mark/mask ++- * entered by the user ++- * @kobj: kobject representing the private mesh sysfs directory ++- * @attr: the batman-adv attribute the user is interacting with +++ * batadv_store_parse_mark() - parse a mark and mask ++ * @buff: the buffer containing the user data ++- * @count: number of bytes in the buffer +++ * @mark: the variable to store the mark in +++ * @mask: the variable to store the mask in ++ * ++- * Return: 'count' on success or a negative error code in case of failure +++ * Parses a string for a mark and mask. The format is expected to consist of +++ * two 32 bit hexadecimal numbers delimited by a '/'. +++ * +++ * Return: 0 on success, -EINVAL on error. ++ */ ++-static ssize_t batadv_store_isolation_mark(struct kobject *kobj, ++- struct attribute *attr, char *buff, ++- size_t count) +++static int batadv_store_parse_mark(char *buff, u32 *mark, u32 *mask) ++ { ++- struct net_device *net_dev = batadv_kobj_to_netdev(kobj); ++- struct batadv_priv *bat_priv = netdev_priv(net_dev); ++- u32 mark, mask; ++ char *mask_ptr; ++ ++ /* parse the mask if it has been specified, otherwise assume the mask is ++ * the biggest possible ++ */ ++- mask = 0xFFFFFFFF; +++ *mask = 0xFFFFFFFF; ++ mask_ptr = strchr(buff, '/'); ++ if (mask_ptr) { ++ *mask_ptr = '\0'; ++@@ -657,12 +653,36 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj, ++ /* the mask must be entered in hex base as it is going to be a ++ * bitmask and not a prefix length ++ */ ++- if (kstrtou32(mask_ptr, 16, &mask) < 0) +++ if (kstrtou32(mask_ptr, 16, mask) < 0) ++ return -EINVAL; ++ } ++ ++ /* the mark can be entered in any base */ ++- if (kstrtou32(buff, 0, &mark) < 0) +++ if (kstrtou32(buff, 0, mark) < 0) +++ return -EINVAL; +++ +++ return 0; +++} +++ +++/** +++ * batadv_store_isolation_mark() - parse and store the isolation mark/mask +++ * entered by the user +++ * @kobj: kobject representing the private mesh sysfs directory +++ * @attr: the batman-adv attribute the user is interacting with +++ * @buff: the buffer containing the user data +++ * @count: number of bytes in the buffer +++ * +++ * Return: 'count' on success or a negative error code in case of failure +++ */ +++static ssize_t batadv_store_isolation_mark(struct kobject *kobj, +++ struct attribute *attr, char *buff, +++ size_t count) +++{ +++ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); +++ struct batadv_priv *bat_priv = netdev_priv(net_dev); +++ u32 mark, mask; +++ +++ if (batadv_store_parse_mark(buff, &mark, &mask) < 0) ++ return -EINVAL; ++ ++ bat_priv->isolation_mark_mask = mask; ++@@ -676,6 +696,56 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj, ++ return count; ++ } ++ +++/** +++ * batadv_show_noflood_mark() - print the current noflood mark/mask +++ * @kobj: kobject representing the private mesh sysfs directory +++ * @attr: the batman-adv attribute the user is interacting with +++ * @buff: the buffer that will contain the data to send back to the user +++ * +++ * Return: the number of bytes written into 'buff' on success or a negative +++ * error code in case of failure +++ */ +++static ssize_t batadv_show_noflood_mark(struct kobject *kobj, +++ struct attribute *attr, char *buff) +++{ +++ struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); +++ +++ return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->noflood_mark, +++ bat_priv->noflood_mark_mask); +++} +++ +++/** +++ * batadv_store_noflood_mark() - parse and store the noflood mark/mask +++ * entered by the user +++ * @kobj: kobject representing the private mesh sysfs directory +++ * @attr: the batman-adv attribute the user is interacting with +++ * @buff: the buffer containing the user data +++ * @count: number of bytes in the buffer +++ * +++ * Return: 'count' on success or a negative error code in case of failure +++ */ +++static ssize_t batadv_store_noflood_mark(struct kobject *kobj, +++ struct attribute *attr, char *buff, +++ size_t count) +++{ +++ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); +++ struct batadv_priv *bat_priv = netdev_priv(net_dev); +++ u32 mark, mask; +++ +++ if (batadv_store_parse_mark(buff, &mark, &mask) < 0) +++ return -EINVAL; +++ +++ bat_priv->noflood_mark_mask = mask; +++ /* erase bits not covered by the mask */ +++ bat_priv->noflood_mark = mark & bat_priv->noflood_mark_mask; +++ +++ batadv_info(net_dev, +++ "New skb noflood mark: %#.8x/%#.8x\n", +++ bat_priv->noflood_mark, bat_priv->noflood_mark_mask); +++ +++ return count; +++} +++ ++ BATADV_ATTR_SIF_BOOL(aggregated_ogms, 0644, NULL); ++ BATADV_ATTR_SIF_BOOL(bonding, 0644, NULL); ++ #ifdef CONFIG_BATMAN_ADV_BLA ++@@ -708,6 +778,8 @@ BATADV_ATTR_SIF_BOOL(network_coding, 0644, batadv_nc_status_update); ++ #endif ++ static BATADV_ATTR(isolation_mark, 0644, batadv_show_isolation_mark, ++ batadv_store_isolation_mark); +++static BATADV_ATTR(noflood_mark, 0644, batadv_show_noflood_mark, +++ batadv_store_noflood_mark); ++ ++ static struct batadv_attribute *batadv_mesh_attrs[] = { ++ &batadv_attr_aggregated_ogms, ++@@ -736,6 +808,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { ++ &batadv_attr_network_coding, ++ #endif ++ &batadv_attr_isolation_mark, +++ &batadv_attr_noflood_mark, ++ NULL, ++ }; ++ ++diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h ++index 47690038..44ab319f 100644 ++--- a/net/batman-adv/types.h +++++ b/net/batman-adv/types.h ++@@ -1586,6 +1586,18 @@ struct batadv_priv { ++ */ ++ u32 isolation_mark_mask; ++ +++ /** +++ * @noflood_mark: the skb->mark value used to allow directed targeting +++ * only +++ */ +++ u32 noflood_mark; +++ +++ /** +++ * @noflood_mark_mask: bitmask identifying the bits in skb->mark to be +++ * used for the noflood mark +++ */ +++ u32 noflood_mark_mask; +++ ++ /** @bcast_seqno: last sent broadcast packet sequence number */ ++ atomic_t bcast_seqno; ++ ++-- ++2.11.0 ++