Merge tag 'mt76-for-kvalo-2021-01-29' of https://github.com/nbd168/wireless
[linux-2.6-microblaze.git] / net / bridge / br_multicast_eht.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 // Copyright (c) 2020, Nikolay Aleksandrov <nikolay@nvidia.com>
3 #include <linux/err.h>
4 #include <linux/export.h>
5 #include <linux/if_ether.h>
6 #include <linux/igmp.h>
7 #include <linux/in.h>
8 #include <linux/jhash.h>
9 #include <linux/kernel.h>
10 #include <linux/log2.h>
11 #include <linux/netdevice.h>
12 #include <linux/netfilter_bridge.h>
13 #include <linux/random.h>
14 #include <linux/rculist.h>
15 #include <linux/skbuff.h>
16 #include <linux/slab.h>
17 #include <linux/timer.h>
18 #include <linux/inetdevice.h>
19 #include <linux/mroute.h>
20 #include <net/ip.h>
21 #include <net/switchdev.h>
22 #if IS_ENABLED(CONFIG_IPV6)
23 #include <linux/icmpv6.h>
24 #include <net/ipv6.h>
25 #include <net/mld.h>
26 #include <net/ip6_checksum.h>
27 #include <net/addrconf.h>
28 #endif
29
30 #include "br_private.h"
31 #include "br_private_mcast_eht.h"
32
33 static bool br_multicast_del_eht_set_entry(struct net_bridge_port_group *pg,
34                                            union net_bridge_eht_addr *src_addr,
35                                            union net_bridge_eht_addr *h_addr);
36 static void br_multicast_create_eht_set_entry(struct net_bridge_port_group *pg,
37                                               union net_bridge_eht_addr *src_addr,
38                                               union net_bridge_eht_addr *h_addr,
39                                               int filter_mode,
40                                               bool allow_zero_src);
41
42 static struct net_bridge_group_eht_host *
43 br_multicast_eht_host_lookup(struct net_bridge_port_group *pg,
44                              union net_bridge_eht_addr *h_addr)
45 {
46         struct rb_node *node = pg->eht_host_tree.rb_node;
47
48         while (node) {
49                 struct net_bridge_group_eht_host *this;
50                 int result;
51
52                 this = rb_entry(node, struct net_bridge_group_eht_host,
53                                 rb_node);
54                 result = memcmp(h_addr, &this->h_addr, sizeof(*h_addr));
55                 if (result < 0)
56                         node = node->rb_left;
57                 else if (result > 0)
58                         node = node->rb_right;
59                 else
60                         return this;
61         }
62
63         return NULL;
64 }
65
66 static int br_multicast_eht_host_filter_mode(struct net_bridge_port_group *pg,
67                                              union net_bridge_eht_addr *h_addr)
68 {
69         struct net_bridge_group_eht_host *eht_host;
70
71         eht_host = br_multicast_eht_host_lookup(pg, h_addr);
72         if (!eht_host)
73                 return MCAST_INCLUDE;
74
75         return eht_host->filter_mode;
76 }
77
78 static struct net_bridge_group_eht_set_entry *
79 br_multicast_eht_set_entry_lookup(struct net_bridge_group_eht_set *eht_set,
80                                   union net_bridge_eht_addr *h_addr)
81 {
82         struct rb_node *node = eht_set->entry_tree.rb_node;
83
84         while (node) {
85                 struct net_bridge_group_eht_set_entry *this;
86                 int result;
87
88                 this = rb_entry(node, struct net_bridge_group_eht_set_entry,
89                                 rb_node);
90                 result = memcmp(h_addr, &this->h_addr, sizeof(*h_addr));
91                 if (result < 0)
92                         node = node->rb_left;
93                 else if (result > 0)
94                         node = node->rb_right;
95                 else
96                         return this;
97         }
98
99         return NULL;
100 }
101
102 static struct net_bridge_group_eht_set *
103 br_multicast_eht_set_lookup(struct net_bridge_port_group *pg,
104                             union net_bridge_eht_addr *src_addr)
105 {
106         struct rb_node *node = pg->eht_set_tree.rb_node;
107
108         while (node) {
109                 struct net_bridge_group_eht_set *this;
110                 int result;
111
112                 this = rb_entry(node, struct net_bridge_group_eht_set,
113                                 rb_node);
114                 result = memcmp(src_addr, &this->src_addr, sizeof(*src_addr));
115                 if (result < 0)
116                         node = node->rb_left;
117                 else if (result > 0)
118                         node = node->rb_right;
119                 else
120                         return this;
121         }
122
123         return NULL;
124 }
125
126 static void __eht_destroy_host(struct net_bridge_group_eht_host *eht_host)
127 {
128         WARN_ON(!hlist_empty(&eht_host->set_entries));
129
130         br_multicast_eht_hosts_dec(eht_host->pg);
131
132         rb_erase(&eht_host->rb_node, &eht_host->pg->eht_host_tree);
133         RB_CLEAR_NODE(&eht_host->rb_node);
134         kfree(eht_host);
135 }
136
137 static void br_multicast_destroy_eht_set_entry(struct net_bridge_mcast_gc *gc)
138 {
139         struct net_bridge_group_eht_set_entry *set_h;
140
141         set_h = container_of(gc, struct net_bridge_group_eht_set_entry, mcast_gc);
142         WARN_ON(!RB_EMPTY_NODE(&set_h->rb_node));
143
144         del_timer_sync(&set_h->timer);
145         kfree(set_h);
146 }
147
148 static void br_multicast_destroy_eht_set(struct net_bridge_mcast_gc *gc)
149 {
150         struct net_bridge_group_eht_set *eht_set;
151
152         eht_set = container_of(gc, struct net_bridge_group_eht_set, mcast_gc);
153         WARN_ON(!RB_EMPTY_NODE(&eht_set->rb_node));
154         WARN_ON(!RB_EMPTY_ROOT(&eht_set->entry_tree));
155
156         del_timer_sync(&eht_set->timer);
157         kfree(eht_set);
158 }
159
160 static void __eht_del_set_entry(struct net_bridge_group_eht_set_entry *set_h)
161 {
162         struct net_bridge_group_eht_host *eht_host = set_h->h_parent;
163         union net_bridge_eht_addr zero_addr;
164
165         rb_erase(&set_h->rb_node, &set_h->eht_set->entry_tree);
166         RB_CLEAR_NODE(&set_h->rb_node);
167         hlist_del_init(&set_h->host_list);
168         memset(&zero_addr, 0, sizeof(zero_addr));
169         if (memcmp(&set_h->h_addr, &zero_addr, sizeof(zero_addr)))
170                 eht_host->num_entries--;
171         hlist_add_head(&set_h->mcast_gc.gc_node, &set_h->br->mcast_gc_list);
172         queue_work(system_long_wq, &set_h->br->mcast_gc_work);
173
174         if (hlist_empty(&eht_host->set_entries))
175                 __eht_destroy_host(eht_host);
176 }
177
178 static void br_multicast_del_eht_set(struct net_bridge_group_eht_set *eht_set)
179 {
180         struct net_bridge_group_eht_set_entry *set_h;
181         struct rb_node *node;
182
183         while ((node = rb_first(&eht_set->entry_tree))) {
184                 set_h = rb_entry(node, struct net_bridge_group_eht_set_entry,
185                                  rb_node);
186                 __eht_del_set_entry(set_h);
187         }
188
189         rb_erase(&eht_set->rb_node, &eht_set->pg->eht_set_tree);
190         RB_CLEAR_NODE(&eht_set->rb_node);
191         hlist_add_head(&eht_set->mcast_gc.gc_node, &eht_set->br->mcast_gc_list);
192         queue_work(system_long_wq, &eht_set->br->mcast_gc_work);
193 }
194
195 void br_multicast_eht_clean_sets(struct net_bridge_port_group *pg)
196 {
197         struct net_bridge_group_eht_set *eht_set;
198         struct rb_node *node;
199
200         while ((node = rb_first(&pg->eht_set_tree))) {
201                 eht_set = rb_entry(node, struct net_bridge_group_eht_set,
202                                    rb_node);
203                 br_multicast_del_eht_set(eht_set);
204         }
205 }
206
207 static void br_multicast_eht_set_entry_expired(struct timer_list *t)
208 {
209         struct net_bridge_group_eht_set_entry *set_h = from_timer(set_h, t, timer);
210         struct net_bridge *br = set_h->br;
211
212         spin_lock(&br->multicast_lock);
213         if (RB_EMPTY_NODE(&set_h->rb_node) || timer_pending(&set_h->timer))
214                 goto out;
215
216         br_multicast_del_eht_set_entry(set_h->eht_set->pg,
217                                        &set_h->eht_set->src_addr,
218                                        &set_h->h_addr);
219 out:
220         spin_unlock(&br->multicast_lock);
221 }
222
223 static void br_multicast_eht_set_expired(struct timer_list *t)
224 {
225         struct net_bridge_group_eht_set *eht_set = from_timer(eht_set, t,
226                                                               timer);
227         struct net_bridge *br = eht_set->br;
228
229         spin_lock(&br->multicast_lock);
230         if (RB_EMPTY_NODE(&eht_set->rb_node) || timer_pending(&eht_set->timer))
231                 goto out;
232
233         br_multicast_del_eht_set(eht_set);
234 out:
235         spin_unlock(&br->multicast_lock);
236 }
237
238 static struct net_bridge_group_eht_host *
239 __eht_lookup_create_host(struct net_bridge_port_group *pg,
240                          union net_bridge_eht_addr *h_addr,
241                          unsigned char filter_mode)
242 {
243         struct rb_node **link = &pg->eht_host_tree.rb_node, *parent = NULL;
244         struct net_bridge_group_eht_host *eht_host;
245
246         while (*link) {
247                 struct net_bridge_group_eht_host *this;
248                 int result;
249
250                 this = rb_entry(*link, struct net_bridge_group_eht_host,
251                                 rb_node);
252                 result = memcmp(h_addr, &this->h_addr, sizeof(*h_addr));
253                 parent = *link;
254                 if (result < 0)
255                         link = &((*link)->rb_left);
256                 else if (result > 0)
257                         link = &((*link)->rb_right);
258                 else
259                         return this;
260         }
261
262         if (br_multicast_eht_hosts_over_limit(pg))
263                 return NULL;
264
265         eht_host = kzalloc(sizeof(*eht_host), GFP_ATOMIC);
266         if (!eht_host)
267                 return NULL;
268
269         memcpy(&eht_host->h_addr, h_addr, sizeof(*h_addr));
270         INIT_HLIST_HEAD(&eht_host->set_entries);
271         eht_host->pg = pg;
272         eht_host->filter_mode = filter_mode;
273
274         rb_link_node(&eht_host->rb_node, parent, link);
275         rb_insert_color(&eht_host->rb_node, &pg->eht_host_tree);
276
277         br_multicast_eht_hosts_inc(pg);
278
279         return eht_host;
280 }
281
282 static struct net_bridge_group_eht_set_entry *
283 __eht_lookup_create_set_entry(struct net_bridge *br,
284                               struct net_bridge_group_eht_set *eht_set,
285                               struct net_bridge_group_eht_host *eht_host,
286                               bool allow_zero_src)
287 {
288         struct rb_node **link = &eht_set->entry_tree.rb_node, *parent = NULL;
289         struct net_bridge_group_eht_set_entry *set_h;
290
291         while (*link) {
292                 struct net_bridge_group_eht_set_entry *this;
293                 int result;
294
295                 this = rb_entry(*link, struct net_bridge_group_eht_set_entry,
296                                 rb_node);
297                 result = memcmp(&eht_host->h_addr, &this->h_addr,
298                                 sizeof(union net_bridge_eht_addr));
299                 parent = *link;
300                 if (result < 0)
301                         link = &((*link)->rb_left);
302                 else if (result > 0)
303                         link = &((*link)->rb_right);
304                 else
305                         return this;
306         }
307
308         /* always allow auto-created zero entry */
309         if (!allow_zero_src && eht_host->num_entries >= PG_SRC_ENT_LIMIT)
310                 return NULL;
311
312         set_h = kzalloc(sizeof(*set_h), GFP_ATOMIC);
313         if (!set_h)
314                 return NULL;
315
316         memcpy(&set_h->h_addr, &eht_host->h_addr,
317                sizeof(union net_bridge_eht_addr));
318         set_h->mcast_gc.destroy = br_multicast_destroy_eht_set_entry;
319         set_h->eht_set = eht_set;
320         set_h->h_parent = eht_host;
321         set_h->br = br;
322         timer_setup(&set_h->timer, br_multicast_eht_set_entry_expired, 0);
323
324         hlist_add_head(&set_h->host_list, &eht_host->set_entries);
325         rb_link_node(&set_h->rb_node, parent, link);
326         rb_insert_color(&set_h->rb_node, &eht_set->entry_tree);
327         /* we must not count the auto-created zero entry otherwise we won't be
328          * able to track the full list of PG_SRC_ENT_LIMIT entries
329          */
330         if (!allow_zero_src)
331                 eht_host->num_entries++;
332
333         return set_h;
334 }
335
336 static struct net_bridge_group_eht_set *
337 __eht_lookup_create_set(struct net_bridge_port_group *pg,
338                         union net_bridge_eht_addr *src_addr)
339 {
340         struct rb_node **link = &pg->eht_set_tree.rb_node, *parent = NULL;
341         struct net_bridge_group_eht_set *eht_set;
342
343         while (*link) {
344                 struct net_bridge_group_eht_set *this;
345                 int result;
346
347                 this = rb_entry(*link, struct net_bridge_group_eht_set,
348                                 rb_node);
349                 result = memcmp(src_addr, &this->src_addr, sizeof(*src_addr));
350                 parent = *link;
351                 if (result < 0)
352                         link = &((*link)->rb_left);
353                 else if (result > 0)
354                         link = &((*link)->rb_right);
355                 else
356                         return this;
357         }
358
359         eht_set = kzalloc(sizeof(*eht_set), GFP_ATOMIC);
360         if (!eht_set)
361                 return NULL;
362
363         memcpy(&eht_set->src_addr, src_addr, sizeof(*src_addr));
364         eht_set->mcast_gc.destroy = br_multicast_destroy_eht_set;
365         eht_set->pg = pg;
366         eht_set->br = pg->key.port->br;
367         eht_set->entry_tree = RB_ROOT;
368         timer_setup(&eht_set->timer, br_multicast_eht_set_expired, 0);
369
370         rb_link_node(&eht_set->rb_node, parent, link);
371         rb_insert_color(&eht_set->rb_node, &pg->eht_set_tree);
372
373         return eht_set;
374 }
375
376 static void br_multicast_ip_src_to_eht_addr(const struct br_ip *src,
377                                             union net_bridge_eht_addr *dest)
378 {
379         switch (src->proto) {
380         case htons(ETH_P_IP):
381                 dest->ip4 = src->src.ip4;
382                 break;
383 #if IS_ENABLED(CONFIG_IPV6)
384         case htons(ETH_P_IPV6):
385                 memcpy(&dest->ip6, &src->src.ip6, sizeof(struct in6_addr));
386                 break;
387 #endif
388         }
389 }
390
391 static void br_eht_convert_host_filter_mode(struct net_bridge_port_group *pg,
392                                             union net_bridge_eht_addr *h_addr,
393                                             int filter_mode)
394 {
395         struct net_bridge_group_eht_host *eht_host;
396         union net_bridge_eht_addr zero_addr;
397
398         eht_host = br_multicast_eht_host_lookup(pg, h_addr);
399         if (eht_host)
400                 eht_host->filter_mode = filter_mode;
401
402         memset(&zero_addr, 0, sizeof(zero_addr));
403         switch (filter_mode) {
404         case MCAST_INCLUDE:
405                 br_multicast_del_eht_set_entry(pg, &zero_addr, h_addr);
406                 break;
407         case MCAST_EXCLUDE:
408                 br_multicast_create_eht_set_entry(pg, &zero_addr, h_addr,
409                                                   MCAST_EXCLUDE,
410                                                   true);
411                 break;
412         }
413 }
414
415 static void br_multicast_create_eht_set_entry(struct net_bridge_port_group *pg,
416                                               union net_bridge_eht_addr *src_addr,
417                                               union net_bridge_eht_addr *h_addr,
418                                               int filter_mode,
419                                               bool allow_zero_src)
420 {
421         struct net_bridge_group_eht_set_entry *set_h;
422         struct net_bridge_group_eht_host *eht_host;
423         struct net_bridge *br = pg->key.port->br;
424         struct net_bridge_group_eht_set *eht_set;
425         union net_bridge_eht_addr zero_addr;
426
427         memset(&zero_addr, 0, sizeof(zero_addr));
428         if (!allow_zero_src && !memcmp(src_addr, &zero_addr, sizeof(zero_addr)))
429                 return;
430
431         eht_set = __eht_lookup_create_set(pg, src_addr);
432         if (!eht_set)
433                 return;
434
435         eht_host = __eht_lookup_create_host(pg, h_addr, filter_mode);
436         if (!eht_host)
437                 goto fail_host;
438
439         set_h = __eht_lookup_create_set_entry(br, eht_set, eht_host,
440                                               allow_zero_src);
441         if (!set_h)
442                 goto fail_set_entry;
443
444         mod_timer(&set_h->timer, jiffies + br_multicast_gmi(br));
445         mod_timer(&eht_set->timer, jiffies + br_multicast_gmi(br));
446
447         return;
448
449 fail_set_entry:
450         if (hlist_empty(&eht_host->set_entries))
451                 __eht_destroy_host(eht_host);
452 fail_host:
453         if (RB_EMPTY_ROOT(&eht_set->entry_tree))
454                 br_multicast_del_eht_set(eht_set);
455 }
456
457 static bool br_multicast_del_eht_set_entry(struct net_bridge_port_group *pg,
458                                            union net_bridge_eht_addr *src_addr,
459                                            union net_bridge_eht_addr *h_addr)
460 {
461         struct net_bridge_group_eht_set_entry *set_h;
462         struct net_bridge_group_eht_set *eht_set;
463         bool set_deleted = false;
464
465         eht_set = br_multicast_eht_set_lookup(pg, src_addr);
466         if (!eht_set)
467                 goto out;
468
469         set_h = br_multicast_eht_set_entry_lookup(eht_set, h_addr);
470         if (!set_h)
471                 goto out;
472
473         __eht_del_set_entry(set_h);
474
475         if (RB_EMPTY_ROOT(&eht_set->entry_tree)) {
476                 br_multicast_del_eht_set(eht_set);
477                 set_deleted = true;
478         }
479
480 out:
481         return set_deleted;
482 }
483
484 static void br_multicast_del_eht_host(struct net_bridge_port_group *pg,
485                                       union net_bridge_eht_addr *h_addr)
486 {
487         struct net_bridge_group_eht_set_entry *set_h;
488         struct net_bridge_group_eht_host *eht_host;
489         struct hlist_node *tmp;
490
491         eht_host = br_multicast_eht_host_lookup(pg, h_addr);
492         if (!eht_host)
493                 return;
494
495         hlist_for_each_entry_safe(set_h, tmp, &eht_host->set_entries, host_list)
496                 br_multicast_del_eht_set_entry(set_h->eht_set->pg,
497                                                &set_h->eht_set->src_addr,
498                                                &set_h->h_addr);
499 }
500
501 static void __eht_allow_incl(struct net_bridge_port_group *pg,
502                              union net_bridge_eht_addr *h_addr,
503                              void *srcs,
504                              u32 nsrcs,
505                              size_t addr_size)
506 {
507         union net_bridge_eht_addr eht_src_addr;
508         u32 src_idx;
509
510         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
511         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
512                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
513                 br_multicast_create_eht_set_entry(pg, &eht_src_addr, h_addr,
514                                                   MCAST_INCLUDE,
515                                                   false);
516         }
517 }
518
519 static bool __eht_allow_excl(struct net_bridge_port_group *pg,
520                              union net_bridge_eht_addr *h_addr,
521                              void *srcs,
522                              u32 nsrcs,
523                              size_t addr_size)
524 {
525         bool changed = false, host_excl = false;
526         union net_bridge_eht_addr eht_src_addr;
527         struct net_bridge_group_src *src_ent;
528         struct br_ip src_ip;
529         u32 src_idx;
530
531         host_excl = !!(br_multicast_eht_host_filter_mode(pg, h_addr) == MCAST_EXCLUDE);
532         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
533         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
534                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
535                 if (!host_excl) {
536                         br_multicast_create_eht_set_entry(pg, &eht_src_addr, h_addr,
537                                                           MCAST_INCLUDE,
538                                                           false);
539                 } else {
540                         if (!br_multicast_del_eht_set_entry(pg, &eht_src_addr,
541                                                             h_addr))
542                                 continue;
543                         memcpy(&src_ip, srcs + (src_idx * addr_size), addr_size);
544                         src_ent = br_multicast_find_group_src(pg, &src_ip);
545                         if (!src_ent)
546                                 continue;
547                         br_multicast_del_group_src(src_ent, true);
548                         changed = true;
549                 }
550         }
551
552         return changed;
553 }
554
555 static bool br_multicast_eht_allow(struct net_bridge_port_group *pg,
556                                    union net_bridge_eht_addr *h_addr,
557                                    void *srcs,
558                                    u32 nsrcs,
559                                    size_t addr_size)
560 {
561         bool changed = false;
562
563         switch (br_multicast_eht_host_filter_mode(pg, h_addr)) {
564         case MCAST_INCLUDE:
565                 __eht_allow_incl(pg, h_addr, srcs, nsrcs, addr_size);
566                 break;
567         case MCAST_EXCLUDE:
568                 changed = __eht_allow_excl(pg, h_addr, srcs, nsrcs, addr_size);
569                 break;
570         }
571
572         return changed;
573 }
574
575 static bool __eht_block_incl(struct net_bridge_port_group *pg,
576                              union net_bridge_eht_addr *h_addr,
577                              void *srcs,
578                              u32 nsrcs,
579                              size_t addr_size)
580 {
581         union net_bridge_eht_addr eht_src_addr;
582         struct net_bridge_group_src *src_ent;
583         bool changed = false;
584         struct br_ip src_ip;
585         u32 src_idx;
586
587         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
588         memset(&src_ip, 0, sizeof(src_ip));
589         src_ip.proto = pg->key.addr.proto;
590         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
591                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
592                 if (!br_multicast_del_eht_set_entry(pg, &eht_src_addr, h_addr))
593                         continue;
594                 memcpy(&src_ip, srcs + (src_idx * addr_size), addr_size);
595                 src_ent = br_multicast_find_group_src(pg, &src_ip);
596                 if (!src_ent)
597                         continue;
598                 br_multicast_del_group_src(src_ent, true);
599                 changed = true;
600         }
601
602         return changed;
603 }
604
605 static bool __eht_block_excl(struct net_bridge_port_group *pg,
606                              union net_bridge_eht_addr *h_addr,
607                              void *srcs,
608                              u32 nsrcs,
609                              size_t addr_size)
610 {
611         bool changed = false, host_excl = false;
612         union net_bridge_eht_addr eht_src_addr;
613         struct net_bridge_group_src *src_ent;
614         struct br_ip src_ip;
615         u32 src_idx;
616
617         host_excl = !!(br_multicast_eht_host_filter_mode(pg, h_addr) == MCAST_EXCLUDE);
618         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
619         memset(&src_ip, 0, sizeof(src_ip));
620         src_ip.proto = pg->key.addr.proto;
621         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
622                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
623                 if (host_excl) {
624                         br_multicast_create_eht_set_entry(pg, &eht_src_addr, h_addr,
625                                                           MCAST_EXCLUDE,
626                                                           false);
627                 } else {
628                         if (!br_multicast_del_eht_set_entry(pg, &eht_src_addr,
629                                                             h_addr))
630                                 continue;
631                         memcpy(&src_ip, srcs + (src_idx * addr_size), addr_size);
632                         src_ent = br_multicast_find_group_src(pg, &src_ip);
633                         if (!src_ent)
634                                 continue;
635                         br_multicast_del_group_src(src_ent, true);
636                         changed = true;
637                 }
638         }
639
640         return changed;
641 }
642
643 static bool br_multicast_eht_block(struct net_bridge_port_group *pg,
644                                    union net_bridge_eht_addr *h_addr,
645                                    void *srcs,
646                                    u32 nsrcs,
647                                    size_t addr_size)
648 {
649         bool changed = false;
650
651         switch (br_multicast_eht_host_filter_mode(pg, h_addr)) {
652         case MCAST_INCLUDE:
653                 changed = __eht_block_incl(pg, h_addr, srcs, nsrcs, addr_size);
654                 break;
655         case MCAST_EXCLUDE:
656                 changed = __eht_block_excl(pg, h_addr, srcs, nsrcs, addr_size);
657                 break;
658         }
659
660         return changed;
661 }
662
663 /* flush_entries is true when changing mode */
664 static bool __eht_inc_exc(struct net_bridge_port_group *pg,
665                           union net_bridge_eht_addr *h_addr,
666                           void *srcs,
667                           u32 nsrcs,
668                           size_t addr_size,
669                           unsigned char filter_mode,
670                           bool to_report)
671 {
672         bool changed = false, flush_entries = to_report;
673         union net_bridge_eht_addr eht_src_addr;
674         u32 src_idx;
675
676         if (br_multicast_eht_host_filter_mode(pg, h_addr) != filter_mode)
677                 flush_entries = true;
678
679         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
680         /* if we're changing mode del host and its entries */
681         if (flush_entries)
682                 br_multicast_del_eht_host(pg, h_addr);
683         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
684                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
685                 br_multicast_create_eht_set_entry(pg, &eht_src_addr, h_addr,
686                                                   filter_mode, false);
687         }
688         /* we can be missing sets only if we've deleted some entries */
689         if (flush_entries) {
690                 struct net_bridge *br = pg->key.port->br;
691                 struct net_bridge_group_eht_set *eht_set;
692                 struct net_bridge_group_src *src_ent;
693                 struct hlist_node *tmp;
694
695                 hlist_for_each_entry_safe(src_ent, tmp, &pg->src_list, node) {
696                         br_multicast_ip_src_to_eht_addr(&src_ent->addr,
697                                                         &eht_src_addr);
698                         if (!br_multicast_eht_set_lookup(pg, &eht_src_addr)) {
699                                 br_multicast_del_group_src(src_ent, true);
700                                 changed = true;
701                                 continue;
702                         }
703                         /* this is an optimization for TO_INCLUDE where we lower
704                          * the set's timeout to LMQT to catch timeout hosts:
705                          * - host A (timing out): set entries X, Y
706                          * - host B: set entry Z (new from current TO_INCLUDE)
707                          *           sends BLOCK Z after LMQT but host A's EHT
708                          *           entries still exist (unless lowered to LMQT
709                          *           so they can timeout with the S,Gs)
710                          * => we wait another LMQT, when we can just delete the
711                          *    group immediately
712                          */
713                         if (!(src_ent->flags & BR_SGRP_F_SEND) ||
714                             filter_mode != MCAST_INCLUDE ||
715                             !to_report)
716                                 continue;
717                         eht_set = br_multicast_eht_set_lookup(pg,
718                                                               &eht_src_addr);
719                         if (!eht_set)
720                                 continue;
721                         mod_timer(&eht_set->timer, jiffies + br_multicast_lmqt(br));
722                 }
723         }
724
725         return changed;
726 }
727
728 static bool br_multicast_eht_inc(struct net_bridge_port_group *pg,
729                                  union net_bridge_eht_addr *h_addr,
730                                  void *srcs,
731                                  u32 nsrcs,
732                                  size_t addr_size,
733                                  bool to_report)
734 {
735         bool changed;
736
737         changed = __eht_inc_exc(pg, h_addr, srcs, nsrcs, addr_size,
738                                 MCAST_INCLUDE, to_report);
739         br_eht_convert_host_filter_mode(pg, h_addr, MCAST_INCLUDE);
740
741         return changed;
742 }
743
744 static bool br_multicast_eht_exc(struct net_bridge_port_group *pg,
745                                  union net_bridge_eht_addr *h_addr,
746                                  void *srcs,
747                                  u32 nsrcs,
748                                  size_t addr_size,
749                                  bool to_report)
750 {
751         bool changed;
752
753         changed = __eht_inc_exc(pg, h_addr, srcs, nsrcs, addr_size,
754                                 MCAST_EXCLUDE, to_report);
755         br_eht_convert_host_filter_mode(pg, h_addr, MCAST_EXCLUDE);
756
757         return changed;
758 }
759
760 static bool __eht_ip4_handle(struct net_bridge_port_group *pg,
761                              union net_bridge_eht_addr *h_addr,
762                              void *srcs,
763                              u32 nsrcs,
764                              int grec_type)
765 {
766         bool changed = false, to_report = false;
767
768         switch (grec_type) {
769         case IGMPV3_ALLOW_NEW_SOURCES:
770                 br_multicast_eht_allow(pg, h_addr, srcs, nsrcs, sizeof(__be32));
771                 break;
772         case IGMPV3_BLOCK_OLD_SOURCES:
773                 changed = br_multicast_eht_block(pg, h_addr, srcs, nsrcs,
774                                                  sizeof(__be32));
775                 break;
776         case IGMPV3_CHANGE_TO_INCLUDE:
777                 to_report = true;
778                 fallthrough;
779         case IGMPV3_MODE_IS_INCLUDE:
780                 changed = br_multicast_eht_inc(pg, h_addr, srcs, nsrcs,
781                                                sizeof(__be32), to_report);
782                 break;
783         case IGMPV3_CHANGE_TO_EXCLUDE:
784                 to_report = true;
785                 fallthrough;
786         case IGMPV3_MODE_IS_EXCLUDE:
787                 changed = br_multicast_eht_exc(pg, h_addr, srcs, nsrcs,
788                                                sizeof(__be32), to_report);
789                 break;
790         }
791
792         return changed;
793 }
794
795 #if IS_ENABLED(CONFIG_IPV6)
796 static bool __eht_ip6_handle(struct net_bridge_port_group *pg,
797                              union net_bridge_eht_addr *h_addr,
798                              void *srcs,
799                              u32 nsrcs,
800                              int grec_type)
801 {
802         bool changed = false, to_report = false;
803
804         switch (grec_type) {
805         case MLD2_ALLOW_NEW_SOURCES:
806                 br_multicast_eht_allow(pg, h_addr, srcs, nsrcs,
807                                        sizeof(struct in6_addr));
808                 break;
809         case MLD2_BLOCK_OLD_SOURCES:
810                 changed = br_multicast_eht_block(pg, h_addr, srcs, nsrcs,
811                                                  sizeof(struct in6_addr));
812                 break;
813         case MLD2_CHANGE_TO_INCLUDE:
814                 to_report = true;
815                 fallthrough;
816         case MLD2_MODE_IS_INCLUDE:
817                 changed = br_multicast_eht_inc(pg, h_addr, srcs, nsrcs,
818                                                sizeof(struct in6_addr),
819                                                to_report);
820                 break;
821         case MLD2_CHANGE_TO_EXCLUDE:
822                 to_report = true;
823                 fallthrough;
824         case MLD2_MODE_IS_EXCLUDE:
825                 changed = br_multicast_eht_exc(pg, h_addr, srcs, nsrcs,
826                                                sizeof(struct in6_addr),
827                                                to_report);
828                 break;
829         }
830
831         return changed;
832 }
833 #endif
834
835 /* true means an entry was deleted */
836 bool br_multicast_eht_handle(struct net_bridge_port_group *pg,
837                              void *h_addr,
838                              void *srcs,
839                              u32 nsrcs,
840                              size_t addr_size,
841                              int grec_type)
842 {
843         bool eht_enabled = !!(pg->key.port->flags & BR_MULTICAST_FAST_LEAVE);
844         union net_bridge_eht_addr eht_host_addr;
845         bool changed = false;
846
847         if (!eht_enabled)
848                 goto out;
849
850         memset(&eht_host_addr, 0, sizeof(eht_host_addr));
851         memcpy(&eht_host_addr, h_addr, addr_size);
852         if (addr_size == sizeof(__be32))
853                 changed = __eht_ip4_handle(pg, &eht_host_addr, srcs, nsrcs,
854                                            grec_type);
855 #if IS_ENABLED(CONFIG_IPV6)
856         else
857                 changed = __eht_ip6_handle(pg, &eht_host_addr, srcs, nsrcs,
858                                            grec_type);
859 #endif
860
861 out:
862         return changed;
863 }
864
865 int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p,
866                                      u32 eht_hosts_limit)
867 {
868         struct net_bridge *br = p->br;
869
870         if (!eht_hosts_limit)
871                 return -EINVAL;
872
873         spin_lock_bh(&br->multicast_lock);
874         p->multicast_eht_hosts_limit = eht_hosts_limit;
875         spin_unlock_bh(&br->multicast_lock);
876
877         return 0;
878 }