diff options
author | Linus Lüssing <linus.luessing@web.de> | 2014-02-15 11:47:52 -0500 |
---|---|---|
committer | Antonio Quartulli <antonio@meshcoding.com> | 2014-03-22 04:18:57 -0400 |
commit | 1d8ab8d3c176d31530b3ffd4547cf731018e2a45 (patch) | |
tree | b62208972cdfb70a853ff5177c29154fd165bea7 /net/batman-adv | |
parent | 60432d756cf06e597ef9da511402dd059b112447 (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.c | 126 | ||||
-rw-r--r-- | net/batman-adv/multicast.h | 25 | ||||
-rw-r--r-- | net/batman-adv/send.c | 10 | ||||
-rw-r--r-- | net/batman-adv/send.h | 5 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 20 | ||||
-rw-r--r-- | net/batman-adv/sysfs.c | 6 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 91 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 2 | ||||
-rw-r--r-- | net/batman-adv/types.h | 7 |
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 | */ | ||
261 | static 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 | */ | ||
298 | static 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 | */ | ||
325 | static struct batadv_orig_node * | ||
326 | batadv_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 | */ | ||
343 | enum batadv_forw_mode | ||
344 | batadv_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 | */ | ||
29 | enum 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 | ||
23 | void batadv_mcast_mla_update(struct batadv_priv *bat_priv); | 37 | void batadv_mcast_mla_update(struct batadv_priv *bat_priv); |
24 | 38 | ||
39 | enum batadv_forw_mode | ||
40 | batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
41 | struct batadv_orig_node **mcast_single_orig); | ||
42 | |||
25 | void batadv_mcast_init(struct batadv_priv *bat_priv); | 43 | void batadv_mcast_init(struct batadv_priv *bat_priv); |
26 | 44 | ||
27 | void batadv_mcast_free(struct batadv_priv *bat_priv); | 45 | void 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 | ||
56 | static inline enum batadv_forw_mode | ||
57 | batadv_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 | |||
38 | static inline int batadv_mcast_init(struct batadv_priv *bat_priv) | 63 | static 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 | */ |
251 | static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | 251 | int 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); |
39 | int 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); | ||
39 | int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, | 44 | int 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 | ||
252 | send: | 254 | send: |
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); |
540 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, | 540 | static 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 | ||
543 | BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL); | ||
544 | #endif | ||
542 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 545 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
543 | BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); | 546 | BATADV_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 | */ | ||
205 | int 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 | |||
196 | static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) | 221 | static 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 | |||
1228 | out: | 1255 | out: |
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 | */ | ||
1602 | static void | ||
1603 | batadv_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 */ |
1567 | static void | 1614 | static void |
1568 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) | 1615 | batadv_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 | */ | ||
1585 | static void | 1638 | static void |
1586 | batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, | 1639 | batadv_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); | |||
29 | void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | 29 | void 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); |
32 | int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, | ||
33 | const uint8_t *addr, unsigned short vid); | ||
32 | struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, | 34 | struct 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 | */ |
915 | struct batadv_tt_global_entry { | 921 | struct 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 | }; |