blob: 68a9554961eb41544c6da01b38cb65821b9e6ef5 [file] [log] [blame]
Sven Eckelmann9f6446c2015-04-23 13:16:35 +02001/* Copyright (C) 2014-2015 B.A.T.M.A.N. contributors:
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01002 *
3 * Linus Lüssing
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
Linus Lüssingc5caf4e2014-02-15 17:47:49 +010018#include "multicast.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020019#include "main.h"
20
21#include <linux/atomic.h>
Linus Lüssing9c936e32015-06-16 17:10:25 +020022#include <linux/bitops.h>
Linus Lüssing8a4023c2015-06-16 17:10:26 +020023#include <linux/bug.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020024#include <linux/byteorder/generic.h>
25#include <linux/errno.h>
26#include <linux/etherdevice.h>
27#include <linux/fs.h>
28#include <linux/if_ether.h>
29#include <linux/in6.h>
30#include <linux/in.h>
31#include <linux/ip.h>
32#include <linux/ipv6.h>
33#include <linux/list.h>
34#include <linux/netdevice.h>
35#include <linux/rculist.h>
36#include <linux/rcupdate.h>
37#include <linux/skbuff.h>
38#include <linux/slab.h>
39#include <linux/spinlock.h>
40#include <linux/stddef.h>
41#include <linux/string.h>
42#include <linux/types.h>
43#include <net/addrconf.h>
44#include <net/ipv6.h>
45
46#include "packet.h"
Linus Lüssingc5caf4e2014-02-15 17:47:49 +010047#include "translation-table.h"
48
49/**
50 * batadv_mcast_mla_softif_get - get softif multicast listeners
51 * @dev: the device to collect multicast addresses from
52 * @mcast_list: a list to put found addresses into
53 *
54 * Collect multicast addresses of the local multicast listeners
55 * on the given soft interface, dev, in the given mcast_list.
56 *
57 * Returns -ENOMEM on memory allocation error or the number of
58 * items added to the mcast_list otherwise.
59 */
60static int batadv_mcast_mla_softif_get(struct net_device *dev,
61 struct hlist_head *mcast_list)
62{
63 struct netdev_hw_addr *mc_list_entry;
64 struct batadv_hw_addr *new;
65 int ret = 0;
66
67 netif_addr_lock_bh(dev);
68 netdev_for_each_mc_addr(mc_list_entry, dev) {
69 new = kmalloc(sizeof(*new), GFP_ATOMIC);
70 if (!new) {
71 ret = -ENOMEM;
72 break;
73 }
74
75 ether_addr_copy(new->addr, mc_list_entry->addr);
76 hlist_add_head(&new->list, mcast_list);
77 ret++;
78 }
79 netif_addr_unlock_bh(dev);
80
81 return ret;
82}
83
84/**
85 * batadv_mcast_mla_is_duplicate - check whether an address is in a list
86 * @mcast_addr: the multicast address to check
87 * @mcast_list: the list with multicast addresses to search in
88 *
89 * Returns true if the given address is already in the given list.
90 * Otherwise returns false.
91 */
92static bool batadv_mcast_mla_is_duplicate(uint8_t *mcast_addr,
93 struct hlist_head *mcast_list)
94{
95 struct batadv_hw_addr *mcast_entry;
96
97 hlist_for_each_entry(mcast_entry, mcast_list, list)
98 if (batadv_compare_eth(mcast_entry->addr, mcast_addr))
99 return true;
100
101 return false;
102}
103
104/**
105 * batadv_mcast_mla_list_free - free a list of multicast addresses
106 * @mcast_list: the list to free
107 *
108 * Removes and frees all items in the given mcast_list.
109 */
110static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
111{
112 struct batadv_hw_addr *mcast_entry;
113 struct hlist_node *tmp;
114
115 hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
116 hlist_del(&mcast_entry->list);
117 kfree(mcast_entry);
118 }
119}
120
121/**
122 * batadv_mcast_mla_tt_retract - clean up multicast listener announcements
123 * @bat_priv: the bat priv with all the soft interface information
124 * @mcast_list: a list of addresses which should _not_ be removed
125 *
126 * Retracts the announcement of any multicast listener from the
127 * translation table except the ones listed in the given mcast_list.
128 *
129 * If mcast_list is NULL then all are retracted.
130 */
131static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
132 struct hlist_head *mcast_list)
133{
134 struct batadv_hw_addr *mcast_entry;
135 struct hlist_node *tmp;
136
137 hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
138 list) {
139 if (mcast_list &&
140 batadv_mcast_mla_is_duplicate(mcast_entry->addr,
141 mcast_list))
142 continue;
143
144 batadv_tt_local_remove(bat_priv, mcast_entry->addr,
145 BATADV_NO_FLAGS,
146 "mcast TT outdated", false);
147
148 hlist_del(&mcast_entry->list);
149 kfree(mcast_entry);
150 }
151}
152
153/**
154 * batadv_mcast_mla_tt_add - add multicast listener announcements
155 * @bat_priv: the bat priv with all the soft interface information
156 * @mcast_list: a list of addresses which are going to get added
157 *
158 * Adds multicast listener announcements from the given mcast_list to the
159 * translation table if they have not been added yet.
160 */
161static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
162 struct hlist_head *mcast_list)
163{
164 struct batadv_hw_addr *mcast_entry;
165 struct hlist_node *tmp;
166
167 if (!mcast_list)
168 return;
169
170 hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
171 if (batadv_mcast_mla_is_duplicate(mcast_entry->addr,
172 &bat_priv->mcast.mla_list))
173 continue;
174
175 if (!batadv_tt_local_add(bat_priv->soft_iface,
176 mcast_entry->addr, BATADV_NO_FLAGS,
177 BATADV_NULL_IFINDEX, BATADV_NO_MARK))
178 continue;
179
180 hlist_del(&mcast_entry->list);
181 hlist_add_head(&mcast_entry->list, &bat_priv->mcast.mla_list);
182 }
183}
184
185/**
186 * batadv_mcast_has_bridge - check whether the soft-iface is bridged
187 * @bat_priv: the bat priv with all the soft interface information
188 *
189 * Checks whether there is a bridge on top of our soft interface. Returns
190 * true if so, false otherwise.
191 */
192static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
193{
194 struct net_device *upper = bat_priv->soft_iface;
195
196 rcu_read_lock();
197 do {
198 upper = netdev_master_upper_dev_get_rcu(upper);
199 } while (upper && !(upper->priv_flags & IFF_EBRIDGE));
200 rcu_read_unlock();
201
202 return upper;
203}
204
205/**
Linus Lüssing60432d72014-02-15 17:47:51 +0100206 * batadv_mcast_mla_tvlv_update - update multicast tvlv
207 * @bat_priv: the bat priv with all the soft interface information
208 *
209 * Updates the own multicast tvlv with our current multicast related settings,
210 * capabilities and inabilities.
211 *
212 * Returns true if the tvlv container is registered afterwards. Otherwise
213 * returns false.
214 */
215static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv)
216{
217 struct batadv_tvlv_mcast_data mcast_data;
218
219 mcast_data.flags = BATADV_NO_FLAGS;
220 memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));
221
222 /* Avoid attaching MLAs, if there is a bridge on top of our soft
223 * interface, we don't support that yet (TODO)
224 */
225 if (batadv_mcast_has_bridge(bat_priv)) {
226 if (bat_priv->mcast.enabled) {
227 batadv_tvlv_container_unregister(bat_priv,
228 BATADV_TVLV_MCAST, 1);
229 bat_priv->mcast.enabled = false;
230 }
231
232 return false;
233 }
234
235 if (!bat_priv->mcast.enabled ||
236 mcast_data.flags != bat_priv->mcast.flags) {
237 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1,
238 &mcast_data, sizeof(mcast_data));
239 bat_priv->mcast.flags = mcast_data.flags;
240 bat_priv->mcast.enabled = true;
241 }
242
243 return true;
244}
245
246/**
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100247 * batadv_mcast_mla_update - update the own MLAs
248 * @bat_priv: the bat priv with all the soft interface information
249 *
Linus Lüssing60432d72014-02-15 17:47:51 +0100250 * Updates the own multicast listener announcements in the translation
251 * table as well as the own, announced multicast tvlv container.
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100252 */
253void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
254{
255 struct net_device *soft_iface = bat_priv->soft_iface;
256 struct hlist_head mcast_list = HLIST_HEAD_INIT;
257 int ret;
258
Linus Lüssing60432d72014-02-15 17:47:51 +0100259 if (!batadv_mcast_mla_tvlv_update(bat_priv))
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100260 goto update;
261
262 ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
263 if (ret < 0)
264 goto out;
265
266update:
267 batadv_mcast_mla_tt_retract(bat_priv, &mcast_list);
268 batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
269
270out:
271 batadv_mcast_mla_list_free(&mcast_list);
272}
273
274/**
Linus Lüssingab498862014-02-15 17:47:53 +0100275 * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential
276 * @bat_priv: the bat priv with all the soft interface information
277 * @skb: the IPv4 packet to check
278 * @is_unsnoopable: stores whether the destination is snoopable
279 *
280 * Checks whether the given IPv4 packet has the potential to be forwarded with a
281 * mode more optimal than classic flooding.
282 *
283 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM in case of
284 * memory allocation failure.
285 */
286static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv,
287 struct sk_buff *skb,
288 bool *is_unsnoopable)
289{
290 struct iphdr *iphdr;
291
292 /* We might fail due to out-of-memory -> drop it */
293 if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr)))
294 return -ENOMEM;
295
296 iphdr = ip_hdr(skb);
297
298 /* TODO: Implement Multicast Router Discovery (RFC4286),
299 * then allow scope > link local, too
300 */
301 if (!ipv4_is_local_multicast(iphdr->daddr))
302 return -EINVAL;
303
304 /* link-local multicast listeners behind a bridge are
305 * not snoopable (see RFC4541, section 2.1.2.2)
306 */
307 *is_unsnoopable = true;
308
309 return 0;
310}
311
312/**
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100313 * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential
314 * @bat_priv: the bat priv with all the soft interface information
315 * @skb: the IPv6 packet to check
Linus Lüssingab498862014-02-15 17:47:53 +0100316 * @is_unsnoopable: stores whether the destination is snoopable
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100317 *
318 * Checks whether the given IPv6 packet has the potential to be forwarded with a
319 * mode more optimal than classic flooding.
320 *
321 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
322 * of memory.
323 */
324static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv,
Linus Lüssingab498862014-02-15 17:47:53 +0100325 struct sk_buff *skb,
326 bool *is_unsnoopable)
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100327{
328 struct ipv6hdr *ip6hdr;
329
330 /* We might fail due to out-of-memory -> drop it */
331 if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr)))
332 return -ENOMEM;
333
334 ip6hdr = ipv6_hdr(skb);
335
336 /* TODO: Implement Multicast Router Discovery (RFC4286),
337 * then allow scope > link local, too
338 */
339 if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL)
340 return -EINVAL;
341
342 /* link-local-all-nodes multicast listeners behind a bridge are
343 * not snoopable (see RFC4541, section 3, paragraph 3)
344 */
345 if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr))
Linus Lüssingab498862014-02-15 17:47:53 +0100346 *is_unsnoopable = true;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100347
348 return 0;
349}
350
351/**
352 * batadv_mcast_forw_mode_check - check for optimized forwarding potential
353 * @bat_priv: the bat priv with all the soft interface information
354 * @skb: the multicast frame to check
Linus Lüssingab498862014-02-15 17:47:53 +0100355 * @is_unsnoopable: stores whether the destination is snoopable
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100356 *
357 * Checks whether the given multicast ethernet frame has the potential to be
358 * forwarded with a mode more optimal than classic flooding.
359 *
360 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
361 * of memory.
362 */
363static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
Linus Lüssingab498862014-02-15 17:47:53 +0100364 struct sk_buff *skb,
365 bool *is_unsnoopable)
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100366{
367 struct ethhdr *ethhdr = eth_hdr(skb);
368
369 if (!atomic_read(&bat_priv->multicast_mode))
370 return -EINVAL;
371
372 if (atomic_read(&bat_priv->mcast.num_disabled))
373 return -EINVAL;
374
375 switch (ntohs(ethhdr->h_proto)) {
Linus Lüssingab498862014-02-15 17:47:53 +0100376 case ETH_P_IP:
377 return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb,
378 is_unsnoopable);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100379 case ETH_P_IPV6:
Linus Lüssingab498862014-02-15 17:47:53 +0100380 return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb,
381 is_unsnoopable);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100382 default:
383 return -EINVAL;
384 }
385}
386
387/**
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100388 * batadv_mcast_want_all_ip_count - count nodes with unspecific mcast interest
389 * @bat_priv: the bat priv with all the soft interface information
390 * @ethhdr: ethernet header of a packet
391 *
392 * Returns the number of nodes which want all IPv4 multicast traffic if the
393 * given ethhdr is from an IPv4 packet or the number of nodes which want all
394 * IPv6 traffic if it matches an IPv6 packet.
395 */
396static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv,
397 struct ethhdr *ethhdr)
398{
399 switch (ntohs(ethhdr->h_proto)) {
400 case ETH_P_IP:
401 return atomic_read(&bat_priv->mcast.num_want_all_ipv4);
402 case ETH_P_IPV6:
403 return atomic_read(&bat_priv->mcast.num_want_all_ipv6);
404 default:
405 /* we shouldn't be here... */
406 return 0;
407 }
408}
409
410/**
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100411 * batadv_mcast_forw_tt_node_get - get a multicast tt node
412 * @bat_priv: the bat priv with all the soft interface information
413 * @ethhdr: the ether header containing the multicast destination
414 *
415 * Returns an orig_node matching the multicast address provided by ethhdr
416 * via a translation table lookup. This increases the returned nodes refcount.
417 */
418static struct batadv_orig_node *
419batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv,
420 struct ethhdr *ethhdr)
421{
422 return batadv_transtable_search(bat_priv, ethhdr->h_source,
423 ethhdr->h_dest, BATADV_NO_FLAGS);
424}
425
426/**
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100427 * batadv_mcast_want_forw_ipv4_node_get - get a node with an ipv4 flag
428 * @bat_priv: the bat priv with all the soft interface information
429 *
430 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and
431 * increases its refcount.
432 */
433static struct batadv_orig_node *
434batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
435{
436 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
437
438 rcu_read_lock();
439 hlist_for_each_entry_rcu(tmp_orig_node,
440 &bat_priv->mcast.want_all_ipv4_list,
441 mcast_want_all_ipv4_node) {
Marek Lindneraf0a1712014-04-24 03:41:26 +0800442 if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100443 continue;
444
445 orig_node = tmp_orig_node;
446 break;
447 }
448 rcu_read_unlock();
449
450 return orig_node;
451}
452
453/**
454 * batadv_mcast_want_forw_ipv6_node_get - get a node with an ipv6 flag
455 * @bat_priv: the bat priv with all the soft interface information
456 *
457 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set
458 * and increases its refcount.
459 */
460static struct batadv_orig_node *
461batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
462{
463 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
464
465 rcu_read_lock();
466 hlist_for_each_entry_rcu(tmp_orig_node,
467 &bat_priv->mcast.want_all_ipv6_list,
468 mcast_want_all_ipv6_node) {
Marek Lindneraf0a1712014-04-24 03:41:26 +0800469 if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100470 continue;
471
472 orig_node = tmp_orig_node;
473 break;
474 }
475 rcu_read_unlock();
476
477 return orig_node;
478}
479
480/**
481 * batadv_mcast_want_forw_ip_node_get - get a node with an ipv4/ipv6 flag
482 * @bat_priv: the bat priv with all the soft interface information
483 * @ethhdr: an ethernet header to determine the protocol family from
484 *
485 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or
486 * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and
487 * increases its refcount.
488 */
489static struct batadv_orig_node *
490batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv,
491 struct ethhdr *ethhdr)
492{
493 switch (ntohs(ethhdr->h_proto)) {
494 case ETH_P_IP:
495 return batadv_mcast_forw_ipv4_node_get(bat_priv);
496 case ETH_P_IPV6:
497 return batadv_mcast_forw_ipv6_node_get(bat_priv);
498 default:
499 /* we shouldn't be here... */
500 return NULL;
501 }
502}
503
504/**
Linus Lüssingab498862014-02-15 17:47:53 +0100505 * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag
506 * @bat_priv: the bat priv with all the soft interface information
507 *
508 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag
509 * set and increases its refcount.
510 */
511static struct batadv_orig_node *
512batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv)
513{
514 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
515
516 rcu_read_lock();
517 hlist_for_each_entry_rcu(tmp_orig_node,
518 &bat_priv->mcast.want_all_unsnoopables_list,
519 mcast_want_all_unsnoopables_node) {
Marek Lindneraf0a1712014-04-24 03:41:26 +0800520 if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
Linus Lüssingab498862014-02-15 17:47:53 +0100521 continue;
522
523 orig_node = tmp_orig_node;
524 break;
525 }
526 rcu_read_unlock();
527
528 return orig_node;
529}
530
531/**
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100532 * batadv_mcast_forw_mode - check on how to forward a multicast packet
533 * @bat_priv: the bat priv with all the soft interface information
534 * @skb: The multicast packet to check
535 * @orig: an originator to be set to forward the skb to
536 *
537 * Returns the forwarding mode as enum batadv_forw_mode and in case of
538 * BATADV_FORW_SINGLE set the orig to the single originator the skb
539 * should be forwarded to.
540 */
541enum batadv_forw_mode
542batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
543 struct batadv_orig_node **orig)
544{
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100545 int ret, tt_count, ip_count, unsnoop_count, total_count;
Linus Lüssingab498862014-02-15 17:47:53 +0100546 bool is_unsnoopable = false;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100547 struct ethhdr *ethhdr;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100548
Linus Lüssingab498862014-02-15 17:47:53 +0100549 ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100550 if (ret == -ENOMEM)
551 return BATADV_FORW_NONE;
552 else if (ret < 0)
553 return BATADV_FORW_ALL;
554
555 ethhdr = eth_hdr(skb);
556
557 tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest,
558 BATADV_NO_FLAGS);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100559 ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
Linus Lüssingab498862014-02-15 17:47:53 +0100560 unsnoop_count = !is_unsnoopable ? 0 :
561 atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100562
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100563 total_count = tt_count + ip_count + unsnoop_count;
Linus Lüssingab498862014-02-15 17:47:53 +0100564
565 switch (total_count) {
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100566 case 1:
Linus Lüssingab498862014-02-15 17:47:53 +0100567 if (tt_count)
568 *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100569 else if (ip_count)
570 *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr);
Linus Lüssingab498862014-02-15 17:47:53 +0100571 else if (unsnoop_count)
572 *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv);
573
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100574 if (*orig)
575 return BATADV_FORW_SINGLE;
576
577 /* fall through */
578 case 0:
579 return BATADV_FORW_NONE;
580 default:
581 return BATADV_FORW_ALL;
582 }
583}
584
585/**
Linus Lüssingab498862014-02-15 17:47:53 +0100586 * batadv_mcast_want_unsnoop_update - update unsnoop counter and list
587 * @bat_priv: the bat priv with all the soft interface information
588 * @orig: the orig_node which multicast state might have changed of
589 * @mcast_flags: flags indicating the new multicast state
590 *
591 * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator,
592 * orig, has toggled then this method updates counter and list accordingly.
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200593 *
594 * Caller needs to hold orig->mcast_handler_lock.
Linus Lüssingab498862014-02-15 17:47:53 +0100595 */
596static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
597 struct batadv_orig_node *orig,
598 uint8_t mcast_flags)
599{
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200600 struct hlist_node *node = &orig->mcast_want_all_unsnoopables_node;
601 struct hlist_head *head = &bat_priv->mcast.want_all_unsnoopables_list;
602
Linus Lüssingab498862014-02-15 17:47:53 +0100603 /* switched from flag unset to set */
604 if (mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
605 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)) {
606 atomic_inc(&bat_priv->mcast.num_want_all_unsnoopables);
607
608 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200609 /* flag checks above + mcast_handler_lock prevents this */
610 WARN_ON(!hlist_unhashed(node));
611
612 hlist_add_head_rcu(node, head);
Linus Lüssingab498862014-02-15 17:47:53 +0100613 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
614 /* switched from flag set to unset */
615 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) &&
616 orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) {
617 atomic_dec(&bat_priv->mcast.num_want_all_unsnoopables);
618
619 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200620 /* flag checks above + mcast_handler_lock prevents this */
621 WARN_ON(hlist_unhashed(node));
622
623 hlist_del_init_rcu(node);
Linus Lüssingab498862014-02-15 17:47:53 +0100624 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
625 }
626}
627
628/**
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100629 * batadv_mcast_want_ipv4_update - update want-all-ipv4 counter and list
630 * @bat_priv: the bat priv with all the soft interface information
631 * @orig: the orig_node which multicast state might have changed of
632 * @mcast_flags: flags indicating the new multicast state
633 *
634 * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has
635 * toggled then this method updates counter and list accordingly.
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200636 *
637 * Caller needs to hold orig->mcast_handler_lock.
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100638 */
639static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
640 struct batadv_orig_node *orig,
641 uint8_t mcast_flags)
642{
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200643 struct hlist_node *node = &orig->mcast_want_all_ipv4_node;
644 struct hlist_head *head = &bat_priv->mcast.want_all_ipv4_list;
645
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100646 /* switched from flag unset to set */
647 if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4 &&
648 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)) {
649 atomic_inc(&bat_priv->mcast.num_want_all_ipv4);
650
651 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200652 /* flag checks above + mcast_handler_lock prevents this */
653 WARN_ON(!hlist_unhashed(node));
654
655 hlist_add_head_rcu(node, head);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100656 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
657 /* switched from flag set to unset */
658 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) &&
659 orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) {
660 atomic_dec(&bat_priv->mcast.num_want_all_ipv4);
661
662 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200663 /* flag checks above + mcast_handler_lock prevents this */
664 WARN_ON(hlist_unhashed(node));
665
666 hlist_del_init_rcu(node);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100667 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
668 }
669}
670
671/**
672 * batadv_mcast_want_ipv6_update - update want-all-ipv6 counter and list
673 * @bat_priv: the bat priv with all the soft interface information
674 * @orig: the orig_node which multicast state might have changed of
675 * @mcast_flags: flags indicating the new multicast state
676 *
677 * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has
678 * toggled then this method updates counter and list accordingly.
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200679 *
680 * Caller needs to hold orig->mcast_handler_lock.
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100681 */
682static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
683 struct batadv_orig_node *orig,
684 uint8_t mcast_flags)
685{
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200686 struct hlist_node *node = &orig->mcast_want_all_ipv6_node;
687 struct hlist_head *head = &bat_priv->mcast.want_all_ipv6_list;
688
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100689 /* switched from flag unset to set */
690 if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6 &&
691 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)) {
692 atomic_inc(&bat_priv->mcast.num_want_all_ipv6);
693
694 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200695 /* flag checks above + mcast_handler_lock prevents this */
696 WARN_ON(!hlist_unhashed(node));
697
698 hlist_add_head_rcu(node, head);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100699 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
700 /* switched from flag set to unset */
701 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) &&
702 orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) {
703 atomic_dec(&bat_priv->mcast.num_want_all_ipv6);
704
705 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200706 /* flag checks above + mcast_handler_lock prevents this */
707 WARN_ON(hlist_unhashed(node));
708
709 hlist_del_init_rcu(node);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100710 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
711 }
712}
713
714/**
Linus Lüssing60432d72014-02-15 17:47:51 +0100715 * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
716 * @bat_priv: the bat priv with all the soft interface information
717 * @orig: the orig_node of the ogm
718 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
719 * @tvlv_value: tvlv buffer containing the multicast data
720 * @tvlv_value_len: tvlv buffer length
721 */
722static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
723 struct batadv_orig_node *orig,
724 uint8_t flags,
725 void *tvlv_value,
726 uint16_t tvlv_value_len)
727{
728 bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
729 uint8_t mcast_flags = BATADV_NO_FLAGS;
730 bool orig_initialized;
731
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200732 if (orig_mcast_enabled && tvlv_value &&
733 (tvlv_value_len >= sizeof(mcast_flags)))
734 mcast_flags = *(uint8_t *)tvlv_value;
735
736 spin_lock_bh(&orig->mcast_handler_lock);
Linus Lüssing9c936e32015-06-16 17:10:25 +0200737 orig_initialized = test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
738 &orig->capa_initialized);
Linus Lüssing60432d72014-02-15 17:47:51 +0100739
740 /* If mcast support is turned on decrease the disabled mcast node
741 * counter only if we had increased it for this node before. If this
742 * is a completely new orig_node no need to decrease the counter.
743 */
744 if (orig_mcast_enabled &&
Linus Lüssing9c936e32015-06-16 17:10:25 +0200745 !test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities)) {
Linus Lüssing60432d72014-02-15 17:47:51 +0100746 if (orig_initialized)
747 atomic_dec(&bat_priv->mcast.num_disabled);
Linus Lüssing9c936e32015-06-16 17:10:25 +0200748 set_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities);
Linus Lüssinge8829f02014-10-30 05:40:46 +0100749 /* If mcast support is being switched off or if this is an initial
750 * OGM without mcast support then increase the disabled mcast
751 * node counter.
Linus Lüssing60432d72014-02-15 17:47:51 +0100752 */
753 } else if (!orig_mcast_enabled &&
Linus Lüssing9c936e32015-06-16 17:10:25 +0200754 (test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities) ||
Linus Lüssinge8829f02014-10-30 05:40:46 +0100755 !orig_initialized)) {
Linus Lüssing60432d72014-02-15 17:47:51 +0100756 atomic_inc(&bat_priv->mcast.num_disabled);
Linus Lüssing9c936e32015-06-16 17:10:25 +0200757 clear_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities);
Linus Lüssing60432d72014-02-15 17:47:51 +0100758 }
759
Linus Lüssing9c936e32015-06-16 17:10:25 +0200760 set_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capa_initialized);
Linus Lüssing60432d72014-02-15 17:47:51 +0100761
Linus Lüssingab498862014-02-15 17:47:53 +0100762 batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100763 batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags);
764 batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags);
Linus Lüssingab498862014-02-15 17:47:53 +0100765
Linus Lüssing60432d72014-02-15 17:47:51 +0100766 orig->mcast_flags = mcast_flags;
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200767 spin_unlock_bh(&orig->mcast_handler_lock);
Linus Lüssing60432d72014-02-15 17:47:51 +0100768}
769
770/**
771 * batadv_mcast_init - initialize the multicast optimizations structures
772 * @bat_priv: the bat priv with all the soft interface information
773 */
774void batadv_mcast_init(struct batadv_priv *bat_priv)
775{
776 batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1,
777 NULL, BATADV_TVLV_MCAST, 1,
778 BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
779}
780
781/**
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100782 * batadv_mcast_free - free the multicast optimizations structures
783 * @bat_priv: the bat priv with all the soft interface information
784 */
785void batadv_mcast_free(struct batadv_priv *bat_priv)
786{
Linus Lüssing60432d72014-02-15 17:47:51 +0100787 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
788 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
789
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100790 batadv_mcast_mla_tt_retract(bat_priv, NULL);
791}
Linus Lüssing60432d72014-02-15 17:47:51 +0100792
793/**
794 * batadv_mcast_purge_orig - reset originator global mcast state modifications
795 * @orig: the originator which is going to get purged
796 */
797void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
798{
799 struct batadv_priv *bat_priv = orig->bat_priv;
800
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200801 spin_lock_bh(&orig->mcast_handler_lock);
802
Linus Lüssing9c936e32015-06-16 17:10:25 +0200803 if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capabilities) &&
804 test_bit(BATADV_ORIG_CAPA_HAS_MCAST, &orig->capa_initialized))
Linus Lüssing60432d72014-02-15 17:47:51 +0100805 atomic_dec(&bat_priv->mcast.num_disabled);
Linus Lüssingab498862014-02-15 17:47:53 +0100806
807 batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
Linus Lüssing4c8755d2014-02-15 17:47:54 +0100808 batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
809 batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
Linus Lüssing8a4023c2015-06-16 17:10:26 +0200810
811 spin_unlock_bh(&orig->mcast_handler_lock);
Linus Lüssing60432d72014-02-15 17:47:51 +0100812}