Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 // Copyright (c) 2020, Nikolay Aleksandrov <nikolay@nvidia.com>
0003 #include <linux/err.h>
0004 #include <linux/export.h>
0005 #include <linux/if_ether.h>
0006 #include <linux/igmp.h>
0007 #include <linux/in.h>
0008 #include <linux/jhash.h>
0009 #include <linux/kernel.h>
0010 #include <linux/log2.h>
0011 #include <linux/netdevice.h>
0012 #include <linux/netfilter_bridge.h>
0013 #include <linux/random.h>
0014 #include <linux/rculist.h>
0015 #include <linux/skbuff.h>
0016 #include <linux/slab.h>
0017 #include <linux/timer.h>
0018 #include <linux/inetdevice.h>
0019 #include <linux/mroute.h>
0020 #include <net/ip.h>
0021 #include <net/switchdev.h>
0022 #if IS_ENABLED(CONFIG_IPV6)
0023 #include <linux/icmpv6.h>
0024 #include <net/ipv6.h>
0025 #include <net/mld.h>
0026 #include <net/ip6_checksum.h>
0027 #include <net/addrconf.h>
0028 #endif
0029 
0030 #include "br_private.h"
0031 #include "br_private_mcast_eht.h"
0032 
0033 static bool br_multicast_del_eht_set_entry(struct net_bridge_port_group *pg,
0034                        union net_bridge_eht_addr *src_addr,
0035                        union net_bridge_eht_addr *h_addr);
0036 static void br_multicast_create_eht_set_entry(const struct net_bridge_mcast *brmctx,
0037                           struct net_bridge_port_group *pg,
0038                           union net_bridge_eht_addr *src_addr,
0039                           union net_bridge_eht_addr *h_addr,
0040                           int filter_mode,
0041                           bool allow_zero_src);
0042 
0043 static struct net_bridge_group_eht_host *
0044 br_multicast_eht_host_lookup(struct net_bridge_port_group *pg,
0045                  union net_bridge_eht_addr *h_addr)
0046 {
0047     struct rb_node *node = pg->eht_host_tree.rb_node;
0048 
0049     while (node) {
0050         struct net_bridge_group_eht_host *this;
0051         int result;
0052 
0053         this = rb_entry(node, struct net_bridge_group_eht_host,
0054                 rb_node);
0055         result = memcmp(h_addr, &this->h_addr, sizeof(*h_addr));
0056         if (result < 0)
0057             node = node->rb_left;
0058         else if (result > 0)
0059             node = node->rb_right;
0060         else
0061             return this;
0062     }
0063 
0064     return NULL;
0065 }
0066 
0067 static int br_multicast_eht_host_filter_mode(struct net_bridge_port_group *pg,
0068                          union net_bridge_eht_addr *h_addr)
0069 {
0070     struct net_bridge_group_eht_host *eht_host;
0071 
0072     eht_host = br_multicast_eht_host_lookup(pg, h_addr);
0073     if (!eht_host)
0074         return MCAST_INCLUDE;
0075 
0076     return eht_host->filter_mode;
0077 }
0078 
0079 static struct net_bridge_group_eht_set_entry *
0080 br_multicast_eht_set_entry_lookup(struct net_bridge_group_eht_set *eht_set,
0081                   union net_bridge_eht_addr *h_addr)
0082 {
0083     struct rb_node *node = eht_set->entry_tree.rb_node;
0084 
0085     while (node) {
0086         struct net_bridge_group_eht_set_entry *this;
0087         int result;
0088 
0089         this = rb_entry(node, struct net_bridge_group_eht_set_entry,
0090                 rb_node);
0091         result = memcmp(h_addr, &this->h_addr, sizeof(*h_addr));
0092         if (result < 0)
0093             node = node->rb_left;
0094         else if (result > 0)
0095             node = node->rb_right;
0096         else
0097             return this;
0098     }
0099 
0100     return NULL;
0101 }
0102 
0103 static struct net_bridge_group_eht_set *
0104 br_multicast_eht_set_lookup(struct net_bridge_port_group *pg,
0105                 union net_bridge_eht_addr *src_addr)
0106 {
0107     struct rb_node *node = pg->eht_set_tree.rb_node;
0108 
0109     while (node) {
0110         struct net_bridge_group_eht_set *this;
0111         int result;
0112 
0113         this = rb_entry(node, struct net_bridge_group_eht_set,
0114                 rb_node);
0115         result = memcmp(src_addr, &this->src_addr, sizeof(*src_addr));
0116         if (result < 0)
0117             node = node->rb_left;
0118         else if (result > 0)
0119             node = node->rb_right;
0120         else
0121             return this;
0122     }
0123 
0124     return NULL;
0125 }
0126 
0127 static void __eht_destroy_host(struct net_bridge_group_eht_host *eht_host)
0128 {
0129     WARN_ON(!hlist_empty(&eht_host->set_entries));
0130 
0131     br_multicast_eht_hosts_dec(eht_host->pg);
0132 
0133     rb_erase(&eht_host->rb_node, &eht_host->pg->eht_host_tree);
0134     RB_CLEAR_NODE(&eht_host->rb_node);
0135     kfree(eht_host);
0136 }
0137 
0138 static void br_multicast_destroy_eht_set_entry(struct net_bridge_mcast_gc *gc)
0139 {
0140     struct net_bridge_group_eht_set_entry *set_h;
0141 
0142     set_h = container_of(gc, struct net_bridge_group_eht_set_entry, mcast_gc);
0143     WARN_ON(!RB_EMPTY_NODE(&set_h->rb_node));
0144 
0145     del_timer_sync(&set_h->timer);
0146     kfree(set_h);
0147 }
0148 
0149 static void br_multicast_destroy_eht_set(struct net_bridge_mcast_gc *gc)
0150 {
0151     struct net_bridge_group_eht_set *eht_set;
0152 
0153     eht_set = container_of(gc, struct net_bridge_group_eht_set, mcast_gc);
0154     WARN_ON(!RB_EMPTY_NODE(&eht_set->rb_node));
0155     WARN_ON(!RB_EMPTY_ROOT(&eht_set->entry_tree));
0156 
0157     del_timer_sync(&eht_set->timer);
0158     kfree(eht_set);
0159 }
0160 
0161 static void __eht_del_set_entry(struct net_bridge_group_eht_set_entry *set_h)
0162 {
0163     struct net_bridge_group_eht_host *eht_host = set_h->h_parent;
0164     union net_bridge_eht_addr zero_addr;
0165 
0166     rb_erase(&set_h->rb_node, &set_h->eht_set->entry_tree);
0167     RB_CLEAR_NODE(&set_h->rb_node);
0168     hlist_del_init(&set_h->host_list);
0169     memset(&zero_addr, 0, sizeof(zero_addr));
0170     if (memcmp(&set_h->h_addr, &zero_addr, sizeof(zero_addr)))
0171         eht_host->num_entries--;
0172     hlist_add_head(&set_h->mcast_gc.gc_node, &set_h->br->mcast_gc_list);
0173     queue_work(system_long_wq, &set_h->br->mcast_gc_work);
0174 
0175     if (hlist_empty(&eht_host->set_entries))
0176         __eht_destroy_host(eht_host);
0177 }
0178 
0179 static void br_multicast_del_eht_set(struct net_bridge_group_eht_set *eht_set)
0180 {
0181     struct net_bridge_group_eht_set_entry *set_h;
0182     struct rb_node *node;
0183 
0184     while ((node = rb_first(&eht_set->entry_tree))) {
0185         set_h = rb_entry(node, struct net_bridge_group_eht_set_entry,
0186                  rb_node);
0187         __eht_del_set_entry(set_h);
0188     }
0189 
0190     rb_erase(&eht_set->rb_node, &eht_set->pg->eht_set_tree);
0191     RB_CLEAR_NODE(&eht_set->rb_node);
0192     hlist_add_head(&eht_set->mcast_gc.gc_node, &eht_set->br->mcast_gc_list);
0193     queue_work(system_long_wq, &eht_set->br->mcast_gc_work);
0194 }
0195 
0196 void br_multicast_eht_clean_sets(struct net_bridge_port_group *pg)
0197 {
0198     struct net_bridge_group_eht_set *eht_set;
0199     struct rb_node *node;
0200 
0201     while ((node = rb_first(&pg->eht_set_tree))) {
0202         eht_set = rb_entry(node, struct net_bridge_group_eht_set,
0203                    rb_node);
0204         br_multicast_del_eht_set(eht_set);
0205     }
0206 }
0207 
0208 static void br_multicast_eht_set_entry_expired(struct timer_list *t)
0209 {
0210     struct net_bridge_group_eht_set_entry *set_h = from_timer(set_h, t, timer);
0211     struct net_bridge *br = set_h->br;
0212 
0213     spin_lock(&br->multicast_lock);
0214     if (RB_EMPTY_NODE(&set_h->rb_node) || timer_pending(&set_h->timer))
0215         goto out;
0216 
0217     br_multicast_del_eht_set_entry(set_h->eht_set->pg,
0218                        &set_h->eht_set->src_addr,
0219                        &set_h->h_addr);
0220 out:
0221     spin_unlock(&br->multicast_lock);
0222 }
0223 
0224 static void br_multicast_eht_set_expired(struct timer_list *t)
0225 {
0226     struct net_bridge_group_eht_set *eht_set = from_timer(eht_set, t,
0227                                   timer);
0228     struct net_bridge *br = eht_set->br;
0229 
0230     spin_lock(&br->multicast_lock);
0231     if (RB_EMPTY_NODE(&eht_set->rb_node) || timer_pending(&eht_set->timer))
0232         goto out;
0233 
0234     br_multicast_del_eht_set(eht_set);
0235 out:
0236     spin_unlock(&br->multicast_lock);
0237 }
0238 
0239 static struct net_bridge_group_eht_host *
0240 __eht_lookup_create_host(struct net_bridge_port_group *pg,
0241              union net_bridge_eht_addr *h_addr,
0242              unsigned char filter_mode)
0243 {
0244     struct rb_node **link = &pg->eht_host_tree.rb_node, *parent = NULL;
0245     struct net_bridge_group_eht_host *eht_host;
0246 
0247     while (*link) {
0248         struct net_bridge_group_eht_host *this;
0249         int result;
0250 
0251         this = rb_entry(*link, struct net_bridge_group_eht_host,
0252                 rb_node);
0253         result = memcmp(h_addr, &this->h_addr, sizeof(*h_addr));
0254         parent = *link;
0255         if (result < 0)
0256             link = &((*link)->rb_left);
0257         else if (result > 0)
0258             link = &((*link)->rb_right);
0259         else
0260             return this;
0261     }
0262 
0263     if (br_multicast_eht_hosts_over_limit(pg))
0264         return NULL;
0265 
0266     eht_host = kzalloc(sizeof(*eht_host), GFP_ATOMIC);
0267     if (!eht_host)
0268         return NULL;
0269 
0270     memcpy(&eht_host->h_addr, h_addr, sizeof(*h_addr));
0271     INIT_HLIST_HEAD(&eht_host->set_entries);
0272     eht_host->pg = pg;
0273     eht_host->filter_mode = filter_mode;
0274 
0275     rb_link_node(&eht_host->rb_node, parent, link);
0276     rb_insert_color(&eht_host->rb_node, &pg->eht_host_tree);
0277 
0278     br_multicast_eht_hosts_inc(pg);
0279 
0280     return eht_host;
0281 }
0282 
0283 static struct net_bridge_group_eht_set_entry *
0284 __eht_lookup_create_set_entry(struct net_bridge *br,
0285                   struct net_bridge_group_eht_set *eht_set,
0286                   struct net_bridge_group_eht_host *eht_host,
0287                   bool allow_zero_src)
0288 {
0289     struct rb_node **link = &eht_set->entry_tree.rb_node, *parent = NULL;
0290     struct net_bridge_group_eht_set_entry *set_h;
0291 
0292     while (*link) {
0293         struct net_bridge_group_eht_set_entry *this;
0294         int result;
0295 
0296         this = rb_entry(*link, struct net_bridge_group_eht_set_entry,
0297                 rb_node);
0298         result = memcmp(&eht_host->h_addr, &this->h_addr,
0299                 sizeof(union net_bridge_eht_addr));
0300         parent = *link;
0301         if (result < 0)
0302             link = &((*link)->rb_left);
0303         else if (result > 0)
0304             link = &((*link)->rb_right);
0305         else
0306             return this;
0307     }
0308 
0309     /* always allow auto-created zero entry */
0310     if (!allow_zero_src && eht_host->num_entries >= PG_SRC_ENT_LIMIT)
0311         return NULL;
0312 
0313     set_h = kzalloc(sizeof(*set_h), GFP_ATOMIC);
0314     if (!set_h)
0315         return NULL;
0316 
0317     memcpy(&set_h->h_addr, &eht_host->h_addr,
0318            sizeof(union net_bridge_eht_addr));
0319     set_h->mcast_gc.destroy = br_multicast_destroy_eht_set_entry;
0320     set_h->eht_set = eht_set;
0321     set_h->h_parent = eht_host;
0322     set_h->br = br;
0323     timer_setup(&set_h->timer, br_multicast_eht_set_entry_expired, 0);
0324 
0325     hlist_add_head(&set_h->host_list, &eht_host->set_entries);
0326     rb_link_node(&set_h->rb_node, parent, link);
0327     rb_insert_color(&set_h->rb_node, &eht_set->entry_tree);
0328     /* we must not count the auto-created zero entry otherwise we won't be
0329      * able to track the full list of PG_SRC_ENT_LIMIT entries
0330      */
0331     if (!allow_zero_src)
0332         eht_host->num_entries++;
0333 
0334     return set_h;
0335 }
0336 
0337 static struct net_bridge_group_eht_set *
0338 __eht_lookup_create_set(struct net_bridge_port_group *pg,
0339             union net_bridge_eht_addr *src_addr)
0340 {
0341     struct rb_node **link = &pg->eht_set_tree.rb_node, *parent = NULL;
0342     struct net_bridge_group_eht_set *eht_set;
0343 
0344     while (*link) {
0345         struct net_bridge_group_eht_set *this;
0346         int result;
0347 
0348         this = rb_entry(*link, struct net_bridge_group_eht_set,
0349                 rb_node);
0350         result = memcmp(src_addr, &this->src_addr, sizeof(*src_addr));
0351         parent = *link;
0352         if (result < 0)
0353             link = &((*link)->rb_left);
0354         else if (result > 0)
0355             link = &((*link)->rb_right);
0356         else
0357             return this;
0358     }
0359 
0360     eht_set = kzalloc(sizeof(*eht_set), GFP_ATOMIC);
0361     if (!eht_set)
0362         return NULL;
0363 
0364     memcpy(&eht_set->src_addr, src_addr, sizeof(*src_addr));
0365     eht_set->mcast_gc.destroy = br_multicast_destroy_eht_set;
0366     eht_set->pg = pg;
0367     eht_set->br = pg->key.port->br;
0368     eht_set->entry_tree = RB_ROOT;
0369     timer_setup(&eht_set->timer, br_multicast_eht_set_expired, 0);
0370 
0371     rb_link_node(&eht_set->rb_node, parent, link);
0372     rb_insert_color(&eht_set->rb_node, &pg->eht_set_tree);
0373 
0374     return eht_set;
0375 }
0376 
0377 static void br_multicast_ip_src_to_eht_addr(const struct br_ip *src,
0378                         union net_bridge_eht_addr *dest)
0379 {
0380     switch (src->proto) {
0381     case htons(ETH_P_IP):
0382         dest->ip4 = src->src.ip4;
0383         break;
0384 #if IS_ENABLED(CONFIG_IPV6)
0385     case htons(ETH_P_IPV6):
0386         memcpy(&dest->ip6, &src->src.ip6, sizeof(struct in6_addr));
0387         break;
0388 #endif
0389     }
0390 }
0391 
0392 static void br_eht_convert_host_filter_mode(const struct net_bridge_mcast *brmctx,
0393                         struct net_bridge_port_group *pg,
0394                         union net_bridge_eht_addr *h_addr,
0395                         int filter_mode)
0396 {
0397     struct net_bridge_group_eht_host *eht_host;
0398     union net_bridge_eht_addr zero_addr;
0399 
0400     eht_host = br_multicast_eht_host_lookup(pg, h_addr);
0401     if (eht_host)
0402         eht_host->filter_mode = filter_mode;
0403 
0404     memset(&zero_addr, 0, sizeof(zero_addr));
0405     switch (filter_mode) {
0406     case MCAST_INCLUDE:
0407         br_multicast_del_eht_set_entry(pg, &zero_addr, h_addr);
0408         break;
0409     case MCAST_EXCLUDE:
0410         br_multicast_create_eht_set_entry(brmctx, pg, &zero_addr,
0411                           h_addr, MCAST_EXCLUDE,
0412                           true);
0413         break;
0414     }
0415 }
0416 
0417 static void br_multicast_create_eht_set_entry(const struct net_bridge_mcast *brmctx,
0418                           struct net_bridge_port_group *pg,
0419                           union net_bridge_eht_addr *src_addr,
0420                           union net_bridge_eht_addr *h_addr,
0421                           int filter_mode,
0422                           bool allow_zero_src)
0423 {
0424     struct net_bridge_group_eht_set_entry *set_h;
0425     struct net_bridge_group_eht_host *eht_host;
0426     struct net_bridge *br = pg->key.port->br;
0427     struct net_bridge_group_eht_set *eht_set;
0428     union net_bridge_eht_addr zero_addr;
0429 
0430     memset(&zero_addr, 0, sizeof(zero_addr));
0431     if (!allow_zero_src && !memcmp(src_addr, &zero_addr, sizeof(zero_addr)))
0432         return;
0433 
0434     eht_set = __eht_lookup_create_set(pg, src_addr);
0435     if (!eht_set)
0436         return;
0437 
0438     eht_host = __eht_lookup_create_host(pg, h_addr, filter_mode);
0439     if (!eht_host)
0440         goto fail_host;
0441 
0442     set_h = __eht_lookup_create_set_entry(br, eht_set, eht_host,
0443                           allow_zero_src);
0444     if (!set_h)
0445         goto fail_set_entry;
0446 
0447     mod_timer(&set_h->timer, jiffies + br_multicast_gmi(brmctx));
0448     mod_timer(&eht_set->timer, jiffies + br_multicast_gmi(brmctx));
0449 
0450     return;
0451 
0452 fail_set_entry:
0453     if (hlist_empty(&eht_host->set_entries))
0454         __eht_destroy_host(eht_host);
0455 fail_host:
0456     if (RB_EMPTY_ROOT(&eht_set->entry_tree))
0457         br_multicast_del_eht_set(eht_set);
0458 }
0459 
0460 static bool br_multicast_del_eht_set_entry(struct net_bridge_port_group *pg,
0461                        union net_bridge_eht_addr *src_addr,
0462                        union net_bridge_eht_addr *h_addr)
0463 {
0464     struct net_bridge_group_eht_set_entry *set_h;
0465     struct net_bridge_group_eht_set *eht_set;
0466     bool set_deleted = false;
0467 
0468     eht_set = br_multicast_eht_set_lookup(pg, src_addr);
0469     if (!eht_set)
0470         goto out;
0471 
0472     set_h = br_multicast_eht_set_entry_lookup(eht_set, h_addr);
0473     if (!set_h)
0474         goto out;
0475 
0476     __eht_del_set_entry(set_h);
0477 
0478     if (RB_EMPTY_ROOT(&eht_set->entry_tree)) {
0479         br_multicast_del_eht_set(eht_set);
0480         set_deleted = true;
0481     }
0482 
0483 out:
0484     return set_deleted;
0485 }
0486 
0487 static void br_multicast_del_eht_host(struct net_bridge_port_group *pg,
0488                       union net_bridge_eht_addr *h_addr)
0489 {
0490     struct net_bridge_group_eht_set_entry *set_h;
0491     struct net_bridge_group_eht_host *eht_host;
0492     struct hlist_node *tmp;
0493 
0494     eht_host = br_multicast_eht_host_lookup(pg, h_addr);
0495     if (!eht_host)
0496         return;
0497 
0498     hlist_for_each_entry_safe(set_h, tmp, &eht_host->set_entries, host_list)
0499         br_multicast_del_eht_set_entry(set_h->eht_set->pg,
0500                            &set_h->eht_set->src_addr,
0501                            &set_h->h_addr);
0502 }
0503 
0504 /* create new set entries from reports */
0505 static void __eht_create_set_entries(const struct net_bridge_mcast *brmctx,
0506                      struct net_bridge_port_group *pg,
0507                      union net_bridge_eht_addr *h_addr,
0508                      void *srcs,
0509                      u32 nsrcs,
0510                      size_t addr_size,
0511                      int filter_mode)
0512 {
0513     union net_bridge_eht_addr eht_src_addr;
0514     u32 src_idx;
0515 
0516     memset(&eht_src_addr, 0, sizeof(eht_src_addr));
0517     for (src_idx = 0; src_idx < nsrcs; src_idx++) {
0518         memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
0519         br_multicast_create_eht_set_entry(brmctx, pg, &eht_src_addr,
0520                           h_addr, filter_mode,
0521                           false);
0522     }
0523 }
0524 
0525 /* delete existing set entries and their (S,G) entries if they were the last */
0526 static bool __eht_del_set_entries(struct net_bridge_port_group *pg,
0527                   union net_bridge_eht_addr *h_addr,
0528                   void *srcs,
0529                   u32 nsrcs,
0530                   size_t addr_size)
0531 {
0532     union net_bridge_eht_addr eht_src_addr;
0533     struct net_bridge_group_src *src_ent;
0534     bool changed = false;
0535     struct br_ip src_ip;
0536     u32 src_idx;
0537 
0538     memset(&eht_src_addr, 0, sizeof(eht_src_addr));
0539     memset(&src_ip, 0, sizeof(src_ip));
0540     src_ip.proto = pg->key.addr.proto;
0541     for (src_idx = 0; src_idx < nsrcs; src_idx++) {
0542         memcpy(&eht_src_addr, srcs + (src_idx * addr_size), addr_size);
0543         if (!br_multicast_del_eht_set_entry(pg, &eht_src_addr, h_addr))
0544             continue;
0545         memcpy(&src_ip, srcs + (src_idx * addr_size), addr_size);
0546         src_ent = br_multicast_find_group_src(pg, &src_ip);
0547         if (!src_ent)
0548             continue;
0549         br_multicast_del_group_src(src_ent, true);
0550         changed = true;
0551     }
0552 
0553     return changed;
0554 }
0555 
0556 static bool br_multicast_eht_allow(const struct net_bridge_mcast *brmctx,
0557                    struct net_bridge_port_group *pg,
0558                    union net_bridge_eht_addr *h_addr,
0559                    void *srcs,
0560                    u32 nsrcs,
0561                    size_t addr_size)
0562 {
0563     bool changed = false;
0564 
0565     switch (br_multicast_eht_host_filter_mode(pg, h_addr)) {
0566     case MCAST_INCLUDE:
0567         __eht_create_set_entries(brmctx, pg, h_addr, srcs, nsrcs,
0568                      addr_size, MCAST_INCLUDE);
0569         break;
0570     case MCAST_EXCLUDE:
0571         changed = __eht_del_set_entries(pg, h_addr, srcs, nsrcs,
0572                         addr_size);
0573         break;
0574     }
0575 
0576     return changed;
0577 }
0578 
0579 static bool br_multicast_eht_block(const struct net_bridge_mcast *brmctx,
0580                    struct net_bridge_port_group *pg,
0581                    union net_bridge_eht_addr *h_addr,
0582                    void *srcs,
0583                    u32 nsrcs,
0584                    size_t addr_size)
0585 {
0586     bool changed = false;
0587 
0588     switch (br_multicast_eht_host_filter_mode(pg, h_addr)) {
0589     case MCAST_INCLUDE:
0590         changed = __eht_del_set_entries(pg, h_addr, srcs, nsrcs,
0591                         addr_size);
0592         break;
0593     case MCAST_EXCLUDE:
0594         __eht_create_set_entries(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
0595                      MCAST_EXCLUDE);
0596         break;
0597     }
0598 
0599     return changed;
0600 }
0601 
0602 /* flush_entries is true when changing mode */
0603 static bool __eht_inc_exc(const struct net_bridge_mcast *brmctx,
0604               struct net_bridge_port_group *pg,
0605               union net_bridge_eht_addr *h_addr,
0606               void *srcs,
0607               u32 nsrcs,
0608               size_t addr_size,
0609               unsigned char filter_mode,
0610               bool to_report)
0611 {
0612     bool changed = false, flush_entries = to_report;
0613     union net_bridge_eht_addr eht_src_addr;
0614 
0615     if (br_multicast_eht_host_filter_mode(pg, h_addr) != filter_mode)
0616         flush_entries = true;
0617 
0618     memset(&eht_src_addr, 0, sizeof(eht_src_addr));
0619     /* if we're changing mode del host and its entries */
0620     if (flush_entries)
0621         br_multicast_del_eht_host(pg, h_addr);
0622     __eht_create_set_entries(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
0623                  filter_mode);
0624     /* we can be missing sets only if we've deleted some entries */
0625     if (flush_entries) {
0626         struct net_bridge_group_eht_set *eht_set;
0627         struct net_bridge_group_src *src_ent;
0628         struct hlist_node *tmp;
0629 
0630         hlist_for_each_entry_safe(src_ent, tmp, &pg->src_list, node) {
0631             br_multicast_ip_src_to_eht_addr(&src_ent->addr,
0632                             &eht_src_addr);
0633             if (!br_multicast_eht_set_lookup(pg, &eht_src_addr)) {
0634                 br_multicast_del_group_src(src_ent, true);
0635                 changed = true;
0636                 continue;
0637             }
0638             /* this is an optimization for TO_INCLUDE where we lower
0639              * the set's timeout to LMQT to catch timeout hosts:
0640              * - host A (timing out): set entries X, Y
0641              * - host B: set entry Z (new from current TO_INCLUDE)
0642              *           sends BLOCK Z after LMQT but host A's EHT
0643              *           entries still exist (unless lowered to LMQT
0644              *           so they can timeout with the S,Gs)
0645              * => we wait another LMQT, when we can just delete the
0646              *    group immediately
0647              */
0648             if (!(src_ent->flags & BR_SGRP_F_SEND) ||
0649                 filter_mode != MCAST_INCLUDE ||
0650                 !to_report)
0651                 continue;
0652             eht_set = br_multicast_eht_set_lookup(pg,
0653                                   &eht_src_addr);
0654             if (!eht_set)
0655                 continue;
0656             mod_timer(&eht_set->timer, jiffies + br_multicast_lmqt(brmctx));
0657         }
0658     }
0659 
0660     return changed;
0661 }
0662 
0663 static bool br_multicast_eht_inc(const struct net_bridge_mcast *brmctx,
0664                  struct net_bridge_port_group *pg,
0665                  union net_bridge_eht_addr *h_addr,
0666                  void *srcs,
0667                  u32 nsrcs,
0668                  size_t addr_size,
0669                  bool to_report)
0670 {
0671     bool changed;
0672 
0673     changed = __eht_inc_exc(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
0674                 MCAST_INCLUDE, to_report);
0675     br_eht_convert_host_filter_mode(brmctx, pg, h_addr, MCAST_INCLUDE);
0676 
0677     return changed;
0678 }
0679 
0680 static bool br_multicast_eht_exc(const struct net_bridge_mcast *brmctx,
0681                  struct net_bridge_port_group *pg,
0682                  union net_bridge_eht_addr *h_addr,
0683                  void *srcs,
0684                  u32 nsrcs,
0685                  size_t addr_size,
0686                  bool to_report)
0687 {
0688     bool changed;
0689 
0690     changed = __eht_inc_exc(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
0691                 MCAST_EXCLUDE, to_report);
0692     br_eht_convert_host_filter_mode(brmctx, pg, h_addr, MCAST_EXCLUDE);
0693 
0694     return changed;
0695 }
0696 
0697 static bool __eht_ip4_handle(const struct net_bridge_mcast *brmctx,
0698                  struct net_bridge_port_group *pg,
0699                  union net_bridge_eht_addr *h_addr,
0700                  void *srcs,
0701                  u32 nsrcs,
0702                  int grec_type)
0703 {
0704     bool changed = false, to_report = false;
0705 
0706     switch (grec_type) {
0707     case IGMPV3_ALLOW_NEW_SOURCES:
0708         br_multicast_eht_allow(brmctx, pg, h_addr, srcs, nsrcs,
0709                        sizeof(__be32));
0710         break;
0711     case IGMPV3_BLOCK_OLD_SOURCES:
0712         changed = br_multicast_eht_block(brmctx, pg, h_addr, srcs, nsrcs,
0713                          sizeof(__be32));
0714         break;
0715     case IGMPV3_CHANGE_TO_INCLUDE:
0716         to_report = true;
0717         fallthrough;
0718     case IGMPV3_MODE_IS_INCLUDE:
0719         changed = br_multicast_eht_inc(brmctx, pg, h_addr, srcs, nsrcs,
0720                            sizeof(__be32), to_report);
0721         break;
0722     case IGMPV3_CHANGE_TO_EXCLUDE:
0723         to_report = true;
0724         fallthrough;
0725     case IGMPV3_MODE_IS_EXCLUDE:
0726         changed = br_multicast_eht_exc(brmctx, pg, h_addr, srcs, nsrcs,
0727                            sizeof(__be32), to_report);
0728         break;
0729     }
0730 
0731     return changed;
0732 }
0733 
0734 #if IS_ENABLED(CONFIG_IPV6)
0735 static bool __eht_ip6_handle(const struct net_bridge_mcast *brmctx,
0736                  struct net_bridge_port_group *pg,
0737                  union net_bridge_eht_addr *h_addr,
0738                  void *srcs,
0739                  u32 nsrcs,
0740                  int grec_type)
0741 {
0742     bool changed = false, to_report = false;
0743 
0744     switch (grec_type) {
0745     case MLD2_ALLOW_NEW_SOURCES:
0746         br_multicast_eht_allow(brmctx, pg, h_addr, srcs, nsrcs,
0747                        sizeof(struct in6_addr));
0748         break;
0749     case MLD2_BLOCK_OLD_SOURCES:
0750         changed = br_multicast_eht_block(brmctx, pg, h_addr, srcs, nsrcs,
0751                          sizeof(struct in6_addr));
0752         break;
0753     case MLD2_CHANGE_TO_INCLUDE:
0754         to_report = true;
0755         fallthrough;
0756     case MLD2_MODE_IS_INCLUDE:
0757         changed = br_multicast_eht_inc(brmctx, pg, h_addr, srcs, nsrcs,
0758                            sizeof(struct in6_addr),
0759                            to_report);
0760         break;
0761     case MLD2_CHANGE_TO_EXCLUDE:
0762         to_report = true;
0763         fallthrough;
0764     case MLD2_MODE_IS_EXCLUDE:
0765         changed = br_multicast_eht_exc(brmctx, pg, h_addr, srcs, nsrcs,
0766                            sizeof(struct in6_addr),
0767                            to_report);
0768         break;
0769     }
0770 
0771     return changed;
0772 }
0773 #endif
0774 
0775 /* true means an entry was deleted */
0776 bool br_multicast_eht_handle(const struct net_bridge_mcast *brmctx,
0777                  struct net_bridge_port_group *pg,
0778                  void *h_addr,
0779                  void *srcs,
0780                  u32 nsrcs,
0781                  size_t addr_size,
0782                  int grec_type)
0783 {
0784     bool eht_enabled = !!(pg->key.port->flags & BR_MULTICAST_FAST_LEAVE);
0785     union net_bridge_eht_addr eht_host_addr;
0786     bool changed = false;
0787 
0788     if (!eht_enabled)
0789         goto out;
0790 
0791     memset(&eht_host_addr, 0, sizeof(eht_host_addr));
0792     memcpy(&eht_host_addr, h_addr, addr_size);
0793     if (addr_size == sizeof(__be32))
0794         changed = __eht_ip4_handle(brmctx, pg, &eht_host_addr, srcs,
0795                        nsrcs, grec_type);
0796 #if IS_ENABLED(CONFIG_IPV6)
0797     else
0798         changed = __eht_ip6_handle(brmctx, pg, &eht_host_addr, srcs,
0799                        nsrcs, grec_type);
0800 #endif
0801 
0802 out:
0803     return changed;
0804 }
0805 
0806 int br_multicast_eht_set_hosts_limit(struct net_bridge_port *p,
0807                      u32 eht_hosts_limit)
0808 {
0809     struct net_bridge *br = p->br;
0810 
0811     if (!eht_hosts_limit)
0812         return -EINVAL;
0813 
0814     spin_lock_bh(&br->multicast_lock);
0815     p->multicast_eht_hosts_limit = eht_hosts_limit;
0816     spin_unlock_bh(&br->multicast_lock);
0817 
0818     return 0;
0819 }