aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@web.de>2014-02-15 11:47:52 -0500
committerAntonio Quartulli <antonio@meshcoding.com>2014-03-22 04:18:57 -0400
commit1d8ab8d3c176d31530b3ffd4547cf731018e2a45 (patch)
treeb62208972cdfb70a853ff5177c29154fd165bea7 /net/batman-adv
parent60432d756cf06e597ef9da511402dd059b112447 (diff)
batman-adv: Modified forwarding behaviour for multicast packets
With this patch a multicast packet is not always simply flooded anymore, the behaviour for the following cases is changed to reduce unnecessary overhead: If all nodes within the horizon of a certain node have signalized multicast listener announcement capability then an IPv6 multicast packet with a destination of IPv6 link-local scope (excluding ff02::1) coming from the upstream of this node... * ...is dropped if there is no according multicast listener in the translation table, * ...is forwarded via unicast if there is a single node with interested multicast listeners * ...and otherwise still gets flooded. Signed-off-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/multicast.c126
-rw-r--r--net/batman-adv/multicast.h25
-rw-r--r--net/batman-adv/send.c10
-rw-r--r--net/batman-adv/send.h5
-rw-r--r--net/batman-adv/soft-interface.c20
-rw-r--r--net/batman-adv/sysfs.c6
-rw-r--r--net/batman-adv/translation-table.c91
-rw-r--r--net/batman-adv/translation-table.h2
-rw-r--r--net/batman-adv/types.h7
9 files changed, 266 insertions, 26 deletions
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 3ba9a18a906c..1d1627fe0de0 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -20,6 +20,7 @@
20#include "originator.h" 20#include "originator.h"
21#include "hard-interface.h" 21#include "hard-interface.h"
22#include "translation-table.h" 22#include "translation-table.h"
23#include "multicast.h"
23 24
24/** 25/**
25 * batadv_mcast_mla_softif_get - get softif multicast listeners 26 * batadv_mcast_mla_softif_get - get softif multicast listeners
@@ -247,6 +248,131 @@ out:
247} 248}
248 249
249/** 250/**
251 * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential
252 * @bat_priv: the bat priv with all the soft interface information
253 * @skb: the IPv6 packet to check
254 *
255 * Checks whether the given IPv6 packet has the potential to be forwarded with a
256 * mode more optimal than classic flooding.
257 *
258 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
259 * of memory.
260 */
261static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv,
262 struct sk_buff *skb)
263{
264 struct ipv6hdr *ip6hdr;
265
266 /* We might fail due to out-of-memory -> drop it */
267 if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr)))
268 return -ENOMEM;
269
270 ip6hdr = ipv6_hdr(skb);
271
272 /* TODO: Implement Multicast Router Discovery (RFC4286),
273 * then allow scope > link local, too
274 */
275 if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL)
276 return -EINVAL;
277
278 /* link-local-all-nodes multicast listeners behind a bridge are
279 * not snoopable (see RFC4541, section 3, paragraph 3)
280 */
281 if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr))
282 return -EINVAL;
283
284 return 0;
285}
286
287/**
288 * batadv_mcast_forw_mode_check - check for optimized forwarding potential
289 * @bat_priv: the bat priv with all the soft interface information
290 * @skb: the multicast frame to check
291 *
292 * Checks whether the given multicast ethernet frame has the potential to be
293 * forwarded with a mode more optimal than classic flooding.
294 *
295 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
296 * of memory.
297 */
298static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
299 struct sk_buff *skb)
300{
301 struct ethhdr *ethhdr = eth_hdr(skb);
302
303 if (!atomic_read(&bat_priv->multicast_mode))
304 return -EINVAL;
305
306 if (atomic_read(&bat_priv->mcast.num_disabled))
307 return -EINVAL;
308
309 switch (ntohs(ethhdr->h_proto)) {
310 case ETH_P_IPV6:
311 return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb);
312 default:
313 return -EINVAL;
314 }
315}
316
317/**
318 * batadv_mcast_forw_tt_node_get - get a multicast tt node
319 * @bat_priv: the bat priv with all the soft interface information
320 * @ethhdr: the ether header containing the multicast destination
321 *
322 * Returns an orig_node matching the multicast address provided by ethhdr
323 * via a translation table lookup. This increases the returned nodes refcount.
324 */
325static struct batadv_orig_node *
326batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv,
327 struct ethhdr *ethhdr)
328{
329 return batadv_transtable_search(bat_priv, ethhdr->h_source,
330 ethhdr->h_dest, BATADV_NO_FLAGS);
331}
332
333/**
334 * batadv_mcast_forw_mode - check on how to forward a multicast packet
335 * @bat_priv: the bat priv with all the soft interface information
336 * @skb: The multicast packet to check
337 * @orig: an originator to be set to forward the skb to
338 *
339 * Returns the forwarding mode as enum batadv_forw_mode and in case of
340 * BATADV_FORW_SINGLE set the orig to the single originator the skb
341 * should be forwarded to.
342 */
343enum batadv_forw_mode
344batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
345 struct batadv_orig_node **orig)
346{
347 struct ethhdr *ethhdr;
348 int ret, tt_count;
349
350 ret = batadv_mcast_forw_mode_check(bat_priv, skb);
351 if (ret == -ENOMEM)
352 return BATADV_FORW_NONE;
353 else if (ret < 0)
354 return BATADV_FORW_ALL;
355
356 ethhdr = eth_hdr(skb);
357
358 tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest,
359 BATADV_NO_FLAGS);
360
361 switch (tt_count) {
362 case 1:
363 *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr);
364 if (*orig)
365 return BATADV_FORW_SINGLE;
366
367 /* fall through */
368 case 0:
369 return BATADV_FORW_NONE;
370 default:
371 return BATADV_FORW_ALL;
372 }
373}
374
375/**
250 * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container 376 * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
251 * @bat_priv: the bat priv with all the soft interface information 377 * @bat_priv: the bat priv with all the soft interface information
252 * @orig: the orig_node of the ogm 378 * @orig: the orig_node of the ogm
diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h
index c029eaca7c44..73b5d45819c1 100644
--- a/net/batman-adv/multicast.h
+++ b/net/batman-adv/multicast.h
@@ -18,10 +18,28 @@
18#ifndef _NET_BATMAN_ADV_MULTICAST_H_ 18#ifndef _NET_BATMAN_ADV_MULTICAST_H_
19#define _NET_BATMAN_ADV_MULTICAST_H_ 19#define _NET_BATMAN_ADV_MULTICAST_H_
20 20
21/**
22 * batadv_forw_mode - the way a packet should be forwarded as
23 * @BATADV_FORW_ALL: forward the packet to all nodes (currently via classic
24 * flooding)
25 * @BATADV_FORW_SINGLE: forward the packet to a single node (currently via the
26 * BATMAN unicast routing protocol)
27 * @BATADV_FORW_NONE: don't forward, drop it
28 */
29enum batadv_forw_mode {
30 BATADV_FORW_ALL,
31 BATADV_FORW_SINGLE,
32 BATADV_FORW_NONE,
33};
34
21#ifdef CONFIG_BATMAN_ADV_MCAST 35#ifdef CONFIG_BATMAN_ADV_MCAST
22 36
23void batadv_mcast_mla_update(struct batadv_priv *bat_priv); 37void batadv_mcast_mla_update(struct batadv_priv *bat_priv);
24 38
39enum batadv_forw_mode
40batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
41 struct batadv_orig_node **mcast_single_orig);
42
25void batadv_mcast_init(struct batadv_priv *bat_priv); 43void batadv_mcast_init(struct batadv_priv *bat_priv);
26 44
27void batadv_mcast_free(struct batadv_priv *bat_priv); 45void batadv_mcast_free(struct batadv_priv *bat_priv);
@@ -35,6 +53,13 @@ static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
35 return; 53 return;
36} 54}
37 55
56static inline enum batadv_forw_mode
57batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
58 struct batadv_orig_node **mcast_single_orig)
59{
60 return BATADV_FORW_ALL;
61}
62
38static inline int batadv_mcast_init(struct batadv_priv *bat_priv) 63static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
39{ 64{
40 return 0; 65 return 0;
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index ce163d50e5d7..8bee5e8536b7 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -248,11 +248,11 @@ out:
248 * 248 *
249 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. 249 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
250 */ 250 */
251static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, 251int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
252 struct sk_buff *skb, int packet_type, 252 struct sk_buff *skb, int packet_type,
253 int packet_subtype, 253 int packet_subtype,
254 struct batadv_orig_node *orig_node, 254 struct batadv_orig_node *orig_node,
255 unsigned short vid) 255 unsigned short vid)
256{ 256{
257 struct ethhdr *ethhdr; 257 struct ethhdr *ethhdr;
258 struct batadv_unicast_packet *unicast_packet; 258 struct batadv_unicast_packet *unicast_packet;
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 31e87811ce5b..38d0ec1833ae 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -36,6 +36,11 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
36 struct sk_buff *skb, 36 struct sk_buff *skb,
37 struct batadv_orig_node *orig_node, 37 struct batadv_orig_node *orig_node,
38 int packet_subtype); 38 int packet_subtype);
39int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
40 struct sk_buff *skb, int packet_type,
41 int packet_subtype,
42 struct batadv_orig_node *orig_node,
43 unsigned short vid);
39int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, 44int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
40 struct sk_buff *skb, int packet_type, 45 struct sk_buff *skb, int packet_type,
41 int packet_subtype, uint8_t *dst_hint, 46 int packet_subtype, uint8_t *dst_hint,
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 8ff47b7a0e04..1a643fe647e1 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -32,6 +32,7 @@
32#include <linux/ethtool.h> 32#include <linux/ethtool.h>
33#include <linux/etherdevice.h> 33#include <linux/etherdevice.h>
34#include <linux/if_vlan.h> 34#include <linux/if_vlan.h>
35#include "multicast.h"
35#include "bridge_loop_avoidance.h" 36#include "bridge_loop_avoidance.h"
36#include "network-coding.h" 37#include "network-coding.h"
37 38
@@ -170,6 +171,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
170 unsigned short vid; 171 unsigned short vid;
171 uint32_t seqno; 172 uint32_t seqno;
172 int gw_mode; 173 int gw_mode;
174 enum batadv_forw_mode forw_mode;
175 struct batadv_orig_node *mcast_single_orig = NULL;
173 176
174 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) 177 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
175 goto dropped; 178 goto dropped;
@@ -247,9 +250,19 @@ static int batadv_interface_tx(struct sk_buff *skb,
247 * directed to a DHCP server 250 * directed to a DHCP server
248 */ 251 */
249 goto dropped; 252 goto dropped;
250 }
251 253
252send: 254send:
255 if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) {
256 forw_mode = batadv_mcast_forw_mode(bat_priv, skb,
257 &mcast_single_orig);
258 if (forw_mode == BATADV_FORW_NONE)
259 goto dropped;
260
261 if (forw_mode == BATADV_FORW_SINGLE)
262 do_bcast = false;
263 }
264 }
265
253 batadv_skb_set_priority(skb, 0); 266 batadv_skb_set_priority(skb, 0);
254 267
255 /* ethernet packet should be broadcasted */ 268 /* ethernet packet should be broadcasted */
@@ -301,6 +314,10 @@ send:
301 if (ret) 314 if (ret)
302 goto dropped; 315 goto dropped;
303 ret = batadv_send_skb_via_gw(bat_priv, skb, vid); 316 ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
317 } else if (mcast_single_orig) {
318 ret = batadv_send_skb_unicast(bat_priv, skb,
319 BATADV_UNICAST, 0,
320 mcast_single_orig, vid);
304 } else { 321 } else {
305 if (batadv_dat_snoop_outgoing_arp_request(bat_priv, 322 if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
306 skb)) 323 skb))
@@ -691,6 +708,7 @@ static int batadv_softif_init_late(struct net_device *dev)
691#endif 708#endif
692#ifdef CONFIG_BATMAN_ADV_MCAST 709#ifdef CONFIG_BATMAN_ADV_MCAST
693 bat_priv->mcast.flags = BATADV_NO_FLAGS; 710 bat_priv->mcast.flags = BATADV_NO_FLAGS;
711 atomic_set(&bat_priv->multicast_mode, 1);
694 atomic_set(&bat_priv->mcast.num_disabled, 0); 712 atomic_set(&bat_priv->mcast.num_disabled, 0);
695#endif 713#endif
696 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); 714 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index e456bf6bb284..1ebb0d9e2ea5 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -539,6 +539,9 @@ BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE,
539 batadv_post_gw_reselect); 539 batadv_post_gw_reselect);
540static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, 540static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
541 batadv_store_gw_bwidth); 541 batadv_store_gw_bwidth);
542#ifdef CONFIG_BATMAN_ADV_MCAST
543BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
544#endif
542#ifdef CONFIG_BATMAN_ADV_DEBUG 545#ifdef CONFIG_BATMAN_ADV_DEBUG
543BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); 546BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
544#endif 547#endif
@@ -558,6 +561,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
558#ifdef CONFIG_BATMAN_ADV_DAT 561#ifdef CONFIG_BATMAN_ADV_DAT
559 &batadv_attr_distributed_arp_table, 562 &batadv_attr_distributed_arp_table,
560#endif 563#endif
564#ifdef CONFIG_BATMAN_ADV_MCAST
565 &batadv_attr_multicast_mode,
566#endif
561 &batadv_attr_fragmentation, 567 &batadv_attr_fragmentation,
562 &batadv_attr_routing_algo, 568 &batadv_attr_routing_algo,
563 &batadv_attr_gw_mode, 569 &batadv_attr_gw_mode,
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index f641dfe302a4..d636bde72c9a 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -193,6 +193,31 @@ batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
193 } 193 }
194} 194}
195 195
196/**
197 * batadv_tt_global_hash_count - count the number of orig entries
198 * @hash: hash table containing the tt entries
199 * @addr: the mac address of the client to count entries for
200 * @vid: VLAN identifier
201 *
202 * Return the number of originators advertising the given address/data
203 * (excluding ourself).
204 */
205int batadv_tt_global_hash_count(struct batadv_priv *bat_priv,
206 const uint8_t *addr, unsigned short vid)
207{
208 struct batadv_tt_global_entry *tt_global_entry;
209 int count;
210
211 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
212 if (!tt_global_entry)
213 return 0;
214
215 count = atomic_read(&tt_global_entry->orig_list_count);
216 batadv_tt_global_entry_free_ref(tt_global_entry);
217
218 return count;
219}
220
196static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) 221static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
197{ 222{
198 struct batadv_tt_orig_list_entry *orig_entry; 223 struct batadv_tt_orig_list_entry *orig_entry;
@@ -1225,6 +1250,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
1225 hlist_add_head_rcu(&orig_entry->list, 1250 hlist_add_head_rcu(&orig_entry->list,
1226 &tt_global->orig_list); 1251 &tt_global->orig_list);
1227 spin_unlock_bh(&tt_global->list_lock); 1252 spin_unlock_bh(&tt_global->list_lock);
1253 atomic_inc(&tt_global->orig_list_count);
1254
1228out: 1255out:
1229 if (orig_entry) 1256 if (orig_entry)
1230 batadv_tt_orig_list_entry_free_ref(orig_entry); 1257 batadv_tt_orig_list_entry_free_ref(orig_entry);
@@ -1298,6 +1325,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
1298 common->added_at = jiffies; 1325 common->added_at = jiffies;
1299 1326
1300 INIT_HLIST_HEAD(&tt_global_entry->orig_list); 1327 INIT_HLIST_HEAD(&tt_global_entry->orig_list);
1328 atomic_set(&tt_global_entry->orig_list_count, 0);
1301 spin_lock_init(&tt_global_entry->list_lock); 1329 spin_lock_init(&tt_global_entry->list_lock);
1302 1330
1303 hash_added = batadv_hash_add(bat_priv->tt.global_hash, 1331 hash_added = batadv_hash_add(bat_priv->tt.global_hash,
@@ -1563,6 +1591,25 @@ out:
1563 return 0; 1591 return 0;
1564} 1592}
1565 1593
1594/**
1595 * batadv_tt_global_del_orig_entry - remove and free an orig_entry
1596 * @tt_global_entry: the global entry to remove the orig_entry from
1597 * @orig_entry: the orig entry to remove and free
1598 *
1599 * Remove an orig_entry from its list in the given tt_global_entry and
1600 * free this orig_entry afterwards.
1601 */
1602static void
1603batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
1604 struct batadv_tt_orig_list_entry *orig_entry)
1605{
1606 batadv_tt_global_size_dec(orig_entry->orig_node,
1607 tt_global_entry->common.vid);
1608 atomic_dec(&tt_global_entry->orig_list_count);
1609 hlist_del_rcu(&orig_entry->list);
1610 batadv_tt_orig_list_entry_free_ref(orig_entry);
1611}
1612
1566/* deletes the orig list of a tt_global_entry */ 1613/* deletes the orig list of a tt_global_entry */
1567static void 1614static void
1568batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) 1615batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
@@ -1573,20 +1620,26 @@ batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
1573 1620
1574 spin_lock_bh(&tt_global_entry->list_lock); 1621 spin_lock_bh(&tt_global_entry->list_lock);
1575 head = &tt_global_entry->orig_list; 1622 head = &tt_global_entry->orig_list;
1576 hlist_for_each_entry_safe(orig_entry, safe, head, list) { 1623 hlist_for_each_entry_safe(orig_entry, safe, head, list)
1577 hlist_del_rcu(&orig_entry->list); 1624 batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry);
1578 batadv_tt_global_size_dec(orig_entry->orig_node,
1579 tt_global_entry->common.vid);
1580 batadv_tt_orig_list_entry_free_ref(orig_entry);
1581 }
1582 spin_unlock_bh(&tt_global_entry->list_lock); 1625 spin_unlock_bh(&tt_global_entry->list_lock);
1583} 1626}
1584 1627
1628/**
1629 * batadv_tt_global_del_orig_node - remove orig_node from a global tt entry
1630 * @bat_priv: the bat priv with all the soft interface information
1631 * @tt_global_entry: the global entry to remove the orig_node from
1632 * @orig_node: the originator announcing the client
1633 * @message: message to append to the log on deletion
1634 *
1635 * Remove the given orig_node and its according orig_entry from the given
1636 * global tt entry.
1637 */
1585static void 1638static void
1586batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, 1639batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
1587 struct batadv_tt_global_entry *tt_global_entry, 1640 struct batadv_tt_global_entry *tt_global_entry,
1588 struct batadv_orig_node *orig_node, 1641 struct batadv_orig_node *orig_node,
1589 const char *message) 1642 const char *message)
1590{ 1643{
1591 struct hlist_head *head; 1644 struct hlist_head *head;
1592 struct hlist_node *safe; 1645 struct hlist_node *safe;
@@ -1603,10 +1656,8 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
1603 orig_node->orig, 1656 orig_node->orig,
1604 tt_global_entry->common.addr, 1657 tt_global_entry->common.addr,
1605 BATADV_PRINT_VID(vid), message); 1658 BATADV_PRINT_VID(vid), message);
1606 hlist_del_rcu(&orig_entry->list); 1659 batadv_tt_global_del_orig_entry(tt_global_entry,
1607 batadv_tt_global_size_dec(orig_node, 1660 orig_entry);
1608 tt_global_entry->common.vid);
1609 batadv_tt_orig_list_entry_free_ref(orig_entry);
1610 } 1661 }
1611 } 1662 }
1612 spin_unlock_bh(&tt_global_entry->list_lock); 1663 spin_unlock_bh(&tt_global_entry->list_lock);
@@ -1648,8 +1699,8 @@ batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
1648 /* there is another entry, we can simply delete this 1699 /* there is another entry, we can simply delete this
1649 * one and can still use the other one. 1700 * one and can still use the other one.
1650 */ 1701 */
1651 batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, 1702 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
1652 orig_node, message); 1703 orig_node, message);
1653} 1704}
1654 1705
1655/** 1706/**
@@ -1675,8 +1726,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
1675 goto out; 1726 goto out;
1676 1727
1677 if (!roaming) { 1728 if (!roaming) {
1678 batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, 1729 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
1679 orig_node, message); 1730 orig_node, message);
1680 1731
1681 if (hlist_empty(&tt_global_entry->orig_list)) 1732 if (hlist_empty(&tt_global_entry->orig_list))
1682 batadv_tt_global_free(bat_priv, tt_global_entry, 1733 batadv_tt_global_free(bat_priv, tt_global_entry,
@@ -1759,8 +1810,8 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1759 struct batadv_tt_global_entry, 1810 struct batadv_tt_global_entry,
1760 common); 1811 common);
1761 1812
1762 batadv_tt_global_del_orig_entry(bat_priv, tt_global, 1813 batadv_tt_global_del_orig_node(bat_priv, tt_global,
1763 orig_node, message); 1814 orig_node, message);
1764 1815
1765 if (hlist_empty(&tt_global->orig_list)) { 1816 if (hlist_empty(&tt_global->orig_list)) {
1766 vid = tt_global->common.vid; 1817 vid = tt_global->common.vid;
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 20a1d7861ded..ad84d7b89e39 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -29,6 +29,8 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
29void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, 29void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
30 struct batadv_orig_node *orig_node, 30 struct batadv_orig_node *orig_node,
31 int32_t match_vid, const char *message); 31 int32_t match_vid, const char *message);
32int batadv_tt_global_hash_count(struct batadv_priv *bat_priv,
33 const uint8_t *addr, unsigned short vid);
32struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, 34struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
33 const uint8_t *src, 35 const uint8_t *src,
34 const uint8_t *addr, 36 const uint8_t *addr,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 96ee0d2b11d9..c28fc4a403a3 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -696,6 +696,8 @@ struct batadv_softif_vlan {
696 * enabled 696 * enabled
697 * @distributed_arp_table: bool indicating whether distributed ARP table is 697 * @distributed_arp_table: bool indicating whether distributed ARP table is
698 * enabled 698 * enabled
699 * @multicast_mode: Enable or disable multicast optimizations on this node's
700 * sender/originating side
699 * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) 701 * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes)
700 * @gw_sel_class: gateway selection class (applies if gw_mode client) 702 * @gw_sel_class: gateway selection class (applies if gw_mode client)
701 * @orig_interval: OGM broadcast interval in milliseconds 703 * @orig_interval: OGM broadcast interval in milliseconds
@@ -746,6 +748,9 @@ struct batadv_priv {
746#ifdef CONFIG_BATMAN_ADV_DAT 748#ifdef CONFIG_BATMAN_ADV_DAT
747 atomic_t distributed_arp_table; 749 atomic_t distributed_arp_table;
748#endif 750#endif
751#ifdef CONFIG_BATMAN_ADV_MCAST
752 atomic_t multicast_mode;
753#endif
749 atomic_t gw_mode; 754 atomic_t gw_mode;
750 atomic_t gw_sel_class; 755 atomic_t gw_sel_class;
751 atomic_t orig_interval; 756 atomic_t orig_interval;
@@ -909,12 +914,14 @@ struct batadv_tt_local_entry {
909 * struct batadv_tt_global_entry - translation table global entry data 914 * struct batadv_tt_global_entry - translation table global entry data
910 * @common: general translation table data 915 * @common: general translation table data
911 * @orig_list: list of orig nodes announcing this non-mesh client 916 * @orig_list: list of orig nodes announcing this non-mesh client
917 * @orig_list_count: number of items in the orig_list
912 * @list_lock: lock protecting orig_list 918 * @list_lock: lock protecting orig_list
913 * @roam_at: time at which TT_GLOBAL_ROAM was set 919 * @roam_at: time at which TT_GLOBAL_ROAM was set
914 */ 920 */
915struct batadv_tt_global_entry { 921struct batadv_tt_global_entry {
916 struct batadv_tt_common_entry common; 922 struct batadv_tt_common_entry common;
917 struct hlist_head orig_list; 923 struct hlist_head orig_list;
924 atomic_t orig_list_count;
918 spinlock_t list_lock; /* protects orig_list */ 925 spinlock_t list_lock; /* protects orig_list */
919 unsigned long roam_at; 926 unsigned long roam_at;
920}; 927};