aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-mesh9
-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
10 files changed, 275 insertions, 26 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index 4793d3dff6af..c46406296631 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -76,6 +76,15 @@ Description:
76 is used to classify clients as "isolated" by the 76 is used to classify clients as "isolated" by the
77 Extended Isolation feature. 77 Extended Isolation feature.
78 78
79What: /sys/class/net/<mesh_iface>/mesh/multicast_mode
80Date: Feb 2014
81Contact: Linus Lüssing <linus.luessing@web.de>
82Description:
83 Indicates whether multicast optimizations are enabled
84 or disabled. If set to zero then all nodes in the
85 mesh are going to use classic flooding for any
86 multicast packet with no optimizations.
87
79What: /sys/class/net/<mesh_iface>/mesh/network_coding 88What: /sys/class/net/<mesh_iface>/mesh/network_coding
80Date: Nov 2012 89Date: Nov 2012
81Contact: Martin Hundeboll <martin@hundeboll.net> 90Contact: Martin Hundeboll <martin@hundeboll.net>
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};