virtio/vsock: support MSG_EOR bit processing
[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 /* create new set entries from reports */
502 static void __eht_create_set_entries(struct net_bridge_port_group *pg,
503                                      union net_bridge_eht_addr *h_addr,
504                                      void *srcs,
505                                      u32 nsrcs,
506                                      size_t addr_size,
507                                      int filter_mode)
508 {
509         union net_bridge_eht_addr eht_src_addr;
510         u32 src_idx;
511
512         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
513         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
514                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
515                 br_multicast_create_eht_set_entry(pg, &eht_src_addr, h_addr,
516                                                   filter_mode,
517                                                   false);
518         }
519 }
520
521 /* delete existing set entries and their (S,G) entries if they were the last */
522 static bool __eht_del_set_entries(struct net_bridge_port_group *pg,
523                                   union net_bridge_eht_addr *h_addr,
524                                   void *srcs,
525                                   u32 nsrcs,
526                                   size_t addr_size)
527 {
528         union net_bridge_eht_addr eht_src_addr;
529         struct net_bridge_group_src *src_ent;
530         bool changed = false;
531         struct br_ip src_ip;
532         u32 src_idx;
533
534         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
535         memset(&src_ip, 0, sizeof(src_ip));
536         src_ip.proto = pg->key.addr.proto;
537         for (src_idx = 0; src_idx < nsrcs; src_idx++) {
538                 memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
539                 if (!br_multicast_del_eht_set_entry(pg, &eht_src_addr, h_addr))
540                         continue;
541                 memcpy(&src_ip, srcs + (src_idx * addr_size), addr_size);
542                 src_ent = br_multicast_find_group_src(pg, &src_ip);
543                 if (!src_ent)
544                         continue;
545                 br_multicast_del_group_src(src_ent, true);
546                 changed = true;
547         }
548
549         return changed;
550 }
551
552 static bool br_multicast_eht_allow(struct net_bridge_port_group *pg,
553                                    union net_bridge_eht_addr *h_addr,
554                                    void *srcs,
555                                    u32 nsrcs,
556                                    size_t addr_size)
557 {
558         bool changed = false;
559
560         switch (br_multicast_eht_host_filter_mode(pg, h_addr)) {
561         case MCAST_INCLUDE:
562                 __eht_create_set_entries(pg, h_addr, srcs, nsrcs, addr_size,
563                                          MCAST_INCLUDE);
564                 break;
565         case MCAST_EXCLUDE:
566                 changed = __eht_del_set_entries(pg, h_addr, srcs, nsrcs,
567                                                 addr_size);
568                 break;
569         }
570
571         return changed;
572 }
573
574 static bool br_multicast_eht_block(struct net_bridge_port_group *pg,
575                                    union net_bridge_eht_addr *h_addr,
576                                    void *srcs,
577                                    u32 nsrcs,
578                                    size_t addr_size)
579 {
580         bool changed = false;
581
582         switch (br_multicast_eht_host_filter_mode(pg, h_addr)) {
583         case MCAST_INCLUDE:
584                 changed = __eht_del_set_entries(pg, h_addr, srcs, nsrcs,
585                                                 addr_size);
586                 break;
587         case MCAST_EXCLUDE:
588                 __eht_create_set_entries(pg, h_addr, srcs, nsrcs, addr_size,
589                                          MCAST_EXCLUDE);
590                 break;
591         }
592
593         return changed;
594 }
595
596 /* flush_entries is true when changing mode */
597 static bool __eht_inc_exc(struct net_bridge_port_group *pg,
598                           union net_bridge_eht_addr *h_addr,
599                           void *srcs,
600                           u32 nsrcs,
601                           size_t addr_size,
602                           unsigned char filter_mode,
603                           bool to_report)
604 {
605         bool changed = false, flush_entries = to_report;
606         union net_bridge_eht_addr eht_src_addr;
607
608         if (br_multicast_eht_host_filter_mode(pg, h_addr) != filter_mode)
609                 flush_entries = true;
610
611         memset(&eht_src_addr, 0, sizeof(eht_src_addr));
612         /* if we're changing mode del host and its entries */
613         if (flush_entries)
614                 br_multicast_del_eht_host(pg, h_addr);
615         __eht_create_set_entries(pg, h_addr, srcs, nsrcs, addr_size,
616                                  filter_mode);
617         /* we can be missing sets only if we've deleted some entries */
618         if (flush_entries) {
619                 struct net_bridge *br = pg->key.port->br;
620                 struct net_bridge_group_eht_set *eht_set;
621                 struct net_bridge_group_src *src_ent;
622                 struct hlist_node *tmp;
623
624                 hlist_for_each_entry_safe(src_ent, tmp, &pg->src_list, node) {
625                         br_multicast_ip_src_to_eht_addr(&src_ent->addr,
626                                                         &eht_src_addr);
627                         if (!br_multicast_eht_set_lookup(pg, &eht_src_addr)) {
628                                 br_multicast_del_group_src(src_ent, true);
629                                 changed = true;
630                                 continue;
631                         }
632                         /* this is an optimization for TO_INCLUDE where we lower
633                          * the set's timeout to LMQT to catch timeout hosts:
634                          * - host A (timing out): set entries X, Y
635                          * - host B: set entry Z (new from current TO_INCLUDE)
636                          *           sends BLOCK Z after LMQT but host A's EHT
637                          *           entries still exist (unless lowered to LMQT
638                          *           so they can timeout with the S,Gs)
639                          * => we wait another LMQT, when we can just delete the
640                          *    group immediately
641                          */
642                         if (!(src_ent->flags & BR_SGRP_F_SEND) ||
643                             filter_mode != MCAST_INCLUDE ||
644                             !to_report)
645                                 continue;
646                         eht_set = br_multicast_eht_set_lookup(pg,
647                                                               &eht_src_addr);
648                         if (!eht_set)
649                                 continue;
650                         mod_timer(&eht_set->timer, jiffies + br_multicast_lmqt(br));
651                 }
652         }
653
654         return changed;
655 }
656
657 static bool br_multicast_eht_inc(struct net_bridge_port_group *pg,
658                                  union net_bridge_eht_addr *h_addr,
659                                  void *srcs,
660                                  u32 nsrcs,
661                                  size_t addr_size,
662                                  bool to_report)
663 {
664         bool changed;
665
666         changed = __eht_inc_exc(pg, h_addr, srcs, nsrcs, addr_size,
667                                 MCAST_INCLUDE, to_report);
668         br_eht_convert_host_filter_mode(pg, h_addr, MCAST_INCLUDE);
669
670         return changed;
671 }
672
673 static bool br_multicast_eht_exc(struct net_bridge_port_group *pg,
674                                  union net_bridge_eht_addr *h_addr,
675                                  void *srcs,
676                                  u32 nsrcs,
677                                  size_t addr_size,
678                                  bool to_report)
679 {
680         bool changed;
681
682         changed = __eht_inc_exc(pg, h_addr, srcs, nsrcs, addr_size,
683                                 MCAST_EXCLUDE, to_report);
684         br_eht_convert_host_filter_mode(pg, h_addr, MCAST_EXCLUDE);
685
686         return changed;
687 }
688
689 static bool __eht_ip4_handle(struct net_bridge_port_group *pg,
690                              union net_bridge_eht_addr *h_addr,
691                              void *srcs,
692                              u32 nsrcs,
693                              int grec_type)
694 {
695         bool changed = false, to_report = false;
696
697         switch (grec_type) {
698         case IGMPV3_ALLOW_NEW_SOURCES:
699                 br_multicast_eht_allow(pg, h_addr, srcs, nsrcs, sizeof(__be32));
700                 break;
701         case IGMPV3_BLOCK_OLD_SOURCES:
702                 changed = br_multicast_eht_block(pg, h_addr, srcs, nsrcs,
703                                                  sizeof(__be32));
704                 break;
705         case IGMPV3_CHANGE_TO_INCLUDE:
706                 to_report = true;
707                 fallthrough;
708         case IGMPV3_MODE_IS_INCLUDE:
709                 changed = br_multicast_eht_inc(pg, h_addr, srcs, nsrcs,
710                                                sizeof(__be32), to_report);
711                 break;
712         case IGMPV3_CHANGE_TO_EXCLUDE:
713                 to_report = true;
714                 fallthrough;
715         case IGMPV3_MODE_IS_EXCLUDE:
716                 changed = br_multicast_eht_exc(pg, h_addr, srcs, nsrcs,
717                                                sizeof(__be32), to_report);
718                 break;
719         }
720
721         return changed;
722 }
723
724 #if IS_ENABLED(CONFIG_IPV6)
725 static bool __eht_ip6_handle(struct net_bridge_port_group *pg,
726                              union net_bridge_eht_addr *h_addr,
727                              void *srcs,
728                              u32 nsrcs,
729                              int grec_type)
730 {
731         bool changed = false, to_report = false;
732
733         switch (grec_type) {
734         case MLD2_ALLOW_NEW_SOURCES:
735                 br_multicast_eht_allow(pg, h_addr, srcs, nsrcs,
736                                        sizeof(struct in6_addr));
737                 break;
738         case MLD2_BLOCK_OLD_SOURCES:
739                 changed = br_multicast_eht_block(pg, h_addr, srcs, nsrcs,
740                                                  sizeof(struct in6_addr));
741                 break;
742         case MLD2_CHANGE_TO_INCLUDE:
743                 to_report = true;
744                 fallthrough;
745         case MLD2_MODE_IS_INCLUDE:
746                 changed = br_multicast_eht_inc(pg, h_addr, srcs, nsrcs,
747                                                sizeof(struct in6_addr),
748                                                to_report);
749                 break;
750         case MLD2_CHANGE_TO_EXCLUDE:
751                 to_report = true;
752                 fallthrough;
753         case MLD2_MODE_IS_EXCLUDE:
754                 changed = br_multicast_eht_exc(pg, h_addr, srcs, nsrcs,
755                                                sizeof(struct in6_addr),
756                                                to_report);
757                 break;
758         }
759
760         return changed;
761 }
762 #endif
763
764 /* true means an entry was deleted */
765 bool br_multicast_eht_handle(struct net_bridge_port_group *pg,
766                              void *h_addr,
767                              void *srcs,
768                              u32 nsrcs,
769                              size_t addr_size,
770                              int grec_type)
771 {
772         bool eht_enabled = !!(pg->key.port->flags & BR_MULTICAST_FAST_LEAVE);
773         union net_bridge_eht_addr eht_host_addr;
774         bool changed = false;
775
776         if (!eht_enabled)
777                 goto out;
778
779         memset(&eht_host_addr, 0, sizeof(eht_host_addr));
780         memcpy(&eht_host_addr, h_addr, addr_size);
781         if (addr_size == sizeof(__be32))
782                 changed = __eht_ip4_handle(pg, &eht_host_addr, srcs, nsrcs,
783                                            grec_type);
784 #if IS_ENABLED(CONFIG_IPV6)
785         else
786                 changed = __eht_ip6_handle(pg, &eht_host_addr, srcs, nsrcs,
787                                            grec_type);
788 #endif
789
790 out:
791         return changed;
792 }
793
794 int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p,
795                                      u32 eht_hosts_limit)
796 {
797         struct net_bridge *br = p->br;
798
799         if (!eht_hosts_limit)
800                 return -EINVAL;
801
802         spin_lock_bh(&br->multicast_lock);
803         p->multicast_eht_hosts_limit = eht_hosts_limit;
804         spin_unlock_bh(&br->multicast_lock);
805
806         return 0;
807 }