hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/batman-adv/multicast.c
....@@ -1,19 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
2
-/* Copyright (C) 2014-2018 B.A.T.M.A.N. contributors:
2
+/* Copyright (C) 2014-2020 B.A.T.M.A.N. contributors:
33 *
44 * Linus Lüssing
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of version 2 of the GNU General Public
8
- * License as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
175 */
186
197 #include "multicast.h"
....@@ -32,6 +20,7 @@
3220 #include <linux/igmp.h>
3321 #include <linux/in.h>
3422 #include <linux/in6.h>
23
+#include <linux/inetdevice.h>
3524 #include <linux/ip.h>
3625 #include <linux/ipv6.h>
3726 #include <linux/jiffies.h>
....@@ -111,87 +100,236 @@
111100 }
112101
113102 /**
114
- * batadv_mcast_addr_is_ipv4() - check if multicast MAC is IPv4
115
- * @addr: the MAC address to check
103
+ * batadv_mcast_mla_rtr_flags_softif_get_ipv4() - get mcast router flags from
104
+ * node for IPv4
105
+ * @dev: the interface to check
116106 *
117
- * Return: True, if MAC address is one reserved for IPv4 multicast, false
118
- * otherwise.
107
+ * Checks the presence of an IPv4 multicast router on this node.
108
+ *
109
+ * Caller needs to hold rcu read lock.
110
+ *
111
+ * Return: BATADV_NO_FLAGS if present, BATADV_MCAST_WANT_NO_RTR4 otherwise.
119112 */
120
-static bool batadv_mcast_addr_is_ipv4(const u8 *addr)
113
+static u8 batadv_mcast_mla_rtr_flags_softif_get_ipv4(struct net_device *dev)
121114 {
122
- static const u8 prefix[] = {0x01, 0x00, 0x5E};
115
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
123116
124
- return memcmp(prefix, addr, sizeof(prefix)) == 0;
117
+ if (in_dev && IN_DEV_MFORWARD(in_dev))
118
+ return BATADV_NO_FLAGS;
119
+ else
120
+ return BATADV_MCAST_WANT_NO_RTR4;
125121 }
126122
127123 /**
128
- * batadv_mcast_addr_is_ipv6() - check if multicast MAC is IPv6
129
- * @addr: the MAC address to check
124
+ * batadv_mcast_mla_rtr_flags_softif_get_ipv6() - get mcast router flags from
125
+ * node for IPv6
126
+ * @dev: the interface to check
130127 *
131
- * Return: True, if MAC address is one reserved for IPv6 multicast, false
132
- * otherwise.
128
+ * Checks the presence of an IPv6 multicast router on this node.
129
+ *
130
+ * Caller needs to hold rcu read lock.
131
+ *
132
+ * Return: BATADV_NO_FLAGS if present, BATADV_MCAST_WANT_NO_RTR6 otherwise.
133133 */
134
-static bool batadv_mcast_addr_is_ipv6(const u8 *addr)
134
+#if IS_ENABLED(CONFIG_IPV6_MROUTE)
135
+static u8 batadv_mcast_mla_rtr_flags_softif_get_ipv6(struct net_device *dev)
135136 {
136
- static const u8 prefix[] = {0x33, 0x33};
137
+ struct inet6_dev *in6_dev = __in6_dev_get(dev);
137138
138
- return memcmp(prefix, addr, sizeof(prefix)) == 0;
139
+ if (in6_dev && atomic_read(&in6_dev->cnf.mc_forwarding))
140
+ return BATADV_NO_FLAGS;
141
+ else
142
+ return BATADV_MCAST_WANT_NO_RTR6;
139143 }
144
+#else
145
+static inline u8
146
+batadv_mcast_mla_rtr_flags_softif_get_ipv6(struct net_device *dev)
147
+{
148
+ return BATADV_MCAST_WANT_NO_RTR6;
149
+}
150
+#endif
140151
141152 /**
142
- * batadv_mcast_mla_softif_get() - get softif multicast listeners
153
+ * batadv_mcast_mla_rtr_flags_softif_get() - get mcast router flags from node
143154 * @bat_priv: the bat priv with all the soft interface information
144
- * @dev: the device to collect multicast addresses from
145
- * @mcast_list: a list to put found addresses into
155
+ * @bridge: bridge interface on top of the soft_iface if present,
156
+ * otherwise pass NULL
146157 *
147
- * Collects multicast addresses of multicast listeners residing
148
- * on this kernel on the given soft interface, dev, in
149
- * the given mcast_list. In general, multicast listeners provided by
150
- * your multicast receiving applications run directly on this node.
158
+ * Checks the presence of IPv4 and IPv6 multicast routers on this
159
+ * node.
151160 *
152
- * If there is a bridge interface on top of dev, collects from that one
153
- * instead. Just like with IP addresses and routes, multicast listeners
154
- * will(/should) register to the bridge interface instead of an
155
- * enslaved bat0.
156
- *
157
- * Return: -ENOMEM on memory allocation error or the number of
158
- * items added to the mcast_list otherwise.
161
+ * Return:
162
+ * BATADV_NO_FLAGS: Both an IPv4 and IPv6 multicast router is present
163
+ * BATADV_MCAST_WANT_NO_RTR4: No IPv4 multicast router is present
164
+ * BATADV_MCAST_WANT_NO_RTR6: No IPv6 multicast router is present
165
+ * The former two OR'd: no multicast router is present
159166 */
160
-static int batadv_mcast_mla_softif_get(struct batadv_priv *bat_priv,
161
- struct net_device *dev,
162
- struct hlist_head *mcast_list)
167
+static u8 batadv_mcast_mla_rtr_flags_softif_get(struct batadv_priv *bat_priv,
168
+ struct net_device *bridge)
163169 {
164
- bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4;
165
- bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6;
166
- struct net_device *bridge = batadv_mcast_get_bridge(dev);
167
- struct netdev_hw_addr *mc_list_entry;
168
- struct batadv_hw_addr *new;
169
- int ret = 0;
170
+ struct net_device *dev = bridge ? bridge : bat_priv->soft_iface;
171
+ u8 flags = BATADV_NO_FLAGS;
170172
171
- netif_addr_lock_bh(bridge ? bridge : dev);
172
- netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) {
173
- if (all_ipv4 && batadv_mcast_addr_is_ipv4(mc_list_entry->addr))
174
- continue;
173
+ rcu_read_lock();
175174
176
- if (all_ipv6 && batadv_mcast_addr_is_ipv6(mc_list_entry->addr))
177
- continue;
175
+ flags |= batadv_mcast_mla_rtr_flags_softif_get_ipv4(dev);
176
+ flags |= batadv_mcast_mla_rtr_flags_softif_get_ipv6(dev);
178177
179
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
180
- if (!new) {
181
- ret = -ENOMEM;
182
- break;
183
- }
178
+ rcu_read_unlock();
184179
185
- ether_addr_copy(new->addr, mc_list_entry->addr);
186
- hlist_add_head(&new->list, mcast_list);
187
- ret++;
180
+ return flags;
181
+}
182
+
183
+/**
184
+ * batadv_mcast_mla_rtr_flags_bridge_get() - get mcast router flags from bridge
185
+ * @bat_priv: the bat priv with all the soft interface information
186
+ * @bridge: bridge interface on top of the soft_iface if present,
187
+ * otherwise pass NULL
188
+ *
189
+ * Checks the presence of IPv4 and IPv6 multicast routers behind a bridge.
190
+ *
191
+ * Return:
192
+ * BATADV_NO_FLAGS: Both an IPv4 and IPv6 multicast router is present
193
+ * BATADV_MCAST_WANT_NO_RTR4: No IPv4 multicast router is present
194
+ * BATADV_MCAST_WANT_NO_RTR6: No IPv6 multicast router is present
195
+ * The former two OR'd: no multicast router is present
196
+ */
197
+#if IS_ENABLED(CONFIG_IPV6)
198
+static u8 batadv_mcast_mla_rtr_flags_bridge_get(struct batadv_priv *bat_priv,
199
+ struct net_device *bridge)
200
+{
201
+ struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
202
+ struct net_device *dev = bat_priv->soft_iface;
203
+ struct br_ip_list *br_ip_entry, *tmp;
204
+ u8 flags = BATADV_MCAST_WANT_NO_RTR6;
205
+ int ret;
206
+
207
+ if (!bridge)
208
+ return BATADV_MCAST_WANT_NO_RTR4 | BATADV_MCAST_WANT_NO_RTR6;
209
+
210
+ /* TODO: ask the bridge if a multicast router is present (the bridge
211
+ * is capable of performing proper RFC4286 multicast router
212
+ * discovery) instead of searching for a ff02::2 listener here
213
+ */
214
+ ret = br_multicast_list_adjacent(dev, &bridge_mcast_list);
215
+ if (ret < 0)
216
+ return BATADV_NO_FLAGS;
217
+
218
+ list_for_each_entry_safe(br_ip_entry, tmp, &bridge_mcast_list, list) {
219
+ /* the bridge snooping does not maintain IPv4 link-local
220
+ * addresses - therefore we won't find any IPv4 multicast router
221
+ * address here, only IPv6 ones
222
+ */
223
+ if (br_ip_entry->addr.proto == htons(ETH_P_IPV6) &&
224
+ ipv6_addr_is_ll_all_routers(&br_ip_entry->addr.dst.ip6))
225
+ flags &= ~BATADV_MCAST_WANT_NO_RTR6;
226
+
227
+ list_del(&br_ip_entry->list);
228
+ kfree(br_ip_entry);
188229 }
189
- netif_addr_unlock_bh(bridge ? bridge : dev);
190230
231
+ return flags;
232
+}
233
+#else
234
+static inline u8
235
+batadv_mcast_mla_rtr_flags_bridge_get(struct batadv_priv *bat_priv,
236
+ struct net_device *bridge)
237
+{
191238 if (bridge)
192
- dev_put(bridge);
239
+ return BATADV_NO_FLAGS;
240
+ else
241
+ return BATADV_MCAST_WANT_NO_RTR4 | BATADV_MCAST_WANT_NO_RTR6;
242
+}
243
+#endif
193244
194
- return ret;
245
+/**
246
+ * batadv_mcast_mla_rtr_flags_get() - get multicast router flags
247
+ * @bat_priv: the bat priv with all the soft interface information
248
+ * @bridge: bridge interface on top of the soft_iface if present,
249
+ * otherwise pass NULL
250
+ *
251
+ * Checks the presence of IPv4 and IPv6 multicast routers on this
252
+ * node or behind its bridge.
253
+ *
254
+ * Return:
255
+ * BATADV_NO_FLAGS: Both an IPv4 and IPv6 multicast router is present
256
+ * BATADV_MCAST_WANT_NO_RTR4: No IPv4 multicast router is present
257
+ * BATADV_MCAST_WANT_NO_RTR6: No IPv6 multicast router is present
258
+ * The former two OR'd: no multicast router is present
259
+ */
260
+static u8 batadv_mcast_mla_rtr_flags_get(struct batadv_priv *bat_priv,
261
+ struct net_device *bridge)
262
+{
263
+ u8 flags = BATADV_MCAST_WANT_NO_RTR4 | BATADV_MCAST_WANT_NO_RTR6;
264
+
265
+ flags &= batadv_mcast_mla_rtr_flags_softif_get(bat_priv, bridge);
266
+ flags &= batadv_mcast_mla_rtr_flags_bridge_get(bat_priv, bridge);
267
+
268
+ return flags;
269
+}
270
+
271
+/**
272
+ * batadv_mcast_mla_flags_get() - get the new multicast flags
273
+ * @bat_priv: the bat priv with all the soft interface information
274
+ *
275
+ * Return: A set of flags for the current/next TVLV, querier and
276
+ * bridge state.
277
+ */
278
+static struct batadv_mcast_mla_flags
279
+batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv)
280
+{
281
+ struct net_device *dev = bat_priv->soft_iface;
282
+ struct batadv_mcast_querier_state *qr4, *qr6;
283
+ struct batadv_mcast_mla_flags mla_flags;
284
+ struct net_device *bridge;
285
+
286
+ bridge = batadv_mcast_get_bridge(dev);
287
+
288
+ memset(&mla_flags, 0, sizeof(mla_flags));
289
+ mla_flags.enabled = 1;
290
+ mla_flags.tvlv_flags |= batadv_mcast_mla_rtr_flags_get(bat_priv,
291
+ bridge);
292
+
293
+ if (!bridge)
294
+ return mla_flags;
295
+
296
+ dev_put(bridge);
297
+
298
+ mla_flags.bridged = 1;
299
+ qr4 = &mla_flags.querier_ipv4;
300
+ qr6 = &mla_flags.querier_ipv6;
301
+
302
+ if (!IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING))
303
+ pr_warn_once("No bridge IGMP snooping compiled - multicast optimizations disabled\n");
304
+
305
+ qr4->exists = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
306
+ qr4->shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
307
+
308
+ qr6->exists = br_multicast_has_querier_anywhere(dev, ETH_P_IPV6);
309
+ qr6->shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IPV6);
310
+
311
+ mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_UNSNOOPABLES;
312
+
313
+ /* 1) If no querier exists at all, then multicast listeners on
314
+ * our local TT clients behind the bridge will keep silent.
315
+ * 2) If the selected querier is on one of our local TT clients,
316
+ * behind the bridge, then this querier might shadow multicast
317
+ * listeners on our local TT clients, behind this bridge.
318
+ *
319
+ * In both cases, we will signalize other batman nodes that
320
+ * we need all multicast traffic of the according protocol.
321
+ */
322
+ if (!qr4->exists || qr4->shadowing) {
323
+ mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_IPV4;
324
+ mla_flags.tvlv_flags &= ~BATADV_MCAST_WANT_NO_RTR4;
325
+ }
326
+
327
+ if (!qr6->exists || qr6->shadowing) {
328
+ mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_IPV6;
329
+ mla_flags.tvlv_flags &= ~BATADV_MCAST_WANT_NO_RTR6;
330
+ }
331
+
332
+ return mla_flags;
195333 }
196334
197335 /**
....@@ -215,6 +353,201 @@
215353 }
216354
217355 /**
356
+ * batadv_mcast_mla_softif_get_ipv4() - get softif IPv4 multicast listeners
357
+ * @dev: the device to collect multicast addresses from
358
+ * @mcast_list: a list to put found addresses into
359
+ * @flags: flags indicating the new multicast state
360
+ *
361
+ * Collects multicast addresses of IPv4 multicast listeners residing
362
+ * on this kernel on the given soft interface, dev, in
363
+ * the given mcast_list. In general, multicast listeners provided by
364
+ * your multicast receiving applications run directly on this node.
365
+ *
366
+ * Return: -ENOMEM on memory allocation error or the number of
367
+ * items added to the mcast_list otherwise.
368
+ */
369
+static int
370
+batadv_mcast_mla_softif_get_ipv4(struct net_device *dev,
371
+ struct hlist_head *mcast_list,
372
+ struct batadv_mcast_mla_flags *flags)
373
+{
374
+ struct batadv_hw_addr *new;
375
+ struct in_device *in_dev;
376
+ u8 mcast_addr[ETH_ALEN];
377
+ struct ip_mc_list *pmc;
378
+ int ret = 0;
379
+
380
+ if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4)
381
+ return 0;
382
+
383
+ rcu_read_lock();
384
+
385
+ in_dev = __in_dev_get_rcu(dev);
386
+ if (!in_dev) {
387
+ rcu_read_unlock();
388
+ return 0;
389
+ }
390
+
391
+ for (pmc = rcu_dereference(in_dev->mc_list); pmc;
392
+ pmc = rcu_dereference(pmc->next_rcu)) {
393
+ if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
394
+ ipv4_is_local_multicast(pmc->multiaddr))
395
+ continue;
396
+
397
+ if (!(flags->tvlv_flags & BATADV_MCAST_WANT_NO_RTR4) &&
398
+ !ipv4_is_local_multicast(pmc->multiaddr))
399
+ continue;
400
+
401
+ ip_eth_mc_map(pmc->multiaddr, mcast_addr);
402
+
403
+ if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
404
+ continue;
405
+
406
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
407
+ if (!new) {
408
+ ret = -ENOMEM;
409
+ break;
410
+ }
411
+
412
+ ether_addr_copy(new->addr, mcast_addr);
413
+ hlist_add_head(&new->list, mcast_list);
414
+ ret++;
415
+ }
416
+ rcu_read_unlock();
417
+
418
+ return ret;
419
+}
420
+
421
+/**
422
+ * batadv_mcast_mla_softif_get_ipv6() - get softif IPv6 multicast listeners
423
+ * @dev: the device to collect multicast addresses from
424
+ * @mcast_list: a list to put found addresses into
425
+ * @flags: flags indicating the new multicast state
426
+ *
427
+ * Collects multicast addresses of IPv6 multicast listeners residing
428
+ * on this kernel on the given soft interface, dev, in
429
+ * the given mcast_list. In general, multicast listeners provided by
430
+ * your multicast receiving applications run directly on this node.
431
+ *
432
+ * Return: -ENOMEM on memory allocation error or the number of
433
+ * items added to the mcast_list otherwise.
434
+ */
435
+#if IS_ENABLED(CONFIG_IPV6)
436
+static int
437
+batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
438
+ struct hlist_head *mcast_list,
439
+ struct batadv_mcast_mla_flags *flags)
440
+{
441
+ struct batadv_hw_addr *new;
442
+ struct inet6_dev *in6_dev;
443
+ u8 mcast_addr[ETH_ALEN];
444
+ struct ifmcaddr6 *pmc6;
445
+ int ret = 0;
446
+
447
+ if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
448
+ return 0;
449
+
450
+ rcu_read_lock();
451
+
452
+ in6_dev = __in6_dev_get(dev);
453
+ if (!in6_dev) {
454
+ rcu_read_unlock();
455
+ return 0;
456
+ }
457
+
458
+ read_lock_bh(&in6_dev->lock);
459
+ for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
460
+ if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
461
+ IPV6_ADDR_SCOPE_LINKLOCAL)
462
+ continue;
463
+
464
+ if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
465
+ ipv6_addr_is_ll_all_nodes(&pmc6->mca_addr))
466
+ continue;
467
+
468
+ if (!(flags->tvlv_flags & BATADV_MCAST_WANT_NO_RTR6) &&
469
+ IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) >
470
+ IPV6_ADDR_SCOPE_LINKLOCAL)
471
+ continue;
472
+
473
+ ipv6_eth_mc_map(&pmc6->mca_addr, mcast_addr);
474
+
475
+ if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
476
+ continue;
477
+
478
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
479
+ if (!new) {
480
+ ret = -ENOMEM;
481
+ break;
482
+ }
483
+
484
+ ether_addr_copy(new->addr, mcast_addr);
485
+ hlist_add_head(&new->list, mcast_list);
486
+ ret++;
487
+ }
488
+ read_unlock_bh(&in6_dev->lock);
489
+ rcu_read_unlock();
490
+
491
+ return ret;
492
+}
493
+#else
494
+static inline int
495
+batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
496
+ struct hlist_head *mcast_list,
497
+ struct batadv_mcast_mla_flags *flags)
498
+{
499
+ return 0;
500
+}
501
+#endif
502
+
503
+/**
504
+ * batadv_mcast_mla_softif_get() - get softif multicast listeners
505
+ * @dev: the device to collect multicast addresses from
506
+ * @mcast_list: a list to put found addresses into
507
+ * @flags: flags indicating the new multicast state
508
+ *
509
+ * Collects multicast addresses of multicast listeners residing
510
+ * on this kernel on the given soft interface, dev, in
511
+ * the given mcast_list. In general, multicast listeners provided by
512
+ * your multicast receiving applications run directly on this node.
513
+ *
514
+ * If there is a bridge interface on top of dev, collect from that one
515
+ * instead. Just like with IP addresses and routes, multicast listeners
516
+ * will(/should) register to the bridge interface instead of an
517
+ * enslaved bat0.
518
+ *
519
+ * Return: -ENOMEM on memory allocation error or the number of
520
+ * items added to the mcast_list otherwise.
521
+ */
522
+static int
523
+batadv_mcast_mla_softif_get(struct net_device *dev,
524
+ struct hlist_head *mcast_list,
525
+ struct batadv_mcast_mla_flags *flags)
526
+{
527
+ struct net_device *bridge = batadv_mcast_get_bridge(dev);
528
+ int ret4, ret6 = 0;
529
+
530
+ if (bridge)
531
+ dev = bridge;
532
+
533
+ ret4 = batadv_mcast_mla_softif_get_ipv4(dev, mcast_list, flags);
534
+ if (ret4 < 0)
535
+ goto out;
536
+
537
+ ret6 = batadv_mcast_mla_softif_get_ipv6(dev, mcast_list, flags);
538
+ if (ret6 < 0) {
539
+ ret4 = 0;
540
+ goto out;
541
+ }
542
+
543
+out:
544
+ if (bridge)
545
+ dev_put(bridge);
546
+
547
+ return ret4 + ret6;
548
+}
549
+
550
+/**
218551 * batadv_mcast_mla_br_addr_cpy() - copy a bridge multicast address
219552 * @dst: destination to write to - a multicast MAC address
220553 * @src: source to read from - a multicast IP address
....@@ -229,10 +562,10 @@
229562 static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src)
230563 {
231564 if (src->proto == htons(ETH_P_IP))
232
- ip_eth_mc_map(src->u.ip4, dst);
565
+ ip_eth_mc_map(src->dst.ip4, dst);
233566 #if IS_ENABLED(CONFIG_IPV6)
234567 else if (src->proto == htons(ETH_P_IPV6))
235
- ipv6_eth_mc_map(&src->u.ip6, dst);
568
+ ipv6_eth_mc_map(&src->dst.ip6, dst);
236569 #endif
237570 else
238571 eth_zero_addr(dst);
....@@ -240,9 +573,9 @@
240573
241574 /**
242575 * batadv_mcast_mla_bridge_get() - get bridged-in multicast listeners
243
- * @bat_priv: the bat priv with all the soft interface information
244576 * @dev: a bridge slave whose bridge to collect multicast addresses from
245577 * @mcast_list: a list to put found addresses into
578
+ * @flags: flags indicating the new multicast state
246579 *
247580 * Collects multicast addresses of multicast listeners residing
248581 * on foreign, non-mesh devices which we gave access to our mesh via
....@@ -252,14 +585,13 @@
252585 * Return: -ENOMEM on memory allocation error or the number of
253586 * items added to the mcast_list otherwise.
254587 */
255
-static int batadv_mcast_mla_bridge_get(struct batadv_priv *bat_priv,
256
- struct net_device *dev,
257
- struct hlist_head *mcast_list)
588
+static int batadv_mcast_mla_bridge_get(struct net_device *dev,
589
+ struct hlist_head *mcast_list,
590
+ struct batadv_mcast_mla_flags *flags)
258591 {
259592 struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
260
- bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4;
261
- bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6;
262593 struct br_ip_list *br_ip_entry, *tmp;
594
+ u8 tvlv_flags = flags->tvlv_flags;
263595 struct batadv_hw_addr *new;
264596 u8 mcast_addr[ETH_ALEN];
265597 int ret;
....@@ -272,11 +604,34 @@
272604 goto out;
273605
274606 list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) {
275
- if (all_ipv4 && br_ip_entry->addr.proto == htons(ETH_P_IP))
276
- continue;
607
+ if (br_ip_entry->addr.proto == htons(ETH_P_IP)) {
608
+ if (tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4)
609
+ continue;
277610
278
- if (all_ipv6 && br_ip_entry->addr.proto == htons(ETH_P_IPV6))
279
- continue;
611
+ if (tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
612
+ ipv4_is_local_multicast(br_ip_entry->addr.dst.ip4))
613
+ continue;
614
+
615
+ if (!(tvlv_flags & BATADV_MCAST_WANT_NO_RTR4) &&
616
+ !ipv4_is_local_multicast(br_ip_entry->addr.dst.ip4))
617
+ continue;
618
+ }
619
+
620
+#if IS_ENABLED(CONFIG_IPV6)
621
+ if (br_ip_entry->addr.proto == htons(ETH_P_IPV6)) {
622
+ if (tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
623
+ continue;
624
+
625
+ if (tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
626
+ ipv6_addr_is_ll_all_nodes(&br_ip_entry->addr.dst.ip6))
627
+ continue;
628
+
629
+ if (!(tvlv_flags & BATADV_MCAST_WANT_NO_RTR6) &&
630
+ IPV6_ADDR_MC_SCOPE(&br_ip_entry->addr.dst.ip6) >
631
+ IPV6_ADDR_SCOPE_LINKLOCAL)
632
+ continue;
633
+ }
634
+#endif
280635
281636 batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr);
282637 if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
....@@ -383,27 +738,6 @@
383738 }
384739
385740 /**
386
- * batadv_mcast_has_bridge() - check whether the soft-iface is bridged
387
- * @bat_priv: the bat priv with all the soft interface information
388
- *
389
- * Checks whether there is a bridge on top of our soft interface.
390
- *
391
- * Return: true if there is a bridge, false otherwise.
392
- */
393
-static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
394
-{
395
- struct net_device *upper = bat_priv->soft_iface;
396
-
397
- rcu_read_lock();
398
- do {
399
- upper = netdev_master_upper_dev_get_rcu(upper);
400
- } while (upper && !(upper->priv_flags & IFF_EBRIDGE));
401
- rcu_read_unlock();
402
-
403
- return upper;
404
-}
405
-
406
-/**
407741 * batadv_mcast_querier_log() - debug output regarding the querier status on
408742 * link
409743 * @bat_priv: the bat priv with all the soft interface information
....@@ -437,7 +771,7 @@
437771 batadv_info(bat_priv->soft_iface,
438772 "%s Querier disappeared - multicast optimizations disabled\n",
439773 str_proto);
440
- else if (!bat_priv->mcast.bridged && !new_state->exists)
774
+ else if (!bat_priv->mcast.mla_flags.bridged && !new_state->exists)
441775 batadv_info(bat_priv->soft_iface,
442776 "No %s Querier present - multicast optimizations disabled\n",
443777 str_proto);
....@@ -459,9 +793,7 @@
459793 * batadv_mcast_bridge_log() - debug output for topology changes in bridged
460794 * setups
461795 * @bat_priv: the bat priv with all the soft interface information
462
- * @bridged: a flag about whether the soft interface is currently bridged or not
463
- * @querier_ipv4: (maybe) new status of a potential, selected IGMP querier
464
- * @querier_ipv6: (maybe) new status of a potential, selected MLD querier
796
+ * @new_flags: flags indicating the new multicast state
465797 *
466798 * If no bridges are ever used on this node, then this function does nothing.
467799 *
....@@ -474,126 +806,86 @@
474806 * multicast flags this node is going to set.
475807 */
476808 static void
477
-batadv_mcast_bridge_log(struct batadv_priv *bat_priv, bool bridged,
478
- struct batadv_mcast_querier_state *querier_ipv4,
479
- struct batadv_mcast_querier_state *querier_ipv6)
809
+batadv_mcast_bridge_log(struct batadv_priv *bat_priv,
810
+ struct batadv_mcast_mla_flags *new_flags)
480811 {
481
- if (!bat_priv->mcast.bridged && bridged)
812
+ struct batadv_mcast_mla_flags *old_flags = &bat_priv->mcast.mla_flags;
813
+
814
+ if (!old_flags->bridged && new_flags->bridged)
482815 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
483816 "Bridge added: Setting Unsnoopables(U)-flag\n");
484
- else if (bat_priv->mcast.bridged && !bridged)
817
+ else if (old_flags->bridged && !new_flags->bridged)
485818 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
486819 "Bridge removed: Unsetting Unsnoopables(U)-flag\n");
487820
488
- if (bridged) {
821
+ if (new_flags->bridged) {
489822 batadv_mcast_querier_log(bat_priv, "IGMP",
490
- &bat_priv->mcast.querier_ipv4,
491
- querier_ipv4);
823
+ &old_flags->querier_ipv4,
824
+ &new_flags->querier_ipv4);
492825 batadv_mcast_querier_log(bat_priv, "MLD",
493
- &bat_priv->mcast.querier_ipv6,
494
- querier_ipv6);
826
+ &old_flags->querier_ipv6,
827
+ &new_flags->querier_ipv6);
495828 }
496829 }
497830
498831 /**
499832 * batadv_mcast_flags_logs() - output debug information about mcast flag changes
500833 * @bat_priv: the bat priv with all the soft interface information
501
- * @flags: flags indicating the new multicast state
834
+ * @flags: TVLV flags indicating the new multicast state
502835 *
503
- * Whenever the multicast flags this nodes announces changes (@mcast_flags vs.
504
- * bat_priv->mcast.flags), this notifies userspace via the 'mcast' log level.
836
+ * Whenever the multicast TVLV flags this node announces change, this function
837
+ * should be used to notify userspace about the change.
505838 */
506839 static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
507840 {
508
- u8 old_flags = bat_priv->mcast.flags;
509
- char str_old_flags[] = "[...]";
841
+ bool old_enabled = bat_priv->mcast.mla_flags.enabled;
842
+ u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags;
843
+ char str_old_flags[] = "[.... . ]";
510844
511
- sprintf(str_old_flags, "[%c%c%c]",
845
+ sprintf(str_old_flags, "[%c%c%c%s%s]",
512846 (old_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
513847 (old_flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
514
- (old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
848
+ (old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
849
+ !(old_flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ",
850
+ !(old_flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ");
515851
516852 batadv_dbg(BATADV_DBG_MCAST, bat_priv,
517
- "Changing multicast flags from '%s' to '[%c%c%c]'\n",
518
- bat_priv->mcast.enabled ? str_old_flags : "<undefined>",
853
+ "Changing multicast flags from '%s' to '[%c%c%c%s%s]'\n",
854
+ old_enabled ? str_old_flags : "<undefined>",
519855 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
520856 (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
521
- (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
857
+ (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
858
+ !(flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ",
859
+ !(flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ");
522860 }
523861
524862 /**
525
- * batadv_mcast_mla_tvlv_update() - update multicast tvlv
863
+ * batadv_mcast_mla_flags_update() - update multicast flags
526864 * @bat_priv: the bat priv with all the soft interface information
865
+ * @flags: flags indicating the new multicast state
527866 *
528867 * Updates the own multicast tvlv with our current multicast related settings,
529868 * capabilities and inabilities.
530
- *
531
- * Return: false if we want all IPv4 && IPv6 multicast traffic and true
532
- * otherwise.
533869 */
534
-static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv)
870
+static void
871
+batadv_mcast_mla_flags_update(struct batadv_priv *bat_priv,
872
+ struct batadv_mcast_mla_flags *flags)
535873 {
536874 struct batadv_tvlv_mcast_data mcast_data;
537
- struct batadv_mcast_querier_state querier4 = {false, false};
538
- struct batadv_mcast_querier_state querier6 = {false, false};
539
- struct net_device *dev = bat_priv->soft_iface;
540
- bool bridged;
541875
542
- mcast_data.flags = BATADV_NO_FLAGS;
876
+ if (!memcmp(flags, &bat_priv->mcast.mla_flags, sizeof(*flags)))
877
+ return;
878
+
879
+ batadv_mcast_bridge_log(bat_priv, flags);
880
+ batadv_mcast_flags_log(bat_priv, flags->tvlv_flags);
881
+
882
+ mcast_data.flags = flags->tvlv_flags;
543883 memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));
544884
545
- bridged = batadv_mcast_has_bridge(bat_priv);
546
- if (!bridged)
547
- goto update;
885
+ batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2,
886
+ &mcast_data, sizeof(mcast_data));
548887
549
- if (!IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING))
550
- pr_warn_once("No bridge IGMP snooping compiled - multicast optimizations disabled\n");
551
-
552
- querier4.exists = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
553
- querier4.shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
554
-
555
- querier6.exists = br_multicast_has_querier_anywhere(dev, ETH_P_IPV6);
556
- querier6.shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IPV6);
557
-
558
- mcast_data.flags |= BATADV_MCAST_WANT_ALL_UNSNOOPABLES;
559
-
560
- /* 1) If no querier exists at all, then multicast listeners on
561
- * our local TT clients behind the bridge will keep silent.
562
- * 2) If the selected querier is on one of our local TT clients,
563
- * behind the bridge, then this querier might shadow multicast
564
- * listeners on our local TT clients, behind this bridge.
565
- *
566
- * In both cases, we will signalize other batman nodes that
567
- * we need all multicast traffic of the according protocol.
568
- */
569
- if (!querier4.exists || querier4.shadowing)
570
- mcast_data.flags |= BATADV_MCAST_WANT_ALL_IPV4;
571
-
572
- if (!querier6.exists || querier6.shadowing)
573
- mcast_data.flags |= BATADV_MCAST_WANT_ALL_IPV6;
574
-
575
-update:
576
- batadv_mcast_bridge_log(bat_priv, bridged, &querier4, &querier6);
577
-
578
- bat_priv->mcast.querier_ipv4.exists = querier4.exists;
579
- bat_priv->mcast.querier_ipv4.shadowing = querier4.shadowing;
580
-
581
- bat_priv->mcast.querier_ipv6.exists = querier6.exists;
582
- bat_priv->mcast.querier_ipv6.shadowing = querier6.shadowing;
583
-
584
- bat_priv->mcast.bridged = bridged;
585
-
586
- if (!bat_priv->mcast.enabled ||
587
- mcast_data.flags != bat_priv->mcast.flags) {
588
- batadv_mcast_flags_log(bat_priv, mcast_data.flags);
589
- batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2,
590
- &mcast_data, sizeof(mcast_data));
591
- bat_priv->mcast.flags = mcast_data.flags;
592
- bat_priv->mcast.enabled = true;
593
- }
594
-
595
- return !(mcast_data.flags & BATADV_MCAST_WANT_ALL_IPV4 &&
596
- mcast_data.flags & BATADV_MCAST_WANT_ALL_IPV6);
888
+ bat_priv->mcast.mla_flags = *flags;
597889 }
598890
599891 /**
....@@ -612,22 +904,24 @@
612904 {
613905 struct net_device *soft_iface = bat_priv->soft_iface;
614906 struct hlist_head mcast_list = HLIST_HEAD_INIT;
907
+ struct batadv_mcast_mla_flags flags;
615908 int ret;
616909
617
- if (!batadv_mcast_mla_tvlv_update(bat_priv))
618
- goto update;
910
+ flags = batadv_mcast_mla_flags_get(bat_priv);
619911
620
- ret = batadv_mcast_mla_softif_get(bat_priv, soft_iface, &mcast_list);
912
+ ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list, &flags);
621913 if (ret < 0)
622914 goto out;
623915
624
- ret = batadv_mcast_mla_bridge_get(bat_priv, soft_iface, &mcast_list);
916
+ ret = batadv_mcast_mla_bridge_get(soft_iface, &mcast_list, &flags);
625917 if (ret < 0)
626918 goto out;
627919
628
-update:
920
+ spin_lock(&bat_priv->mcast.mla_lock);
629921 batadv_mcast_mla_tt_retract(bat_priv, &mcast_list);
630922 batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
923
+ batadv_mcast_mla_flags_update(bat_priv, &flags);
924
+ spin_unlock(&bat_priv->mcast.mla_lock);
631925
632926 out:
633927 batadv_mcast_mla_list_free(&mcast_list);
....@@ -652,10 +946,7 @@
652946 priv_mcast = container_of(delayed_work, struct batadv_priv_mcast, work);
653947 bat_priv = container_of(priv_mcast, struct batadv_priv, mcast);
654948
655
- spin_lock(&bat_priv->mcast.mla_lock);
656949 __batadv_mcast_mla_update(bat_priv);
657
- spin_unlock(&bat_priv->mcast.mla_lock);
658
-
659950 batadv_mcast_start_timer(bat_priv);
660951 }
661952
....@@ -671,7 +962,7 @@
671962 */
672963 static bool batadv_mcast_is_report_ipv4(struct sk_buff *skb)
673964 {
674
- if (ip_mc_check_igmp(skb, NULL) < 0)
965
+ if (ip_mc_check_igmp(skb) < 0)
675966 return false;
676967
677968 switch (igmp_hdr(skb)->type) {
....@@ -690,6 +981,7 @@
690981 * @bat_priv: the bat priv with all the soft interface information
691982 * @skb: the IPv4 packet to check
692983 * @is_unsnoopable: stores whether the destination is snoopable
984
+ * @is_routable: stores whether the destination is routable
693985 *
694986 * Checks whether the given IPv4 packet has the potential to be forwarded with a
695987 * mode more optimal than classic flooding.
....@@ -699,7 +991,8 @@
699991 */
700992 static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv,
701993 struct sk_buff *skb,
702
- bool *is_unsnoopable)
994
+ bool *is_unsnoopable,
995
+ int *is_routable)
703996 {
704997 struct iphdr *iphdr;
705998
....@@ -712,16 +1005,13 @@
7121005
7131006 iphdr = ip_hdr(skb);
7141007
715
- /* TODO: Implement Multicast Router Discovery (RFC4286),
716
- * then allow scope > link local, too
717
- */
718
- if (!ipv4_is_local_multicast(iphdr->daddr))
719
- return -EINVAL;
720
-
7211008 /* link-local multicast listeners behind a bridge are
7221009 * not snoopable (see RFC4541, section 2.1.2.2)
7231010 */
724
- *is_unsnoopable = true;
1011
+ if (ipv4_is_local_multicast(iphdr->daddr))
1012
+ *is_unsnoopable = true;
1013
+ else
1014
+ *is_routable = ETH_P_IP;
7251015
7261016 return 0;
7271017 }
....@@ -738,7 +1028,7 @@
7381028 */
7391029 static bool batadv_mcast_is_report_ipv6(struct sk_buff *skb)
7401030 {
741
- if (ipv6_mc_check_mld(skb, NULL) < 0)
1031
+ if (ipv6_mc_check_mld(skb) < 0)
7421032 return false;
7431033
7441034 switch (icmp6_hdr(skb)->icmp6_type) {
....@@ -756,6 +1046,7 @@
7561046 * @bat_priv: the bat priv with all the soft interface information
7571047 * @skb: the IPv6 packet to check
7581048 * @is_unsnoopable: stores whether the destination is snoopable
1049
+ * @is_routable: stores whether the destination is routable
7591050 *
7601051 * Checks whether the given IPv6 packet has the potential to be forwarded with a
7611052 * mode more optimal than classic flooding.
....@@ -764,7 +1055,8 @@
7641055 */
7651056 static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv,
7661057 struct sk_buff *skb,
767
- bool *is_unsnoopable)
1058
+ bool *is_unsnoopable,
1059
+ int *is_routable)
7681060 {
7691061 struct ipv6hdr *ip6hdr;
7701062
....@@ -777,10 +1069,7 @@
7771069
7781070 ip6hdr = ipv6_hdr(skb);
7791071
780
- /* TODO: Implement Multicast Router Discovery (RFC4286),
781
- * then allow scope > link local, too
782
- */
783
- if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL)
1072
+ if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) < IPV6_ADDR_SCOPE_LINKLOCAL)
7841073 return -EINVAL;
7851074
7861075 /* link-local-all-nodes multicast listeners behind a bridge are
....@@ -788,6 +1077,8 @@
7881077 */
7891078 if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr))
7901079 *is_unsnoopable = true;
1080
+ else if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) > IPV6_ADDR_SCOPE_LINKLOCAL)
1081
+ *is_routable = ETH_P_IPV6;
7911082
7921083 return 0;
7931084 }
....@@ -797,6 +1088,7 @@
7971088 * @bat_priv: the bat priv with all the soft interface information
7981089 * @skb: the multicast frame to check
7991090 * @is_unsnoopable: stores whether the destination is snoopable
1091
+ * @is_routable: stores whether the destination is routable
8001092 *
8011093 * Checks whether the given multicast ethernet frame has the potential to be
8021094 * forwarded with a mode more optimal than classic flooding.
....@@ -805,7 +1097,8 @@
8051097 */
8061098 static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
8071099 struct sk_buff *skb,
808
- bool *is_unsnoopable)
1100
+ bool *is_unsnoopable,
1101
+ int *is_routable)
8091102 {
8101103 struct ethhdr *ethhdr = eth_hdr(skb);
8111104
....@@ -815,13 +1108,15 @@
8151108 switch (ntohs(ethhdr->h_proto)) {
8161109 case ETH_P_IP:
8171110 return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb,
818
- is_unsnoopable);
1111
+ is_unsnoopable,
1112
+ is_routable);
8191113 case ETH_P_IPV6:
8201114 if (!IS_ENABLED(CONFIG_IPV6))
8211115 return -EINVAL;
8221116
8231117 return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb,
824
- is_unsnoopable);
1118
+ is_unsnoopable,
1119
+ is_routable);
8251120 default:
8261121 return -EINVAL;
8271122 }
....@@ -847,6 +1142,29 @@
8471142 return atomic_read(&bat_priv->mcast.num_want_all_ipv6);
8481143 default:
8491144 /* we shouldn't be here... */
1145
+ return 0;
1146
+ }
1147
+}
1148
+
1149
+/**
1150
+ * batadv_mcast_forw_rtr_count() - count nodes with a multicast router
1151
+ * @bat_priv: the bat priv with all the soft interface information
1152
+ * @protocol: the ethernet protocol type to count multicast routers for
1153
+ *
1154
+ * Return: the number of nodes which want all routable IPv4 multicast traffic
1155
+ * if the protocol is ETH_P_IP or the number of nodes which want all routable
1156
+ * IPv6 traffic if the protocol is ETH_P_IPV6. Otherwise returns 0.
1157
+ */
1158
+
1159
+static int batadv_mcast_forw_rtr_count(struct batadv_priv *bat_priv,
1160
+ int protocol)
1161
+{
1162
+ switch (protocol) {
1163
+ case ETH_P_IP:
1164
+ return atomic_read(&bat_priv->mcast.num_want_all_rtr4);
1165
+ case ETH_P_IPV6:
1166
+ return atomic_read(&bat_priv->mcast.num_want_all_rtr6);
1167
+ default:
8501168 return 0;
8511169 }
8521170 }
....@@ -927,7 +1245,7 @@
9271245 * @ethhdr: an ethernet header to determine the protocol family from
9281246 *
9291247 * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or
930
- * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and
1248
+ * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, sets and
9311249 * increases its refcount.
9321250 */
9331251 static struct batadv_orig_node *
....@@ -973,10 +1291,89 @@
9731291 }
9741292
9751293 /**
1294
+ * batadv_mcast_forw_rtr4_node_get() - get a node with an ipv4 mcast router flag
1295
+ * @bat_priv: the bat priv with all the soft interface information
1296
+ *
1297
+ * Return: an orig_node which has the BATADV_MCAST_WANT_NO_RTR4 flag unset and
1298
+ * increases its refcount.
1299
+ */
1300
+static struct batadv_orig_node *
1301
+batadv_mcast_forw_rtr4_node_get(struct batadv_priv *bat_priv)
1302
+{
1303
+ struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
1304
+
1305
+ rcu_read_lock();
1306
+ hlist_for_each_entry_rcu(tmp_orig_node,
1307
+ &bat_priv->mcast.want_all_rtr4_list,
1308
+ mcast_want_all_rtr4_node) {
1309
+ if (!kref_get_unless_zero(&tmp_orig_node->refcount))
1310
+ continue;
1311
+
1312
+ orig_node = tmp_orig_node;
1313
+ break;
1314
+ }
1315
+ rcu_read_unlock();
1316
+
1317
+ return orig_node;
1318
+}
1319
+
1320
+/**
1321
+ * batadv_mcast_forw_rtr6_node_get() - get a node with an ipv6 mcast router flag
1322
+ * @bat_priv: the bat priv with all the soft interface information
1323
+ *
1324
+ * Return: an orig_node which has the BATADV_MCAST_WANT_NO_RTR6 flag unset
1325
+ * and increases its refcount.
1326
+ */
1327
+static struct batadv_orig_node *
1328
+batadv_mcast_forw_rtr6_node_get(struct batadv_priv *bat_priv)
1329
+{
1330
+ struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
1331
+
1332
+ rcu_read_lock();
1333
+ hlist_for_each_entry_rcu(tmp_orig_node,
1334
+ &bat_priv->mcast.want_all_rtr6_list,
1335
+ mcast_want_all_rtr6_node) {
1336
+ if (!kref_get_unless_zero(&tmp_orig_node->refcount))
1337
+ continue;
1338
+
1339
+ orig_node = tmp_orig_node;
1340
+ break;
1341
+ }
1342
+ rcu_read_unlock();
1343
+
1344
+ return orig_node;
1345
+}
1346
+
1347
+/**
1348
+ * batadv_mcast_forw_rtr_node_get() - get a node with an ipv4/ipv6 router flag
1349
+ * @bat_priv: the bat priv with all the soft interface information
1350
+ * @ethhdr: an ethernet header to determine the protocol family from
1351
+ *
1352
+ * Return: an orig_node which has no BATADV_MCAST_WANT_NO_RTR4 or
1353
+ * BATADV_MCAST_WANT_NO_RTR6 flag, depending on the provided ethhdr, set and
1354
+ * increases its refcount.
1355
+ */
1356
+static struct batadv_orig_node *
1357
+batadv_mcast_forw_rtr_node_get(struct batadv_priv *bat_priv,
1358
+ struct ethhdr *ethhdr)
1359
+{
1360
+ switch (ntohs(ethhdr->h_proto)) {
1361
+ case ETH_P_IP:
1362
+ return batadv_mcast_forw_rtr4_node_get(bat_priv);
1363
+ case ETH_P_IPV6:
1364
+ return batadv_mcast_forw_rtr6_node_get(bat_priv);
1365
+ default:
1366
+ /* we shouldn't be here... */
1367
+ return NULL;
1368
+ }
1369
+}
1370
+
1371
+/**
9761372 * batadv_mcast_forw_mode() - check on how to forward a multicast packet
9771373 * @bat_priv: the bat priv with all the soft interface information
9781374 * @skb: The multicast packet to check
9791375 * @orig: an originator to be set to forward the skb to
1376
+ * @is_routable: stores whether the destination is routable
9801377 *
9811378 * Return: the forwarding mode as enum batadv_forw_mode and in case of
9821379 * BATADV_FORW_SINGLE set the orig to the single originator the skb
....@@ -984,13 +1381,16 @@
9841381 */
9851382 enum batadv_forw_mode
9861383 batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
987
- struct batadv_orig_node **orig)
1384
+ struct batadv_orig_node **orig, int *is_routable)
9881385 {
9891386 int ret, tt_count, ip_count, unsnoop_count, total_count;
9901387 bool is_unsnoopable = false;
1388
+ unsigned int mcast_fanout;
9911389 struct ethhdr *ethhdr;
1390
+ int rtr_count = 0;
9921391
993
- ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable);
1392
+ ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable,
1393
+ is_routable);
9941394 if (ret == -ENOMEM)
9951395 return BATADV_FORW_NONE;
9961396 else if (ret < 0)
....@@ -1003,8 +1403,9 @@
10031403 ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
10041404 unsnoop_count = !is_unsnoopable ? 0 :
10051405 atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
1406
+ rtr_count = batadv_mcast_forw_rtr_count(bat_priv, *is_routable);
10061407
1007
- total_count = tt_count + ip_count + unsnoop_count;
1408
+ total_count = tt_count + ip_count + unsnoop_count + rtr_count;
10081409
10091410 switch (total_count) {
10101411 case 1:
....@@ -1014,16 +1415,24 @@
10141415 *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr);
10151416 else if (unsnoop_count)
10161417 *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv);
1418
+ else if (rtr_count)
1419
+ *orig = batadv_mcast_forw_rtr_node_get(bat_priv,
1420
+ ethhdr);
10171421
10181422 if (*orig)
10191423 return BATADV_FORW_SINGLE;
10201424
1021
- /* fall through */
1425
+ fallthrough;
10221426 case 0:
10231427 return BATADV_FORW_NONE;
10241428 default:
1025
- return BATADV_FORW_ALL;
1429
+ mcast_fanout = atomic_read(&bat_priv->multicast_fanout);
1430
+
1431
+ if (!unsnoop_count && total_count <= mcast_fanout)
1432
+ return BATADV_FORW_SOME;
10261433 }
1434
+
1435
+ return BATADV_FORW_ALL;
10271436 }
10281437
10291438 /**
....@@ -1056,13 +1465,316 @@
10561465 }
10571466
10581467 /**
1468
+ * batadv_mcast_forw_tt() - forwards a packet to multicast listeners
1469
+ * @bat_priv: the bat priv with all the soft interface information
1470
+ * @skb: the multicast packet to transmit
1471
+ * @vid: the vlan identifier
1472
+ *
1473
+ * Sends copies of a frame with multicast destination to any multicast
1474
+ * listener registered in the translation table. A transmission is performed
1475
+ * via a batman-adv unicast packet for each such destination node.
1476
+ *
1477
+ * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1478
+ * otherwise.
1479
+ */
1480
+static int
1481
+batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
1482
+ unsigned short vid)
1483
+{
1484
+ int ret = NET_XMIT_SUCCESS;
1485
+ struct sk_buff *newskb;
1486
+
1487
+ struct batadv_tt_orig_list_entry *orig_entry;
1488
+
1489
+ struct batadv_tt_global_entry *tt_global;
1490
+ const u8 *addr = eth_hdr(skb)->h_dest;
1491
+
1492
+ tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
1493
+ if (!tt_global)
1494
+ goto out;
1495
+
1496
+ rcu_read_lock();
1497
+ hlist_for_each_entry_rcu(orig_entry, &tt_global->orig_list, list) {
1498
+ newskb = skb_copy(skb, GFP_ATOMIC);
1499
+ if (!newskb) {
1500
+ ret = NET_XMIT_DROP;
1501
+ break;
1502
+ }
1503
+
1504
+ batadv_mcast_forw_send_orig(bat_priv, newskb, vid,
1505
+ orig_entry->orig_node);
1506
+ }
1507
+ rcu_read_unlock();
1508
+
1509
+ batadv_tt_global_entry_put(tt_global);
1510
+
1511
+out:
1512
+ return ret;
1513
+}
1514
+
1515
+/**
1516
+ * batadv_mcast_forw_want_all_ipv4() - forward to nodes with want-all-ipv4
1517
+ * @bat_priv: the bat priv with all the soft interface information
1518
+ * @skb: the multicast packet to transmit
1519
+ * @vid: the vlan identifier
1520
+ *
1521
+ * Sends copies of a frame with multicast destination to any node with a
1522
+ * BATADV_MCAST_WANT_ALL_IPV4 flag set. A transmission is performed via a
1523
+ * batman-adv unicast packet for each such destination node.
1524
+ *
1525
+ * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1526
+ * otherwise.
1527
+ */
1528
+static int
1529
+batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv,
1530
+ struct sk_buff *skb, unsigned short vid)
1531
+{
1532
+ struct batadv_orig_node *orig_node;
1533
+ int ret = NET_XMIT_SUCCESS;
1534
+ struct sk_buff *newskb;
1535
+
1536
+ rcu_read_lock();
1537
+ hlist_for_each_entry_rcu(orig_node,
1538
+ &bat_priv->mcast.want_all_ipv4_list,
1539
+ mcast_want_all_ipv4_node) {
1540
+ newskb = skb_copy(skb, GFP_ATOMIC);
1541
+ if (!newskb) {
1542
+ ret = NET_XMIT_DROP;
1543
+ break;
1544
+ }
1545
+
1546
+ batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
1547
+ }
1548
+ rcu_read_unlock();
1549
+ return ret;
1550
+}
1551
+
1552
+/**
1553
+ * batadv_mcast_forw_want_all_ipv6() - forward to nodes with want-all-ipv6
1554
+ * @bat_priv: the bat priv with all the soft interface information
1555
+ * @skb: The multicast packet to transmit
1556
+ * @vid: the vlan identifier
1557
+ *
1558
+ * Sends copies of a frame with multicast destination to any node with a
1559
+ * BATADV_MCAST_WANT_ALL_IPV6 flag set. A transmission is performed via a
1560
+ * batman-adv unicast packet for each such destination node.
1561
+ *
1562
+ * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1563
+ * otherwise.
1564
+ */
1565
+static int
1566
+batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv,
1567
+ struct sk_buff *skb, unsigned short vid)
1568
+{
1569
+ struct batadv_orig_node *orig_node;
1570
+ int ret = NET_XMIT_SUCCESS;
1571
+ struct sk_buff *newskb;
1572
+
1573
+ rcu_read_lock();
1574
+ hlist_for_each_entry_rcu(orig_node,
1575
+ &bat_priv->mcast.want_all_ipv6_list,
1576
+ mcast_want_all_ipv6_node) {
1577
+ newskb = skb_copy(skb, GFP_ATOMIC);
1578
+ if (!newskb) {
1579
+ ret = NET_XMIT_DROP;
1580
+ break;
1581
+ }
1582
+
1583
+ batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
1584
+ }
1585
+ rcu_read_unlock();
1586
+ return ret;
1587
+}
1588
+
1589
+/**
1590
+ * batadv_mcast_forw_want_all() - forward packet to nodes in a want-all list
1591
+ * @bat_priv: the bat priv with all the soft interface information
1592
+ * @skb: the multicast packet to transmit
1593
+ * @vid: the vlan identifier
1594
+ *
1595
+ * Sends copies of a frame with multicast destination to any node with a
1596
+ * BATADV_MCAST_WANT_ALL_IPV4 or BATADV_MCAST_WANT_ALL_IPV6 flag set. A
1597
+ * transmission is performed via a batman-adv unicast packet for each such
1598
+ * destination node.
1599
+ *
1600
+ * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
1601
+ * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
1602
+ */
1603
+static int
1604
+batadv_mcast_forw_want_all(struct batadv_priv *bat_priv,
1605
+ struct sk_buff *skb, unsigned short vid)
1606
+{
1607
+ switch (ntohs(eth_hdr(skb)->h_proto)) {
1608
+ case ETH_P_IP:
1609
+ return batadv_mcast_forw_want_all_ipv4(bat_priv, skb, vid);
1610
+ case ETH_P_IPV6:
1611
+ return batadv_mcast_forw_want_all_ipv6(bat_priv, skb, vid);
1612
+ default:
1613
+ /* we shouldn't be here... */
1614
+ return NET_XMIT_DROP;
1615
+ }
1616
+}
1617
+
1618
+/**
1619
+ * batadv_mcast_forw_want_all_rtr4() - forward to nodes with want-all-rtr4
1620
+ * @bat_priv: the bat priv with all the soft interface information
1621
+ * @skb: the multicast packet to transmit
1622
+ * @vid: the vlan identifier
1623
+ *
1624
+ * Sends copies of a frame with multicast destination to any node with a
1625
+ * BATADV_MCAST_WANT_NO_RTR4 flag unset. A transmission is performed via a
1626
+ * batman-adv unicast packet for each such destination node.
1627
+ *
1628
+ * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1629
+ * otherwise.
1630
+ */
1631
+static int
1632
+batadv_mcast_forw_want_all_rtr4(struct batadv_priv *bat_priv,
1633
+ struct sk_buff *skb, unsigned short vid)
1634
+{
1635
+ struct batadv_orig_node *orig_node;
1636
+ int ret = NET_XMIT_SUCCESS;
1637
+ struct sk_buff *newskb;
1638
+
1639
+ rcu_read_lock();
1640
+ hlist_for_each_entry_rcu(orig_node,
1641
+ &bat_priv->mcast.want_all_rtr4_list,
1642
+ mcast_want_all_rtr4_node) {
1643
+ newskb = skb_copy(skb, GFP_ATOMIC);
1644
+ if (!newskb) {
1645
+ ret = NET_XMIT_DROP;
1646
+ break;
1647
+ }
1648
+
1649
+ batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
1650
+ }
1651
+ rcu_read_unlock();
1652
+ return ret;
1653
+}
1654
+
1655
+/**
1656
+ * batadv_mcast_forw_want_all_rtr6() - forward to nodes with want-all-rtr6
1657
+ * @bat_priv: the bat priv with all the soft interface information
1658
+ * @skb: The multicast packet to transmit
1659
+ * @vid: the vlan identifier
1660
+ *
1661
+ * Sends copies of a frame with multicast destination to any node with a
1662
+ * BATADV_MCAST_WANT_NO_RTR6 flag unset. A transmission is performed via a
1663
+ * batman-adv unicast packet for each such destination node.
1664
+ *
1665
+ * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
1666
+ * otherwise.
1667
+ */
1668
+static int
1669
+batadv_mcast_forw_want_all_rtr6(struct batadv_priv *bat_priv,
1670
+ struct sk_buff *skb, unsigned short vid)
1671
+{
1672
+ struct batadv_orig_node *orig_node;
1673
+ int ret = NET_XMIT_SUCCESS;
1674
+ struct sk_buff *newskb;
1675
+
1676
+ rcu_read_lock();
1677
+ hlist_for_each_entry_rcu(orig_node,
1678
+ &bat_priv->mcast.want_all_rtr6_list,
1679
+ mcast_want_all_rtr6_node) {
1680
+ newskb = skb_copy(skb, GFP_ATOMIC);
1681
+ if (!newskb) {
1682
+ ret = NET_XMIT_DROP;
1683
+ break;
1684
+ }
1685
+
1686
+ batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
1687
+ }
1688
+ rcu_read_unlock();
1689
+ return ret;
1690
+}
1691
+
1692
+/**
1693
+ * batadv_mcast_forw_want_rtr() - forward packet to nodes in a want-all-rtr list
1694
+ * @bat_priv: the bat priv with all the soft interface information
1695
+ * @skb: the multicast packet to transmit
1696
+ * @vid: the vlan identifier
1697
+ *
1698
+ * Sends copies of a frame with multicast destination to any node with a
1699
+ * BATADV_MCAST_WANT_NO_RTR4 or BATADV_MCAST_WANT_NO_RTR6 flag unset. A
1700
+ * transmission is performed via a batman-adv unicast packet for each such
1701
+ * destination node.
1702
+ *
1703
+ * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
1704
+ * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
1705
+ */
1706
+static int
1707
+batadv_mcast_forw_want_rtr(struct batadv_priv *bat_priv,
1708
+ struct sk_buff *skb, unsigned short vid)
1709
+{
1710
+ switch (ntohs(eth_hdr(skb)->h_proto)) {
1711
+ case ETH_P_IP:
1712
+ return batadv_mcast_forw_want_all_rtr4(bat_priv, skb, vid);
1713
+ case ETH_P_IPV6:
1714
+ return batadv_mcast_forw_want_all_rtr6(bat_priv, skb, vid);
1715
+ default:
1716
+ /* we shouldn't be here... */
1717
+ return NET_XMIT_DROP;
1718
+ }
1719
+}
1720
+
1721
+/**
1722
+ * batadv_mcast_forw_send() - send packet to any detected multicast recipient
1723
+ * @bat_priv: the bat priv with all the soft interface information
1724
+ * @skb: the multicast packet to transmit
1725
+ * @vid: the vlan identifier
1726
+ * @is_routable: stores whether the destination is routable
1727
+ *
1728
+ * Sends copies of a frame with multicast destination to any node that signaled
1729
+ * interest in it, that is either via the translation table or the according
1730
+ * want-all flags. A transmission is performed via a batman-adv unicast packet
1731
+ * for each such destination node.
1732
+ *
1733
+ * The given skb is consumed/freed.
1734
+ *
1735
+ * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
1736
+ * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
1737
+ */
1738
+int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
1739
+ unsigned short vid, int is_routable)
1740
+{
1741
+ int ret;
1742
+
1743
+ ret = batadv_mcast_forw_tt(bat_priv, skb, vid);
1744
+ if (ret != NET_XMIT_SUCCESS) {
1745
+ kfree_skb(skb);
1746
+ return ret;
1747
+ }
1748
+
1749
+ ret = batadv_mcast_forw_want_all(bat_priv, skb, vid);
1750
+ if (ret != NET_XMIT_SUCCESS) {
1751
+ kfree_skb(skb);
1752
+ return ret;
1753
+ }
1754
+
1755
+ if (!is_routable)
1756
+ goto skip_mc_router;
1757
+
1758
+ ret = batadv_mcast_forw_want_rtr(bat_priv, skb, vid);
1759
+ if (ret != NET_XMIT_SUCCESS) {
1760
+ kfree_skb(skb);
1761
+ return ret;
1762
+ }
1763
+
1764
+skip_mc_router:
1765
+ consume_skb(skb);
1766
+ return ret;
1767
+}
1768
+
1769
+/**
10591770 * batadv_mcast_want_unsnoop_update() - update unsnoop counter and list
10601771 * @bat_priv: the bat priv with all the soft interface information
10611772 * @orig: the orig_node which multicast state might have changed of
10621773 * @mcast_flags: flags indicating the new multicast state
10631774 *
10641775 * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator,
1065
- * orig, has toggled then this method updates counter and list accordingly.
1776
+ * orig, has toggled then this method updates the counter and the list
1777
+ * accordingly.
10661778 *
10671779 * Caller needs to hold orig->mcast_handler_lock.
10681780 */
....@@ -1107,7 +1819,7 @@
11071819 * @mcast_flags: flags indicating the new multicast state
11081820 *
11091821 * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has
1110
- * toggled then this method updates counter and list accordingly.
1822
+ * toggled then this method updates the counter and the list accordingly.
11111823 *
11121824 * Caller needs to hold orig->mcast_handler_lock.
11131825 */
....@@ -1152,7 +1864,7 @@
11521864 * @mcast_flags: flags indicating the new multicast state
11531865 *
11541866 * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has
1155
- * toggled then this method updates counter and list accordingly.
1867
+ * toggled then this method updates the counter and the list accordingly.
11561868 *
11571869 * Caller needs to hold orig->mcast_handler_lock.
11581870 */
....@@ -1191,6 +1903,127 @@
11911903 }
11921904
11931905 /**
1906
+ * batadv_mcast_want_rtr4_update() - update want-all-rtr4 counter and list
1907
+ * @bat_priv: the bat priv with all the soft interface information
1908
+ * @orig: the orig_node which multicast state might have changed of
1909
+ * @mcast_flags: flags indicating the new multicast state
1910
+ *
1911
+ * If the BATADV_MCAST_WANT_NO_RTR4 flag of this originator, orig, has
1912
+ * toggled then this method updates the counter and the list accordingly.
1913
+ *
1914
+ * Caller needs to hold orig->mcast_handler_lock.
1915
+ */
1916
+static void batadv_mcast_want_rtr4_update(struct batadv_priv *bat_priv,
1917
+ struct batadv_orig_node *orig,
1918
+ u8 mcast_flags)
1919
+{
1920
+ struct hlist_node *node = &orig->mcast_want_all_rtr4_node;
1921
+ struct hlist_head *head = &bat_priv->mcast.want_all_rtr4_list;
1922
+
1923
+ lockdep_assert_held(&orig->mcast_handler_lock);
1924
+
1925
+ /* switched from flag set to unset */
1926
+ if (!(mcast_flags & BATADV_MCAST_WANT_NO_RTR4) &&
1927
+ orig->mcast_flags & BATADV_MCAST_WANT_NO_RTR4) {
1928
+ atomic_inc(&bat_priv->mcast.num_want_all_rtr4);
1929
+
1930
+ spin_lock_bh(&bat_priv->mcast.want_lists_lock);
1931
+ /* flag checks above + mcast_handler_lock prevents this */
1932
+ WARN_ON(!hlist_unhashed(node));
1933
+
1934
+ hlist_add_head_rcu(node, head);
1935
+ spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1936
+ /* switched from flag unset to set */
1937
+ } else if (mcast_flags & BATADV_MCAST_WANT_NO_RTR4 &&
1938
+ !(orig->mcast_flags & BATADV_MCAST_WANT_NO_RTR4)) {
1939
+ atomic_dec(&bat_priv->mcast.num_want_all_rtr4);
1940
+
1941
+ spin_lock_bh(&bat_priv->mcast.want_lists_lock);
1942
+ /* flag checks above + mcast_handler_lock prevents this */
1943
+ WARN_ON(hlist_unhashed(node));
1944
+
1945
+ hlist_del_init_rcu(node);
1946
+ spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1947
+ }
1948
+}
1949
+
1950
+/**
1951
+ * batadv_mcast_want_rtr6_update() - update want-all-rtr6 counter and list
1952
+ * @bat_priv: the bat priv with all the soft interface information
1953
+ * @orig: the orig_node which multicast state might have changed of
1954
+ * @mcast_flags: flags indicating the new multicast state
1955
+ *
1956
+ * If the BATADV_MCAST_WANT_NO_RTR6 flag of this originator, orig, has
1957
+ * toggled then this method updates the counter and the list accordingly.
1958
+ *
1959
+ * Caller needs to hold orig->mcast_handler_lock.
1960
+ */
1961
+static void batadv_mcast_want_rtr6_update(struct batadv_priv *bat_priv,
1962
+ struct batadv_orig_node *orig,
1963
+ u8 mcast_flags)
1964
+{
1965
+ struct hlist_node *node = &orig->mcast_want_all_rtr6_node;
1966
+ struct hlist_head *head = &bat_priv->mcast.want_all_rtr6_list;
1967
+
1968
+ lockdep_assert_held(&orig->mcast_handler_lock);
1969
+
1970
+ /* switched from flag set to unset */
1971
+ if (!(mcast_flags & BATADV_MCAST_WANT_NO_RTR6) &&
1972
+ orig->mcast_flags & BATADV_MCAST_WANT_NO_RTR6) {
1973
+ atomic_inc(&bat_priv->mcast.num_want_all_rtr6);
1974
+
1975
+ spin_lock_bh(&bat_priv->mcast.want_lists_lock);
1976
+ /* flag checks above + mcast_handler_lock prevents this */
1977
+ WARN_ON(!hlist_unhashed(node));
1978
+
1979
+ hlist_add_head_rcu(node, head);
1980
+ spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1981
+ /* switched from flag unset to set */
1982
+ } else if (mcast_flags & BATADV_MCAST_WANT_NO_RTR6 &&
1983
+ !(orig->mcast_flags & BATADV_MCAST_WANT_NO_RTR6)) {
1984
+ atomic_dec(&bat_priv->mcast.num_want_all_rtr6);
1985
+
1986
+ spin_lock_bh(&bat_priv->mcast.want_lists_lock);
1987
+ /* flag checks above + mcast_handler_lock prevents this */
1988
+ WARN_ON(hlist_unhashed(node));
1989
+
1990
+ hlist_del_init_rcu(node);
1991
+ spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
1992
+ }
1993
+}
1994
+
1995
+/**
1996
+ * batadv_mcast_tvlv_flags_get() - get multicast flags from an OGM TVLV
1997
+ * @enabled: whether the originator has multicast TVLV support enabled
1998
+ * @tvlv_value: tvlv buffer containing the multicast flags
1999
+ * @tvlv_value_len: tvlv buffer length
2000
+ *
2001
+ * Return: multicast flags for the given tvlv buffer
2002
+ */
2003
+static u8
2004
+batadv_mcast_tvlv_flags_get(bool enabled, void *tvlv_value, u16 tvlv_value_len)
2005
+{
2006
+ u8 mcast_flags = BATADV_NO_FLAGS;
2007
+
2008
+ if (enabled && tvlv_value && tvlv_value_len >= sizeof(mcast_flags))
2009
+ mcast_flags = *(u8 *)tvlv_value;
2010
+
2011
+ if (!enabled) {
2012
+ mcast_flags |= BATADV_MCAST_WANT_ALL_IPV4;
2013
+ mcast_flags |= BATADV_MCAST_WANT_ALL_IPV6;
2014
+ }
2015
+
2016
+ /* remove redundant flags to avoid sending duplicate packets later */
2017
+ if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)
2018
+ mcast_flags |= BATADV_MCAST_WANT_NO_RTR4;
2019
+
2020
+ if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)
2021
+ mcast_flags |= BATADV_MCAST_WANT_NO_RTR6;
2022
+
2023
+ return mcast_flags;
2024
+}
2025
+
2026
+/**
11942027 * batadv_mcast_tvlv_ogm_handler() - process incoming multicast tvlv container
11952028 * @bat_priv: the bat priv with all the soft interface information
11962029 * @orig: the orig_node of the ogm
....@@ -1205,16 +2038,10 @@
12052038 u16 tvlv_value_len)
12062039 {
12072040 bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
1208
- u8 mcast_flags = BATADV_NO_FLAGS;
2041
+ u8 mcast_flags;
12092042
1210
- if (orig_mcast_enabled && tvlv_value &&
1211
- tvlv_value_len >= sizeof(mcast_flags))
1212
- mcast_flags = *(u8 *)tvlv_value;
1213
-
1214
- if (!orig_mcast_enabled) {
1215
- mcast_flags |= BATADV_MCAST_WANT_ALL_IPV4;
1216
- mcast_flags |= BATADV_MCAST_WANT_ALL_IPV6;
1217
- }
2043
+ mcast_flags = batadv_mcast_tvlv_flags_get(orig_mcast_enabled,
2044
+ tvlv_value, tvlv_value_len);
12182045
12192046 spin_lock_bh(&orig->mcast_handler_lock);
12202047
....@@ -1231,6 +2058,8 @@
12312058 batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags);
12322059 batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags);
12332060 batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags);
2061
+ batadv_mcast_want_rtr4_update(bat_priv, orig, mcast_flags);
2062
+ batadv_mcast_want_rtr6_update(bat_priv, orig, mcast_flags);
12342063
12352064 orig->mcast_flags = mcast_flags;
12362065 spin_unlock_bh(&orig->mcast_handler_lock);
....@@ -1263,15 +2092,16 @@
12632092 static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv,
12642093 struct seq_file *seq)
12652094 {
1266
- u8 flags = bat_priv->mcast.flags;
2095
+ struct batadv_mcast_mla_flags *mla_flags = &bat_priv->mcast.mla_flags;
12672096 char querier4, querier6, shadowing4, shadowing6;
1268
- bool bridged = bat_priv->mcast.bridged;
2097
+ bool bridged = mla_flags->bridged;
2098
+ u8 flags = mla_flags->tvlv_flags;
12692099
12702100 if (bridged) {
1271
- querier4 = bat_priv->mcast.querier_ipv4.exists ? '.' : '4';
1272
- querier6 = bat_priv->mcast.querier_ipv6.exists ? '.' : '6';
1273
- shadowing4 = bat_priv->mcast.querier_ipv4.shadowing ? '4' : '.';
1274
- shadowing6 = bat_priv->mcast.querier_ipv6.shadowing ? '6' : '.';
2101
+ querier4 = mla_flags->querier_ipv4.exists ? '.' : '4';
2102
+ querier6 = mla_flags->querier_ipv6.exists ? '.' : '6';
2103
+ shadowing4 = mla_flags->querier_ipv4.shadowing ? '4' : '.';
2104
+ shadowing6 = mla_flags->querier_ipv6.shadowing ? '6' : '.';
12752105 } else {
12762106 querier4 = '?';
12772107 querier6 = '?';
....@@ -1279,10 +2109,12 @@
12792109 shadowing6 = '?';
12802110 }
12812111
1282
- seq_printf(seq, "Multicast flags (own flags: [%c%c%c])\n",
2112
+ seq_printf(seq, "Multicast flags (own flags: [%c%c%c%s%s])\n",
12832113 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
12842114 (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
1285
- (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
2115
+ (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
2116
+ !(flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ",
2117
+ !(flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ");
12862118 seq_printf(seq, "* Bridged [U]\t\t\t\t%c\n", bridged ? 'U' : '.');
12872119 seq_printf(seq, "* No IGMP/MLD Querier [4/6]:\t\t%c/%c\n",
12882120 querier4, querier6);
....@@ -1336,13 +2168,17 @@
13362168
13372169 flags = orig_node->mcast_flags;
13382170
1339
- seq_printf(seq, "%pM [%c%c%c]\n", orig_node->orig,
2171
+ seq_printf(seq, "%pM [%c%c%c%s%s]\n", orig_node->orig,
13402172 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)
13412173 ? 'U' : '.',
13422174 (flags & BATADV_MCAST_WANT_ALL_IPV4)
13432175 ? '4' : '.',
13442176 (flags & BATADV_MCAST_WANT_ALL_IPV6)
1345
- ? '6' : '.');
2177
+ ? '6' : '.',
2178
+ !(flags & BATADV_MCAST_WANT_NO_RTR4)
2179
+ ? "R4" : ". ",
2180
+ !(flags & BATADV_MCAST_WANT_NO_RTR6)
2181
+ ? "R6" : ". ");
13462182 }
13472183 rcu_read_unlock();
13482184 }
....@@ -1363,19 +2199,19 @@
13632199 int batadv_mcast_mesh_info_put(struct sk_buff *msg,
13642200 struct batadv_priv *bat_priv)
13652201 {
1366
- u32 flags = bat_priv->mcast.flags;
2202
+ u32 flags = bat_priv->mcast.mla_flags.tvlv_flags;
13672203 u32 flags_priv = BATADV_NO_FLAGS;
13682204
1369
- if (bat_priv->mcast.bridged) {
2205
+ if (bat_priv->mcast.mla_flags.bridged) {
13702206 flags_priv |= BATADV_MCAST_FLAGS_BRIDGED;
13712207
1372
- if (bat_priv->mcast.querier_ipv4.exists)
2208
+ if (bat_priv->mcast.mla_flags.querier_ipv4.exists)
13732209 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS;
1374
- if (bat_priv->mcast.querier_ipv6.exists)
2210
+ if (bat_priv->mcast.mla_flags.querier_ipv6.exists)
13752211 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS;
1376
- if (bat_priv->mcast.querier_ipv4.shadowing)
2212
+ if (bat_priv->mcast.mla_flags.querier_ipv4.shadowing)
13772213 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING;
1378
- if (bat_priv->mcast.querier_ipv6.shadowing)
2214
+ if (bat_priv->mcast.mla_flags.querier_ipv6.shadowing)
13792215 flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING;
13802216 }
13812217
....@@ -1391,21 +2227,25 @@
13912227 * to a netlink socket
13922228 * @msg: buffer for the message
13932229 * @portid: netlink port
1394
- * @seq: Sequence number of netlink message
2230
+ * @cb: Control block containing additional options
13952231 * @orig_node: originator to dump the multicast flags of
13962232 *
13972233 * Return: 0 or error code.
13982234 */
13992235 static int
1400
-batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
2236
+batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid,
2237
+ struct netlink_callback *cb,
14012238 struct batadv_orig_node *orig_node)
14022239 {
14032240 void *hdr;
14042241
1405
- hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1406
- NLM_F_MULTI, BATADV_CMD_GET_MCAST_FLAGS);
2242
+ hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
2243
+ &batadv_netlink_family, NLM_F_MULTI,
2244
+ BATADV_CMD_GET_MCAST_FLAGS);
14072245 if (!hdr)
14082246 return -ENOBUFS;
2247
+
2248
+ genl_dump_check_consistent(cb, hdr);
14092249
14102250 if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
14112251 orig_node->orig)) {
....@@ -1431,21 +2271,26 @@
14312271 * table to a netlink socket
14322272 * @msg: buffer for the message
14332273 * @portid: netlink port
1434
- * @seq: Sequence number of netlink message
1435
- * @head: bucket to dump
2274
+ * @cb: Control block containing additional options
2275
+ * @hash: hash to dump
2276
+ * @bucket: bucket index to dump
14362277 * @idx_skip: How many entries to skip
14372278 *
14382279 * Return: 0 or error code.
14392280 */
14402281 static int
1441
-batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1442
- struct hlist_head *head, long *idx_skip)
2282
+batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid,
2283
+ struct netlink_callback *cb,
2284
+ struct batadv_hashtable *hash,
2285
+ unsigned int bucket, long *idx_skip)
14432286 {
14442287 struct batadv_orig_node *orig_node;
14452288 long idx = 0;
14462289
1447
- rcu_read_lock();
1448
- hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
2290
+ spin_lock_bh(&hash->list_locks[bucket]);
2291
+ cb->seq = atomic_read(&hash->generation) << 1 | 1;
2292
+
2293
+ hlist_for_each_entry(orig_node, &hash->table[bucket], hash_entry) {
14492294 if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
14502295 &orig_node->capa_initialized))
14512296 continue;
....@@ -1453,9 +2298,8 @@
14532298 if (idx < *idx_skip)
14542299 goto skip;
14552300
1456
- if (batadv_mcast_flags_dump_entry(msg, portid, seq,
1457
- orig_node)) {
1458
- rcu_read_unlock();
2301
+ if (batadv_mcast_flags_dump_entry(msg, portid, cb, orig_node)) {
2302
+ spin_unlock_bh(&hash->list_locks[bucket]);
14592303 *idx_skip = idx;
14602304
14612305 return -EMSGSIZE;
....@@ -1464,7 +2308,7 @@
14642308 skip:
14652309 idx++;
14662310 }
1467
- rcu_read_unlock();
2311
+ spin_unlock_bh(&hash->list_locks[bucket]);
14682312
14692313 return 0;
14702314 }
....@@ -1473,7 +2317,7 @@
14732317 * __batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket
14742318 * @msg: buffer for the message
14752319 * @portid: netlink port
1476
- * @seq: Sequence number of netlink message
2320
+ * @cb: Control block containing additional options
14772321 * @bat_priv: the bat priv with all the soft interface information
14782322 * @bucket: current bucket to dump
14792323 * @idx: index in current bucket to the next entry to dump
....@@ -1481,19 +2325,17 @@
14812325 * Return: 0 or error code.
14822326 */
14832327 static int
1484
-__batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid, u32 seq,
2328
+__batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
2329
+ struct netlink_callback *cb,
14852330 struct batadv_priv *bat_priv, long *bucket, long *idx)
14862331 {
14872332 struct batadv_hashtable *hash = bat_priv->orig_hash;
14882333 long bucket_tmp = *bucket;
1489
- struct hlist_head *head;
14902334 long idx_tmp = *idx;
14912335
14922336 while (bucket_tmp < hash->size) {
1493
- head = &hash->table[bucket_tmp];
1494
-
1495
- if (batadv_mcast_flags_dump_bucket(msg, portid, seq, head,
1496
- &idx_tmp))
2337
+ if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
2338
+ bucket_tmp, &idx_tmp))
14972339 break;
14982340
14992341 bucket_tmp++;
....@@ -1576,8 +2418,7 @@
15762418 return ret;
15772419
15782420 bat_priv = netdev_priv(primary_if->soft_iface);
1579
- ret = __batadv_mcast_flags_dump(msg, portid, cb->nlh->nlmsg_seq,
1580
- bat_priv, bucket, idx);
2421
+ ret = __batadv_mcast_flags_dump(msg, portid, cb, bat_priv, bucket, idx);
15812422
15822423 batadv_hardif_put(primary_if);
15832424 return ret;
....@@ -1611,6 +2452,10 @@
16112452 batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
16122453 batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
16132454 batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
2455
+ batadv_mcast_want_rtr4_update(bat_priv, orig,
2456
+ BATADV_MCAST_WANT_NO_RTR4);
2457
+ batadv_mcast_want_rtr6_update(bat_priv, orig,
2458
+ BATADV_MCAST_WANT_NO_RTR6);
16142459
16152460 spin_unlock_bh(&orig->mcast_handler_lock);
16162461 }