.automatic_shrinking = true,
 };
 
-static void br_multicast_start_querier(struct net_bridge *br,
+static void br_multicast_start_querier(struct net_bridge_mcast *brmctx,
                                       struct bridge_mcast_own_query *query);
-static void br_ip4_multicast_add_router(struct net_bridge *br,
-                                       struct net_bridge_port *port);
-static void br_ip4_multicast_leave_group(struct net_bridge *br,
-                                        struct net_bridge_port *port,
+static void br_ip4_multicast_add_router(struct net_bridge_mcast *brmctx,
+                                       struct net_bridge_mcast_port *pmctx);
+static void br_ip4_multicast_leave_group(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx,
                                         __be32 group,
                                         __u16 vid,
                                         const unsigned char *src);
 static void br_multicast_port_group_rexmit(struct timer_list *t);
 
 static void
-br_multicast_rport_del_notify(struct net_bridge_port *p, bool deleted);
-static void br_ip6_multicast_add_router(struct net_bridge *br,
-                                       struct net_bridge_port *port);
+br_multicast_rport_del_notify(struct net_bridge_mcast_port *pmctx, bool deleted);
+static void br_ip6_multicast_add_router(struct net_bridge_mcast *brmctx,
+                                       struct net_bridge_mcast_port *pmctx);
 #if IS_ENABLED(CONFIG_IPV6)
-static void br_ip6_multicast_leave_group(struct net_bridge *br,
-                                        struct net_bridge_port *port,
+static void br_ip6_multicast_leave_group(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx,
                                         const struct in6_addr *group,
                                         __u16 vid, const unsigned char *src);
 #endif
 static struct net_bridge_port_group *
-__br_multicast_add_group(struct net_bridge *br,
-                        struct net_bridge_port *port,
+__br_multicast_add_group(struct net_bridge_mcast *brmctx,
+                        struct net_bridge_mcast_port *pmctx,
                         struct br_ip *group,
                         const unsigned char *src,
                         u8 filter_mode,
 }
 #endif
 
-struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
+struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge_mcast *brmctx,
                                        struct sk_buff *skb, u16 vid)
 {
+       struct net_bridge *br = brmctx->br;
        struct br_ip ip;
 
        if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
        switch (skb->protocol) {
        case htons(ETH_P_IP):
                ip.dst.ip4 = ip_hdr(skb)->daddr;
-               if (br->multicast_ctx.multicast_igmp_version == 3) {
+               if (brmctx->multicast_igmp_version == 3) {
                        struct net_bridge_mdb_entry *mdb;
 
                        ip.src.ip4 = ip_hdr(skb)->saddr;
 #if IS_ENABLED(CONFIG_IPV6)
        case htons(ETH_P_IPV6):
                ip.dst.ip6 = ipv6_hdr(skb)->daddr;
-               if (br->multicast_ctx.multicast_mld_version == 2) {
+               if (brmctx->multicast_mld_version == 2) {
                        struct net_bridge_mdb_entry *mdb;
 
                        ip.src.ip6 = ipv6_hdr(skb)->saddr;
        return ether_addr_equal(src, p->eth_addr);
 }
 
-static void __fwd_add_star_excl(struct net_bridge_port_group *pg,
+static void __fwd_add_star_excl(struct net_bridge_mcast_port *pmctx,
+                               struct net_bridge_port_group *pg,
                                struct br_ip *sg_ip)
 {
        struct net_bridge_port_group_sg_key sg_key;
-       struct net_bridge *br = pg->key.port->br;
        struct net_bridge_port_group *src_pg;
+       struct net_bridge_mcast *brmctx;
 
        memset(&sg_key, 0, sizeof(sg_key));
+       brmctx = &pg->key.port->br->multicast_ctx;
        sg_key.port = pg->key.port;
        sg_key.addr = *sg_ip;
-       if (br_sg_port_find(br, &sg_key))
+       if (br_sg_port_find(brmctx->br, &sg_key))
                return;
 
-       src_pg = __br_multicast_add_group(br, pg->key.port, sg_ip, pg->eth_addr,
+       src_pg = __br_multicast_add_group(brmctx, pmctx,
+                                         sg_ip, pg->eth_addr,
                                          MCAST_INCLUDE, false, false);
        if (IS_ERR_OR_NULL(src_pg) ||
            src_pg->rt_protocol != RTPROT_KERNEL)
 {
        struct net_bridge *br = pg->key.port->br;
        struct net_bridge_port_group *pg_lst;
+       struct net_bridge_mcast_port *pmctx;
        struct net_bridge_mdb_entry *mp;
        struct br_ip sg_ip;
 
        mp = br_mdb_ip_get(br, &pg->key.addr);
        if (!mp)
                return;
+       pmctx = &pg->key.port->multicast_ctx;
 
        memset(&sg_ip, 0, sizeof(sg_ip));
        sg_ip = pg->key.addr;
                                __fwd_del_star_excl(pg, &sg_ip);
                                break;
                        case MCAST_EXCLUDE:
-                               __fwd_add_star_excl(pg, &sg_ip);
+                               __fwd_add_star_excl(pmctx, pg, &sg_ip);
                                break;
                        }
                }
 {
        struct net_bridge_port_group_sg_key sg_key;
        struct net_bridge *br = star_mp->br;
+       struct net_bridge_mcast_port *pmctx;
        struct net_bridge_port_group *pg;
+       struct net_bridge_mcast *brmctx;
 
        if (WARN_ON(br_multicast_is_star_g(&sg->key.addr)))
                return;
        br_multicast_sg_host_state(star_mp, sg);
        memset(&sg_key, 0, sizeof(sg_key));
        sg_key.addr = sg->key.addr;
+       brmctx = &br->multicast_ctx;
        /* we need to add all exclude ports to the S,G */
        for (pg = mlock_dereference(star_mp->ports, br);
             pg;
                if (br_sg_port_find(br, &sg_key))
                        continue;
 
-               src_pg = __br_multicast_add_group(br, pg->key.port,
+               pmctx = &pg->key.port->multicast_ctx;
+               src_pg = __br_multicast_add_group(brmctx, pmctx,
                                                  &sg->key.addr,
                                                  sg->eth_addr,
                                                  MCAST_INCLUDE, false, false);
 static void br_multicast_fwd_src_add(struct net_bridge_group_src *src)
 {
        struct net_bridge_mdb_entry *star_mp;
+       struct net_bridge_mcast_port *pmctx;
        struct net_bridge_port_group *sg;
+       struct net_bridge_mcast *brmctx;
        struct br_ip sg_ip;
 
        if (src->flags & BR_SGRP_F_INSTALLED)
                return;
 
        memset(&sg_ip, 0, sizeof(sg_ip));
+       pmctx = &src->pg->key.port->multicast_ctx;
+       brmctx = &src->br->multicast_ctx;
        sg_ip = src->pg->key.addr;
        sg_ip.src = src->addr.src;
-       sg = __br_multicast_add_group(src->br, src->pg->key.port, &sg_ip,
+
+       sg = __br_multicast_add_group(brmctx, pmctx, &sg_ip,
                                      src->pg->eth_addr, MCAST_INCLUDE, false,
                                      !timer_pending(&src->timer));
        if (IS_ERR_OR_NULL(sg))
        }
 }
 
-static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
+static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brmctx,
                                                    struct net_bridge_port_group *pg,
                                                    __be32 ip_dst, __be32 group,
                                                    bool with_srcs, bool over_lmqt,
                                                    u8 sflag, u8 *igmp_type,
                                                    bool *need_rexmit)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        struct net_bridge_port *p = pg ? pg->key.port : NULL;
        struct net_bridge_group_src *ent;
        size_t pkt_size, igmp_hdr_size;
 
        pkt_size = sizeof(*eth) + sizeof(*iph) + 4 + igmp_hdr_size;
        if ((p && pkt_size > p->dev->mtu) ||
-           pkt_size > br->dev->mtu)
+           pkt_size > brmctx->br->dev->mtu)
                return NULL;
 
-       skb = netdev_alloc_skb_ip_align(br->dev, pkt_size);
+       skb = netdev_alloc_skb_ip_align(brmctx->br->dev, pkt_size);
        if (!skb)
                goto out;
 
        skb_reset_mac_header(skb);
        eth = eth_hdr(skb);
 
-       ether_addr_copy(eth->h_source, br->dev->dev_addr);
+       ether_addr_copy(eth->h_source, brmctx->br->dev->dev_addr);
        ip_eth_mc_map(ip_dst, eth->h_dest);
        eth->h_proto = htons(ETH_P_IP);
        skb_put(skb, sizeof(*eth));
        iph->frag_off = htons(IP_DF);
        iph->ttl = 1;
        iph->protocol = IPPROTO_IGMP;
-       iph->saddr = br_opt_get(br, BROPT_MULTICAST_QUERY_USE_IFADDR) ?
-                    inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0;
+       iph->saddr = br_opt_get(brmctx->br, BROPT_MULTICAST_QUERY_USE_IFADDR) ?
+                    inet_select_addr(brmctx->br->dev, 0, RT_SCOPE_LINK) : 0;
        iph->daddr = ip_dst;
        ((u8 *)&iph[1])[0] = IPOPT_RA;
        ((u8 *)&iph[1])[1] = 4;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
+static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brmctx,
                                                    struct net_bridge_port_group *pg,
                                                    const struct in6_addr *ip6_dst,
                                                    const struct in6_addr *group,
                                                    u8 sflag, u8 *igmp_type,
                                                    bool *need_rexmit)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        struct net_bridge_port *p = pg ? pg->key.port : NULL;
        struct net_bridge_group_src *ent;
        size_t pkt_size, mld_hdr_size;
 
        pkt_size = sizeof(*eth) + sizeof(*ip6h) + 8 + mld_hdr_size;
        if ((p && pkt_size > p->dev->mtu) ||
-           pkt_size > br->dev->mtu)
+           pkt_size > brmctx->br->dev->mtu)
                return NULL;
 
-       skb = netdev_alloc_skb_ip_align(br->dev, pkt_size);
+       skb = netdev_alloc_skb_ip_align(brmctx->br->dev, pkt_size);
        if (!skb)
                goto out;
 
        skb_reset_mac_header(skb);
        eth = eth_hdr(skb);
 
-       ether_addr_copy(eth->h_source, br->dev->dev_addr);
+       ether_addr_copy(eth->h_source, brmctx->br->dev->dev_addr);
        eth->h_proto = htons(ETH_P_IPV6);
        skb_put(skb, sizeof(*eth));
 
        ip6h->nexthdr = IPPROTO_HOPOPTS;
        ip6h->hop_limit = 1;
        ip6h->daddr = *ip6_dst;
-       if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
-                              &ip6h->saddr)) {
+       if (ipv6_dev_get_saddr(dev_net(brmctx->br->dev), brmctx->br->dev,
+                              &ip6h->daddr, 0, &ip6h->saddr)) {
                kfree_skb(skb);
-               br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, false);
+               br_opt_toggle(brmctx->br, BROPT_HAS_IPV6_ADDR, false);
                return NULL;
        }
 
-       br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);
+       br_opt_toggle(brmctx->br, BROPT_HAS_IPV6_ADDR, true);
        ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
 
        hopopt = (u8 *)(ip6h + 1);
 }
 #endif
 
-static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
+static struct sk_buff *br_multicast_alloc_query(struct net_bridge_mcast *brmctx,
                                                struct net_bridge_port_group *pg,
                                                struct br_ip *ip_dst,
                                                struct br_ip *group,
        switch (group->proto) {
        case htons(ETH_P_IP):
                ip4_dst = ip_dst ? ip_dst->dst.ip4 : htonl(INADDR_ALLHOSTS_GROUP);
-               return br_ip4_multicast_alloc_query(br, pg,
+               return br_ip4_multicast_alloc_query(brmctx, pg,
                                                    ip4_dst, group->dst.ip4,
                                                    with_srcs, over_lmqt,
                                                    sflag, igmp_type,
                        ipv6_addr_set(&ip6_dst, htonl(0xff020000), 0, 0,
                                      htonl(1));
 
-               return br_ip6_multicast_alloc_query(br, pg,
+               return br_ip6_multicast_alloc_query(brmctx, pg,
                                                    &ip6_dst, &group->dst.ip6,
                                                    with_srcs, over_lmqt,
                                                    sflag, igmp_type,
 }
 
 static struct net_bridge_port_group *
-__br_multicast_add_group(struct net_bridge *br,
-                        struct net_bridge_port *port,
+__br_multicast_add_group(struct net_bridge_mcast *brmctx,
+                        struct net_bridge_mcast_port *pmctx,
                         struct br_ip *group,
                         const unsigned char *src,
                         u8 filter_mode,
        struct net_bridge_mdb_entry *mp;
        unsigned long now = jiffies;
 
-       if (!netif_running(br->dev) ||
-           (port && port->state == BR_STATE_DISABLED))
+       if (!netif_running(brmctx->br->dev) ||
+           (pmctx && pmctx->port->state == BR_STATE_DISABLED))
                goto out;
 
-       mp = br_multicast_new_group(br, group);
+       mp = br_multicast_new_group(brmctx->br, group);
        if (IS_ERR(mp))
                return ERR_CAST(mp);
 
-       if (!port) {
+       if (!pmctx) {
                br_multicast_host_join(mp, true);
                goto out;
        }
 
        for (pp = &mp->ports;
-            (p = mlock_dereference(*pp, br)) != NULL;
+            (p = mlock_dereference(*pp, brmctx->br)) != NULL;
             pp = &p->next) {
-               if (br_port_group_equal(p, port, src))
+               if (br_port_group_equal(p, pmctx->port, src))
                        goto found;
-               if ((unsigned long)p->key.port < (unsigned long)port)
+               if ((unsigned long)p->key.port < (unsigned long)pmctx->port)
                        break;
        }
 
-       p = br_multicast_new_port_group(port, group, *pp, 0, src,
+       p = br_multicast_new_port_group(pmctx->port, group, *pp, 0, src,
                                        filter_mode, RTPROT_KERNEL);
        if (unlikely(!p)) {
                p = ERR_PTR(-ENOMEM);
        rcu_assign_pointer(*pp, p);
        if (blocked)
                p->flags |= MDB_PG_FLAGS_BLOCKED;
-       br_mdb_notify(br->dev, mp, p, RTM_NEWMDB);
+       br_mdb_notify(brmctx->br->dev, mp, p, RTM_NEWMDB);
 
 found:
        if (igmpv2_mldv1)
                mod_timer(&p->timer,
-                         now + br->multicast_ctx.multicast_membership_interval);
+                         now + brmctx->multicast_membership_interval);
 
 out:
        return p;
 }
 
-static int br_multicast_add_group(struct net_bridge *br,
-                                 struct net_bridge_port *port,
+static int br_multicast_add_group(struct net_bridge_mcast *brmctx,
+                                 struct net_bridge_mcast_port *pmctx,
                                  struct br_ip *group,
                                  const unsigned char *src,
                                  u8 filter_mode,
        struct net_bridge_port_group *pg;
        int err;
 
-       spin_lock(&br->multicast_lock);
-       pg = __br_multicast_add_group(br, port, group, src, filter_mode,
+       spin_lock(&brmctx->br->multicast_lock);
+       pg = __br_multicast_add_group(brmctx, pmctx, group, src, filter_mode,
                                      igmpv2_mldv1, false);
        /* NULL is considered valid for host joined groups */
        err = PTR_ERR_OR_ZERO(pg);
-       spin_unlock(&br->multicast_lock);
+       spin_unlock(&brmctx->br->multicast_lock);
 
        return err;
 }
 
-static int br_ip4_multicast_add_group(struct net_bridge *br,
-                                     struct net_bridge_port *port,
+static int br_ip4_multicast_add_group(struct net_bridge_mcast *brmctx,
+                                     struct net_bridge_mcast_port *pmctx,
                                      __be32 group,
                                      __u16 vid,
                                      const unsigned char *src,
        br_group.vid = vid;
        filter_mode = igmpv2 ? MCAST_EXCLUDE : MCAST_INCLUDE;
 
-       return br_multicast_add_group(br, port, &br_group, src, filter_mode,
-                                     igmpv2);
+       return br_multicast_add_group(brmctx, pmctx, &br_group, src,
+                                     filter_mode, igmpv2);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static int br_ip6_multicast_add_group(struct net_bridge *br,
-                                     struct net_bridge_port *port,
+static int br_ip6_multicast_add_group(struct net_bridge_mcast *brmctx,
+                                     struct net_bridge_mcast_port *pmctx,
                                      const struct in6_addr *group,
                                      __u16 vid,
                                      const unsigned char *src,
        br_group.vid = vid;
        filter_mode = mldv1 ? MCAST_EXCLUDE : MCAST_INCLUDE;
 
-       return br_multicast_add_group(br, port, &br_group, src, filter_mode,
-                                     mldv1);
+       return br_multicast_add_group(brmctx, pmctx, &br_group, src,
+                                     filter_mode, mldv1);
 }
 #endif
 
        return true;
 }
 
-static bool br_ip4_multicast_rport_del(struct net_bridge_port *p)
+static bool br_ip4_multicast_rport_del(struct net_bridge_mcast_port *pmctx)
 {
-       return br_multicast_rport_del(&p->multicast_ctx.ip4_rlist);
+       return br_multicast_rport_del(&pmctx->ip4_rlist);
 }
 
-static bool br_ip6_multicast_rport_del(struct net_bridge_port *p)
+static bool br_ip6_multicast_rport_del(struct net_bridge_mcast_port *pmctx)
 {
 #if IS_ENABLED(CONFIG_IPV6)
-       return br_multicast_rport_del(&p->multicast_ctx.ip6_rlist);
+       return br_multicast_rport_del(&pmctx->ip6_rlist);
 #else
        return false;
 #endif
                goto out;
 
        del = br_multicast_rport_del(rlist);
-       br_multicast_rport_del_notify(pmctx->port, del);
+       br_multicast_rport_del_notify(pmctx, del);
 out:
        spin_unlock(&br->multicast_lock);
 }
            !br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
                goto out;
 
-       br_multicast_start_querier(brmctx->br, query);
+       br_multicast_start_querier(brmctx, query);
 
 out:
        spin_unlock(&brmctx->br->multicast_lock);
 }
 #endif
 
-static void br_multicast_select_own_querier(struct net_bridge *br,
+static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx,
                                            struct br_ip *ip,
                                            struct sk_buff *skb)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
-
        if (ip->proto == htons(ETH_P_IP))
                brmctx->ip4_querier.addr.src.ip4 = ip_hdr(skb)->saddr;
 #if IS_ENABLED(CONFIG_IPV6)
 #endif
 }
 
-static void __br_multicast_send_query(struct net_bridge *br,
-                                     struct net_bridge_port *port,
+static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
+                                     struct net_bridge_mcast_port *pmctx,
                                      struct net_bridge_port_group *pg,
                                      struct br_ip *ip_dst,
                                      struct br_ip *group,
        u8 igmp_type;
 
 again_under_lmqt:
-       skb = br_multicast_alloc_query(br, pg, ip_dst, group, with_srcs,
+       skb = br_multicast_alloc_query(brmctx, pg, ip_dst, group, with_srcs,
                                       over_lmqt, sflag, &igmp_type,
                                       need_rexmit);
        if (!skb)
                return;
 
-       if (port) {
-               skb->dev = port->dev;
-               br_multicast_count(br, port, skb, igmp_type,
+       if (pmctx) {
+               skb->dev = pmctx->port->dev;
+               br_multicast_count(brmctx->br, pmctx->port, skb, igmp_type,
                                   BR_MCAST_DIR_TX);
                NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
-                       dev_net(port->dev), NULL, skb, NULL, skb->dev,
+                       dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev,
                        br_dev_queue_push_xmit);
 
                if (over_lmqt && with_srcs && sflag) {
                        goto again_under_lmqt;
                }
        } else {
-               br_multicast_select_own_querier(br, group, skb);
-               br_multicast_count(br, port, skb, igmp_type,
+               br_multicast_select_own_querier(brmctx, group, skb);
+               br_multicast_count(brmctx->br, NULL, skb, igmp_type,
                                   BR_MCAST_DIR_RX);
                netif_rx(skb);
        }
 }
 
-static void br_multicast_send_query(struct net_bridge *br,
-                                   struct net_bridge_port *port,
+static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
+                                   struct net_bridge_mcast_port *pmctx,
                                    struct bridge_mcast_own_query *own_query)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        struct bridge_mcast_other_query *other_query = NULL;
        struct br_ip br_group;
        unsigned long time;
 
-       if (!netif_running(br->dev) ||
-           !br_opt_get(br, BROPT_MULTICAST_ENABLED) ||
-           !br_opt_get(br, BROPT_MULTICAST_QUERIER))
+       if (!netif_running(brmctx->br->dev) ||
+           !br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED) ||
+           !br_opt_get(brmctx->br, BROPT_MULTICAST_QUERIER))
                return;
 
        memset(&br_group.dst, 0, sizeof(br_group.dst));
 
-       if (port ? (own_query == &port->multicast_ctx.ip4_own_query) :
-                  (own_query == &brmctx->ip4_own_query)) {
+       if (pmctx ? (own_query == &pmctx->ip4_own_query) :
+                   (own_query == &brmctx->ip4_own_query)) {
                other_query = &brmctx->ip4_other_query;
                br_group.proto = htons(ETH_P_IP);
 #if IS_ENABLED(CONFIG_IPV6)
        if (!other_query || timer_pending(&other_query->timer))
                return;
 
-       __br_multicast_send_query(br, port, NULL, NULL, &br_group, false, 0,
-                                 NULL);
+       __br_multicast_send_query(brmctx, pmctx, NULL, NULL, &br_group, false,
+                                 0, NULL);
 
        time = jiffies;
        time += own_query->startup_sent < brmctx->multicast_startup_query_count ?
        if (query->startup_sent < br->multicast_ctx.multicast_startup_query_count)
                query->startup_sent++;
 
-       br_multicast_send_query(pmctx->port->br, pmctx->port, query);
+       br_multicast_send_query(&br->multicast_ctx, pmctx, query);
 
 out:
        spin_unlock(&br->multicast_lock);
        struct net_bridge_port_group *pg = from_timer(pg, t, rexmit_timer);
        struct bridge_mcast_other_query *other_query = NULL;
        struct net_bridge *br = pg->key.port->br;
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
+       struct net_bridge_mcast_port *pmctx;
+       struct net_bridge_mcast *brmctx;
        bool need_rexmit = false;
 
        spin_lock(&br->multicast_lock);
            !br_opt_get(br, BROPT_MULTICAST_QUERIER))
                goto out;
 
+       brmctx = &br->multicast_ctx;
+       pmctx = &pg->key.port->multicast_ctx;
        if (pg->key.addr.proto == htons(ETH_P_IP))
                other_query = &brmctx->ip4_other_query;
 #if IS_ENABLED(CONFIG_IPV6)
 
        if (pg->grp_query_rexmit_cnt) {
                pg->grp_query_rexmit_cnt--;
-               __br_multicast_send_query(br, pg->key.port, pg, &pg->key.addr,
+               __br_multicast_send_query(brmctx, pmctx, pg, &pg->key.addr,
                                          &pg->key.addr, false, 1, NULL);
        }
-       __br_multicast_send_query(br, pg->key.port, pg, &pg->key.addr,
+       __br_multicast_send_query(brmctx, pmctx, pg, &pg->key.addr,
                                  &pg->key.addr, true, 0, &need_rexmit);
 
        if (pg->grp_query_rexmit_cnt || need_rexmit)
                mod_timer(&query->timer, jiffies);
 }
 
-static void __br_multicast_enable_port(struct net_bridge_port *port)
+static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
 {
-       struct net_bridge *br = port->br;
+       struct net_bridge *br = pmctx->port->br;
+       struct net_bridge_mcast *brmctx = &pmctx->port->br->multicast_ctx;
 
        if (!br_opt_get(br, BROPT_MULTICAST_ENABLED) || !netif_running(br->dev))
                return;
 
-       br_multicast_enable(&port->multicast_ctx.ip4_own_query);
+       br_multicast_enable(&pmctx->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
-       br_multicast_enable(&port->multicast_ctx.ip6_own_query);
+       br_multicast_enable(&pmctx->ip6_own_query);
 #endif
-       if (port->multicast_ctx.multicast_router == MDB_RTR_TYPE_PERM) {
-               br_ip4_multicast_add_router(br, port);
-               br_ip6_multicast_add_router(br, port);
+       if (pmctx->multicast_router == MDB_RTR_TYPE_PERM) {
+               br_ip4_multicast_add_router(brmctx, pmctx);
+               br_ip6_multicast_add_router(brmctx, pmctx);
        }
 }
 
        struct net_bridge *br = port->br;
 
        spin_lock(&br->multicast_lock);
-       __br_multicast_enable_port(port);
+       __br_multicast_enable_port_ctx(&port->multicast_ctx);
        spin_unlock(&br->multicast_lock);
 }
 
 void br_multicast_disable_port(struct net_bridge_port *port)
 {
+       struct net_bridge_mcast_port *pmctx = &port->multicast_ctx;
        struct net_bridge *br = port->br;
        struct net_bridge_port_group *pg;
        struct hlist_node *n;
                if (!(pg->flags & MDB_PG_FLAGS_PERMANENT))
                        br_multicast_find_del_pg(br, pg);
 
-       del |= br_ip4_multicast_rport_del(port);
-       del_timer(&port->multicast_ctx.ip4_mc_router_timer);
-       del_timer(&port->multicast_ctx.ip4_own_query.timer);
-       del |= br_ip6_multicast_rport_del(port);
+       del |= br_ip4_multicast_rport_del(pmctx);
+       del_timer(&pmctx->ip4_mc_router_timer);
+       del_timer(&pmctx->ip4_own_query.timer);
+       del |= br_ip6_multicast_rport_del(pmctx);
 #if IS_ENABLED(CONFIG_IPV6)
-       del_timer(&port->multicast_ctx.ip6_mc_router_timer);
-       del_timer(&port->multicast_ctx.ip6_own_query.timer);
+       del_timer(&pmctx->ip6_mc_router_timer);
+       del_timer(&pmctx->ip6_own_query.timer);
 #endif
-       br_multicast_rport_del_notify(port, del);
+       br_multicast_rport_del_notify(pmctx, del);
        spin_unlock(&br->multicast_lock);
 }
 
        br_multicast_fwd_src_handle(src);
 }
 
-static void __grp_src_query_marked_and_rexmit(struct net_bridge_port_group *pg)
+static void __grp_src_query_marked_and_rexmit(struct net_bridge_mcast *brmctx,
+                                             struct net_bridge_mcast_port *pmctx,
+                                             struct net_bridge_port_group *pg)
 {
        struct bridge_mcast_other_query *other_query = NULL;
-       struct net_bridge *br = pg->key.port->br;
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        u32 lmqc = brmctx->multicast_last_member_count;
        unsigned long lmqt, lmi, now = jiffies;
        struct net_bridge_group_src *ent;
 
-       if (!netif_running(br->dev) ||
-           !br_opt_get(br, BROPT_MULTICAST_ENABLED))
+       if (!netif_running(brmctx->br->dev) ||
+           !br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
                return;
 
        if (pg->key.addr.proto == htons(ETH_P_IP))
                other_query = &brmctx->ip6_other_query;
 #endif
 
-       lmqt = now + br_multicast_lmqt(br);
+       lmqt = now + br_multicast_lmqt(brmctx);
        hlist_for_each_entry(ent, &pg->src_list, node) {
                if (ent->flags & BR_SGRP_F_SEND) {
                        ent->flags &= ~BR_SGRP_F_SEND;
                        if (ent->timer.expires > lmqt) {
-                               if (br_opt_get(br, BROPT_MULTICAST_QUERIER) &&
+                               if (br_opt_get(brmctx->br,
+                                              BROPT_MULTICAST_QUERIER) &&
                                    other_query &&
                                    !timer_pending(&other_query->timer))
                                        ent->src_query_rexmit_cnt = lmqc;
                }
        }
 
-       if (!br_opt_get(br, BROPT_MULTICAST_QUERIER) ||
+       if (!br_opt_get(brmctx->br, BROPT_MULTICAST_QUERIER) ||
            !other_query || timer_pending(&other_query->timer))
                return;
 
-       __br_multicast_send_query(br, pg->key.port, pg, &pg->key.addr,
+       __br_multicast_send_query(brmctx, pmctx, pg, &pg->key.addr,
                                  &pg->key.addr, true, 1, NULL);
 
        lmi = now + brmctx->multicast_last_member_interval;
                mod_timer(&pg->rexmit_timer, lmi);
 }
 
-static void __grp_send_query_and_rexmit(struct net_bridge_port_group *pg)
+static void __grp_send_query_and_rexmit(struct net_bridge_mcast *brmctx,
+                                       struct net_bridge_mcast_port *pmctx,
+                                       struct net_bridge_port_group *pg)
 {
        struct bridge_mcast_other_query *other_query = NULL;
-       struct net_bridge *br = pg->key.port->br;
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        unsigned long now = jiffies, lmi;
 
-       if (!netif_running(br->dev) ||
-           !br_opt_get(br, BROPT_MULTICAST_ENABLED))
+       if (!netif_running(brmctx->br->dev) ||
+           !br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
                return;
 
        if (pg->key.addr.proto == htons(ETH_P_IP))
                other_query = &brmctx->ip6_other_query;
 #endif
 
-       if (br_opt_get(br, BROPT_MULTICAST_QUERIER) &&
+       if (br_opt_get(brmctx->br, BROPT_MULTICAST_QUERIER) &&
            other_query && !timer_pending(&other_query->timer)) {
                lmi = now + brmctx->multicast_last_member_interval;
                pg->grp_query_rexmit_cnt = brmctx->multicast_last_member_count - 1;
-               __br_multicast_send_query(br, pg->key.port, pg, &pg->key.addr,
+               __br_multicast_send_query(brmctx, pmctx, pg, &pg->key.addr,
                                          &pg->key.addr, false, 0, NULL);
                if (!timer_pending(&pg->rexmit_timer) ||
                    time_after(pg->rexmit_timer.expires, lmi))
 
        if (pg->filter_mode == MCAST_EXCLUDE &&
            (!timer_pending(&pg->timer) ||
-            time_after(pg->timer.expires, now + br_multicast_lmqt(br))))
-               mod_timer(&pg->timer, now + br_multicast_lmqt(br));
+            time_after(pg->timer.expires, now + br_multicast_lmqt(brmctx))))
+               mod_timer(&pg->timer, now + br_multicast_lmqt(brmctx));
 }
 
 /* State          Msg type      New state                Actions
  * INCLUDE (A)    ALLOW (B)     INCLUDE (A+B)            (B)=GMI
  * EXCLUDE (X,Y)  ALLOW (A)     EXCLUDE (X+A,Y-A)        (A)=GMI
  */
-static bool br_multicast_isinc_allow(struct net_bridge_port_group *pg, void *h_addr,
+static bool br_multicast_isinc_allow(const struct net_bridge_mcast *brmctx,
+                                    struct net_bridge_port_group *pg, void *h_addr,
                                     void *srcs, u32 nsrcs, size_t addr_size,
                                     int grec_type)
 {
-       struct net_bridge *br = pg->key.port->br;
        struct net_bridge_group_src *ent;
        unsigned long now = jiffies;
        bool changed = false;
                }
 
                if (ent)
-                       __grp_src_mod_timer(ent, now + br_multicast_gmi(br));
+                       __grp_src_mod_timer(ent, now + br_multicast_gmi(brmctx));
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        return changed;
  *                                                       Delete (A-B)
  *                                                       Group Timer=GMI
  */
-static void __grp_src_isexc_incl(struct net_bridge_port_group *pg, void *h_addr,
+static void __grp_src_isexc_incl(const struct net_bridge_mcast *brmctx,
+                                struct net_bridge_port_group *pg, void *h_addr,
                                 void *srcs, u32 nsrcs, size_t addr_size,
                                 int grec_type)
 {
                        br_multicast_fwd_src_handle(ent);
        }
 
-       br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type);
+       br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                               grec_type);
 
        __grp_src_delete_marked(pg);
 }
  *                                                       Delete (Y-A)
  *                                                       Group Timer=GMI
  */
-static bool __grp_src_isexc_excl(struct net_bridge_port_group *pg, void *h_addr,
+static bool __grp_src_isexc_excl(const struct net_bridge_mcast *brmctx,
+                                struct net_bridge_port_group *pg, void *h_addr,
                                 void *srcs, u32 nsrcs, size_t addr_size,
                                 int grec_type)
 {
-       struct net_bridge *br = pg->key.port->br;
        struct net_bridge_group_src *ent;
        unsigned long now = jiffies;
        bool changed = false;
                        ent = br_multicast_new_group_src(pg, &src_ip);
                        if (ent) {
                                __grp_src_mod_timer(ent,
-                                                   now + br_multicast_gmi(br));
+                                                   now + br_multicast_gmi(brmctx));
                                changed = true;
                        }
                }
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        if (__grp_src_delete_marked(pg))
        return changed;
 }
 
-static bool br_multicast_isexc(struct net_bridge_port_group *pg, void *h_addr,
+static bool br_multicast_isexc(const struct net_bridge_mcast *brmctx,
+                              struct net_bridge_port_group *pg, void *h_addr,
                               void *srcs, u32 nsrcs, size_t addr_size,
                               int grec_type)
 {
-       struct net_bridge *br = pg->key.port->br;
        bool changed = false;
 
        switch (pg->filter_mode) {
        case MCAST_INCLUDE:
-               __grp_src_isexc_incl(pg, h_addr, srcs, nsrcs, addr_size,
+               __grp_src_isexc_incl(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
                                     grec_type);
                br_multicast_star_g_handle_mode(pg, MCAST_EXCLUDE);
                changed = true;
                break;
        case MCAST_EXCLUDE:
-               changed = __grp_src_isexc_excl(pg, h_addr, srcs, nsrcs, addr_size,
-                                              grec_type);
+               changed = __grp_src_isexc_excl(brmctx, pg, h_addr, srcs, nsrcs,
+                                              addr_size, grec_type);
                break;
        }
 
        pg->filter_mode = MCAST_EXCLUDE;
-       mod_timer(&pg->timer, jiffies + br_multicast_gmi(br));
+       mod_timer(&pg->timer, jiffies + br_multicast_gmi(brmctx));
 
        return changed;
 }
  * INCLUDE (A)    TO_IN (B)     INCLUDE (A+B)            (B)=GMI
  *                                                       Send Q(G,A-B)
  */
-static bool __grp_src_toin_incl(struct net_bridge_port_group *pg, void *h_addr,
+static bool __grp_src_toin_incl(struct net_bridge_mcast *brmctx,
+                               struct net_bridge_mcast_port *pmctx,
+                               struct net_bridge_port_group *pg, void *h_addr,
                                void *srcs, u32 nsrcs, size_t addr_size,
                                int grec_type)
 {
-       struct net_bridge *br = pg->key.port->br;
        u32 src_idx, to_send = pg->src_ents;
        struct net_bridge_group_src *ent;
        unsigned long now = jiffies;
                                changed = true;
                }
                if (ent)
-                       __grp_src_mod_timer(ent, now + br_multicast_gmi(br));
+                       __grp_src_mod_timer(ent, now + br_multicast_gmi(brmctx));
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        if (to_send)
-               __grp_src_query_marked_and_rexmit(pg);
+               __grp_src_query_marked_and_rexmit(brmctx, pmctx, pg);
 
        return changed;
 }
  *                                                       Send Q(G,X-A)
  *                                                       Send Q(G)
  */
-static bool __grp_src_toin_excl(struct net_bridge_port_group *pg, void *h_addr,
+static bool __grp_src_toin_excl(struct net_bridge_mcast *brmctx,
+                               struct net_bridge_mcast_port *pmctx,
+                               struct net_bridge_port_group *pg, void *h_addr,
                                void *srcs, u32 nsrcs, size_t addr_size,
                                int grec_type)
 {
-       struct net_bridge *br = pg->key.port->br;
        u32 src_idx, to_send = pg->src_ents;
        struct net_bridge_group_src *ent;
        unsigned long now = jiffies;
                                changed = true;
                }
                if (ent)
-                       __grp_src_mod_timer(ent, now + br_multicast_gmi(br));
+                       __grp_src_mod_timer(ent, now + br_multicast_gmi(brmctx));
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        if (to_send)
-               __grp_src_query_marked_and_rexmit(pg);
+               __grp_src_query_marked_and_rexmit(brmctx, pmctx, pg);
 
-       __grp_send_query_and_rexmit(pg);
+       __grp_send_query_and_rexmit(brmctx, pmctx, pg);
 
        return changed;
 }
 
-static bool br_multicast_toin(struct net_bridge_port_group *pg, void *h_addr,
+static bool br_multicast_toin(struct net_bridge_mcast *brmctx,
+                             struct net_bridge_mcast_port *pmctx,
+                             struct net_bridge_port_group *pg, void *h_addr,
                              void *srcs, u32 nsrcs, size_t addr_size,
                              int grec_type)
 {
 
        switch (pg->filter_mode) {
        case MCAST_INCLUDE:
-               changed = __grp_src_toin_incl(pg, h_addr, srcs, nsrcs, addr_size,
-                                             grec_type);
+               changed = __grp_src_toin_incl(brmctx, pmctx, pg, h_addr, srcs,
+                                             nsrcs, addr_size, grec_type);
                break;
        case MCAST_EXCLUDE:
-               changed = __grp_src_toin_excl(pg, h_addr, srcs, nsrcs, addr_size,
-                                             grec_type);
+               changed = __grp_src_toin_excl(brmctx, pmctx, pg, h_addr, srcs,
+                                             nsrcs, addr_size, grec_type);
                break;
        }
 
  *                                                       Send Q(G,A*B)
  *                                                       Group Timer=GMI
  */
-static void __grp_src_toex_incl(struct net_bridge_port_group *pg, void *h_addr,
+static void __grp_src_toex_incl(struct net_bridge_mcast *brmctx,
+                               struct net_bridge_mcast_port *pmctx,
+                               struct net_bridge_port_group *pg, void *h_addr,
                                void *srcs, u32 nsrcs, size_t addr_size,
                                int grec_type)
 {
                        br_multicast_fwd_src_handle(ent);
        }
 
-       br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type);
+       br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                               grec_type);
 
        __grp_src_delete_marked(pg);
        if (to_send)
-               __grp_src_query_marked_and_rexmit(pg);
+               __grp_src_query_marked_and_rexmit(brmctx, pmctx, pg);
 }
 
 /* State          Msg type      New state                Actions
  *                                                       Send Q(G,A-Y)
  *                                                       Group Timer=GMI
  */
-static bool __grp_src_toex_excl(struct net_bridge_port_group *pg, void *h_addr,
+static bool __grp_src_toex_excl(struct net_bridge_mcast *brmctx,
+                               struct net_bridge_mcast_port *pmctx,
+                               struct net_bridge_port_group *pg, void *h_addr,
                                void *srcs, u32 nsrcs, size_t addr_size,
                                int grec_type)
 {
                }
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        if (__grp_src_delete_marked(pg))
                changed = true;
        if (to_send)
-               __grp_src_query_marked_and_rexmit(pg);
+               __grp_src_query_marked_and_rexmit(brmctx, pmctx, pg);
 
        return changed;
 }
 
-static bool br_multicast_toex(struct net_bridge_port_group *pg, void *h_addr,
+static bool br_multicast_toex(struct net_bridge_mcast *brmctx,
+                             struct net_bridge_mcast_port *pmctx,
+                             struct net_bridge_port_group *pg, void *h_addr,
                              void *srcs, u32 nsrcs, size_t addr_size,
                              int grec_type)
 {
-       struct net_bridge *br = pg->key.port->br;
        bool changed = false;
 
        switch (pg->filter_mode) {
        case MCAST_INCLUDE:
-               __grp_src_toex_incl(pg, h_addr, srcs, nsrcs, addr_size,
-                                   grec_type);
+               __grp_src_toex_incl(brmctx, pmctx, pg, h_addr, srcs, nsrcs,
+                                   addr_size, grec_type);
                br_multicast_star_g_handle_mode(pg, MCAST_EXCLUDE);
                changed = true;
                break;
        case MCAST_EXCLUDE:
-               changed = __grp_src_toex_excl(pg, h_addr, srcs, nsrcs, addr_size,
-                                             grec_type);
+               changed = __grp_src_toex_excl(brmctx, pmctx, pg, h_addr, srcs,
+                                             nsrcs, addr_size, grec_type);
                break;
        }
 
        pg->filter_mode = MCAST_EXCLUDE;
-       mod_timer(&pg->timer, jiffies + br_multicast_gmi(br));
+       mod_timer(&pg->timer, jiffies + br_multicast_gmi(brmctx));
 
        return changed;
 }
 /* State          Msg type      New state                Actions
  * INCLUDE (A)    BLOCK (B)     INCLUDE (A)              Send Q(G,A*B)
  */
-static bool __grp_src_block_incl(struct net_bridge_port_group *pg, void *h_addr,
+static bool __grp_src_block_incl(struct net_bridge_mcast *brmctx,
+                                struct net_bridge_mcast_port *pmctx,
+                                struct net_bridge_port_group *pg, void *h_addr,
                                 void *srcs, u32 nsrcs, size_t addr_size, int grec_type)
 {
        struct net_bridge_group_src *ent;
                }
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        if (to_send)
-               __grp_src_query_marked_and_rexmit(pg);
+               __grp_src_query_marked_and_rexmit(brmctx, pmctx, pg);
 
        return changed;
 }
  * EXCLUDE (X,Y)  BLOCK (A)     EXCLUDE (X+(A-Y),Y)      (A-X-Y)=Group Timer
  *                                                       Send Q(G,A-Y)
  */
-static bool __grp_src_block_excl(struct net_bridge_port_group *pg, void *h_addr,
+static bool __grp_src_block_excl(struct net_bridge_mcast *brmctx,
+                                struct net_bridge_mcast_port *pmctx,
+                                struct net_bridge_port_group *pg, void *h_addr,
                                 void *srcs, u32 nsrcs, size_t addr_size, int grec_type)
 {
        struct net_bridge_group_src *ent;
                }
        }
 
-       if (br_multicast_eht_handle(pg, h_addr, srcs, nsrcs, addr_size, grec_type))
+       if (br_multicast_eht_handle(brmctx, pg, h_addr, srcs, nsrcs, addr_size,
+                                   grec_type))
                changed = true;
 
        if (to_send)
-               __grp_src_query_marked_and_rexmit(pg);
+               __grp_src_query_marked_and_rexmit(brmctx, pmctx, pg);
 
        return changed;
 }
 
-static bool br_multicast_block(struct net_bridge_port_group *pg, void *h_addr,
+static bool br_multicast_block(struct net_bridge_mcast *brmctx,
+                              struct net_bridge_mcast_port *pmctx,
+                              struct net_bridge_port_group *pg, void *h_addr,
                               void *srcs, u32 nsrcs, size_t addr_size, int grec_type)
 {
        bool changed = false;
 
        switch (pg->filter_mode) {
        case MCAST_INCLUDE:
-               changed = __grp_src_block_incl(pg, h_addr, srcs, nsrcs, addr_size,
-                                              grec_type);
+               changed = __grp_src_block_incl(brmctx, pmctx, pg, h_addr, srcs,
+                                              nsrcs, addr_size, grec_type);
                break;
        case MCAST_EXCLUDE:
-               changed = __grp_src_block_excl(pg, h_addr, srcs, nsrcs, addr_size,
-                                              grec_type);
+               changed = __grp_src_block_excl(brmctx, pmctx, pg, h_addr, srcs,
+                                              nsrcs, addr_size, grec_type);
                break;
        }
 
        return NULL;
 }
 
-static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
-                                        struct net_bridge_port *port,
+static int br_ip4_multicast_igmp3_report(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx,
                                         struct sk_buff *skb,
                                         u16 vid)
 {
-       bool igmpv2 = br->multicast_ctx.multicast_igmp_version == 2;
+       bool igmpv2 = brmctx->multicast_igmp_version == 2;
        struct net_bridge_mdb_entry *mdst;
        struct net_bridge_port_group *pg;
        const unsigned char *src;
                if (nsrcs == 0 &&
                    (type == IGMPV3_CHANGE_TO_INCLUDE ||
                     type == IGMPV3_MODE_IS_INCLUDE)) {
-                       if (!port || igmpv2) {
-                               br_ip4_multicast_leave_group(br, port, group, vid, src);
+                       if (!pmctx || igmpv2) {
+                               br_ip4_multicast_leave_group(brmctx, pmctx,
+                                                            group, vid, src);
                                continue;
                        }
                } else {
-                       err = br_ip4_multicast_add_group(br, port, group, vid,
-                                                        src, igmpv2);
+                       err = br_ip4_multicast_add_group(brmctx, pmctx, group,
+                                                        vid, src, igmpv2);
                        if (err)
                                break;
                }
 
-               if (!port || igmpv2)
+               if (!pmctx || igmpv2)
                        continue;
 
-               spin_lock_bh(&br->multicast_lock);
-               mdst = br_mdb_ip4_get(br, group, vid);
+               spin_lock_bh(&brmctx->br->multicast_lock);
+               mdst = br_mdb_ip4_get(brmctx->br, group, vid);
                if (!mdst)
                        goto unlock_continue;
-               pg = br_multicast_find_port(mdst, port, src);
+               pg = br_multicast_find_port(mdst, pmctx->port, src);
                if (!pg || (pg->flags & MDB_PG_FLAGS_PERMANENT))
                        goto unlock_continue;
                /* reload grec and host addr */
                h_addr = &ip_hdr(skb)->saddr;
                switch (type) {
                case IGMPV3_ALLOW_NEW_SOURCES:
-                       changed = br_multicast_isinc_allow(pg, h_addr, grec->grec_src,
+                       changed = br_multicast_isinc_allow(brmctx, pg, h_addr,
+                                                          grec->grec_src,
                                                           nsrcs, sizeof(__be32), type);
                        break;
                case IGMPV3_MODE_IS_INCLUDE:
-                       changed = br_multicast_isinc_allow(pg, h_addr, grec->grec_src,
+                       changed = br_multicast_isinc_allow(brmctx, pg, h_addr,
+                                                          grec->grec_src,
                                                           nsrcs, sizeof(__be32), type);
                        break;
                case IGMPV3_MODE_IS_EXCLUDE:
-                       changed = br_multicast_isexc(pg, h_addr, grec->grec_src,
+                       changed = br_multicast_isexc(brmctx, pg, h_addr,
+                                                    grec->grec_src,
                                                     nsrcs, sizeof(__be32), type);
                        break;
                case IGMPV3_CHANGE_TO_INCLUDE:
-                       changed = br_multicast_toin(pg, h_addr, grec->grec_src,
+                       changed = br_multicast_toin(brmctx, pmctx, pg, h_addr,
+                                                   grec->grec_src,
                                                    nsrcs, sizeof(__be32), type);
                        break;
                case IGMPV3_CHANGE_TO_EXCLUDE:
-                       changed = br_multicast_toex(pg, h_addr, grec->grec_src,
+                       changed = br_multicast_toex(brmctx, pmctx, pg, h_addr,
+                                                   grec->grec_src,
                                                    nsrcs, sizeof(__be32), type);
                        break;
                case IGMPV3_BLOCK_OLD_SOURCES:
-                       changed = br_multicast_block(pg, h_addr, grec->grec_src,
+                       changed = br_multicast_block(brmctx, pmctx, pg, h_addr,
+                                                    grec->grec_src,
                                                     nsrcs, sizeof(__be32), type);
                        break;
                }
                if (changed)
-                       br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB);
+                       br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB);
 unlock_continue:
-               spin_unlock_bh(&br->multicast_lock);
+               spin_unlock_bh(&brmctx->br->multicast_lock);
        }
 
        return err;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static int br_ip6_multicast_mld2_report(struct net_bridge *br,
-                                       struct net_bridge_port *port,
+static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
+                                       struct net_bridge_mcast_port *pmctx,
                                        struct sk_buff *skb,
                                        u16 vid)
 {
-       bool mldv1 = br->multicast_ctx.multicast_mld_version == 1;
+       bool mldv1 = brmctx->multicast_mld_version == 1;
        struct net_bridge_mdb_entry *mdst;
        struct net_bridge_port_group *pg;
        unsigned int nsrcs_offset;
                if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE ||
                     grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
                    nsrcs == 0) {
-                       if (!port || mldv1) {
-                               br_ip6_multicast_leave_group(br, port,
+                       if (!pmctx || mldv1) {
+                               br_ip6_multicast_leave_group(brmctx, pmctx,
                                                             &grec->grec_mca,
                                                             vid, src);
                                continue;
                        }
                } else {
-                       err = br_ip6_multicast_add_group(br, port,
+                       err = br_ip6_multicast_add_group(brmctx, pmctx,
                                                         &grec->grec_mca, vid,
                                                         src, mldv1);
                        if (err)
                                break;
                }
 
-               if (!port || mldv1)
+               if (!pmctx || mldv1)
                        continue;
 
-               spin_lock_bh(&br->multicast_lock);
-               mdst = br_mdb_ip6_get(br, &grec->grec_mca, vid);
+               spin_lock_bh(&brmctx->br->multicast_lock);
+               mdst = br_mdb_ip6_get(brmctx->br, &grec->grec_mca, vid);
                if (!mdst)
                        goto unlock_continue;
-               pg = br_multicast_find_port(mdst, port, src);
+               pg = br_multicast_find_port(mdst, pmctx->port, src);
                if (!pg || (pg->flags & MDB_PG_FLAGS_PERMANENT))
                        goto unlock_continue;
                h_addr = &ipv6_hdr(skb)->saddr;
                switch (grec->grec_type) {
                case MLD2_ALLOW_NEW_SOURCES:
-                       changed = br_multicast_isinc_allow(pg, h_addr,
+                       changed = br_multicast_isinc_allow(brmctx, pg, h_addr,
                                                           grec->grec_src, nsrcs,
                                                           sizeof(struct in6_addr),
                                                           grec->grec_type);
                        break;
                case MLD2_MODE_IS_INCLUDE:
-                       changed = br_multicast_isinc_allow(pg, h_addr,
+                       changed = br_multicast_isinc_allow(brmctx, pg, h_addr,
                                                           grec->grec_src, nsrcs,
                                                           sizeof(struct in6_addr),
                                                           grec->grec_type);
                        break;
                case MLD2_MODE_IS_EXCLUDE:
-                       changed = br_multicast_isexc(pg, h_addr,
+                       changed = br_multicast_isexc(brmctx, pg, h_addr,
                                                     grec->grec_src, nsrcs,
                                                     sizeof(struct in6_addr),
                                                     grec->grec_type);
                        break;
                case MLD2_CHANGE_TO_INCLUDE:
-                       changed = br_multicast_toin(pg, h_addr,
+                       changed = br_multicast_toin(brmctx, pmctx, pg, h_addr,
                                                    grec->grec_src, nsrcs,
                                                    sizeof(struct in6_addr),
                                                    grec->grec_type);
                        break;
                case MLD2_CHANGE_TO_EXCLUDE:
-                       changed = br_multicast_toex(pg, h_addr,
+                       changed = br_multicast_toex(brmctx, pmctx, pg, h_addr,
                                                    grec->grec_src, nsrcs,
                                                    sizeof(struct in6_addr),
                                                    grec->grec_type);
                        break;
                case MLD2_BLOCK_OLD_SOURCES:
-                       changed = br_multicast_block(pg, h_addr,
+                       changed = br_multicast_block(brmctx, pmctx, pg, h_addr,
                                                     grec->grec_src, nsrcs,
                                                     sizeof(struct in6_addr),
                                                     grec->grec_type);
                        break;
                }
                if (changed)
-                       br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB);
+                       br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB);
 unlock_continue:
-               spin_unlock_bh(&br->multicast_lock);
+               spin_unlock_bh(&brmctx->br->multicast_lock);
        }
 
        return err;
 }
 #endif
 
-static bool br_ip4_multicast_select_querier(struct net_bridge *br,
+static bool br_ip4_multicast_select_querier(struct net_bridge_mcast *brmctx,
                                            struct net_bridge_port *port,
                                            __be32 saddr)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
-
        if (!timer_pending(&brmctx->ip4_own_query.timer) &&
            !timer_pending(&brmctx->ip4_other_query.timer))
                goto update;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static bool br_ip6_multicast_select_querier(struct net_bridge *br,
+static bool br_ip6_multicast_select_querier(struct net_bridge_mcast *brmctx,
                                            struct net_bridge_port *port,
                                            struct in6_addr *saddr)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
-
        if (!timer_pending(&brmctx->ip6_own_query.timer) &&
            !timer_pending(&brmctx->ip6_other_query.timer))
                goto update;
 #endif
 
 static void
-br_multicast_update_query_timer(struct net_bridge *br,
+br_multicast_update_query_timer(struct net_bridge_mcast *brmctx,
                                struct bridge_mcast_other_query *query,
                                unsigned long max_delay)
 {
        if (!timer_pending(&query->timer))
                query->delay_time = jiffies + max_delay;
 
-       mod_timer(&query->timer, jiffies +
-                                br->multicast_ctx.multicast_querier_interval);
+       mod_timer(&query->timer, jiffies + brmctx->multicast_querier_interval);
 }
 
 static void br_port_mc_router_state_change(struct net_bridge_port *p,
        return slot;
 }
 
-static bool br_multicast_no_router_otherpf(struct net_bridge_port *port,
+static bool br_multicast_no_router_otherpf(struct net_bridge_mcast_port *pmctx,
                                           struct hlist_node *rnode)
 {
 #if IS_ENABLED(CONFIG_IPV6)
-       if (rnode != &port->multicast_ctx.ip6_rlist)
-               return hlist_unhashed(&port->multicast_ctx.ip6_rlist);
+       if (rnode != &pmctx->ip6_rlist)
+               return hlist_unhashed(&pmctx->ip6_rlist);
        else
-               return hlist_unhashed(&port->multicast_ctx.ip4_rlist);
+               return hlist_unhashed(&pmctx->ip4_rlist);
 #else
        return true;
 #endif
  *  and locked by br->multicast_lock and RCU
  */
 static void br_multicast_add_router(struct net_bridge_mcast *brmctx,
-                                   struct net_bridge_port *port,
+                                   struct net_bridge_mcast_port *pmctx,
                                    struct hlist_node *rlist,
                                    struct hlist_head *mc_router_list)
 {
        if (!hlist_unhashed(rlist))
                return;
 
-       slot = br_multicast_get_rport_slot(brmctx, port, mc_router_list);
+       slot = br_multicast_get_rport_slot(brmctx, pmctx->port, mc_router_list);
 
        if (slot)
                hlist_add_behind_rcu(rlist, slot);
         * switched from no IPv4/IPv6 multicast router to a new
         * IPv4 or IPv6 multicast router.
         */
-       if (br_multicast_no_router_otherpf(port, rlist)) {
-               br_rtr_notify(port->br->dev, port, RTM_NEWMDB);
-               br_port_mc_router_state_change(port, true);
+       if (br_multicast_no_router_otherpf(pmctx, rlist)) {
+               br_rtr_notify(pmctx->port->br->dev, pmctx->port, RTM_NEWMDB);
+               br_port_mc_router_state_change(pmctx->port, true);
        }
 }
 
  *  list is maintained ordered by pointer value
  *  and locked by br->multicast_lock and RCU
  */
-static void br_ip4_multicast_add_router(struct net_bridge *br,
-                                       struct net_bridge_port *port)
+static void br_ip4_multicast_add_router(struct net_bridge_mcast *brmctx,
+                                       struct net_bridge_mcast_port *pmctx)
 {
-       br_multicast_add_router(&br->multicast_ctx, port,
-                               &port->multicast_ctx.ip4_rlist,
-                               &br->multicast_ctx.ip4_mc_router_list);
+       br_multicast_add_router(brmctx, pmctx, &pmctx->ip4_rlist,
+                               &brmctx->ip4_mc_router_list);
 }
 
 /* Add port to router_list
  *  list is maintained ordered by pointer value
  *  and locked by br->multicast_lock and RCU
  */
-static void br_ip6_multicast_add_router(struct net_bridge *br,
-                                       struct net_bridge_port *port)
+static void br_ip6_multicast_add_router(struct net_bridge_mcast *brmctx,
+                                       struct net_bridge_mcast_port *pmctx)
 {
 #if IS_ENABLED(CONFIG_IPV6)
-       br_multicast_add_router(&br->multicast_ctx, port,
-                               &port->multicast_ctx.ip6_rlist,
-                               &br->multicast_ctx.ip6_mc_router_list);
+       br_multicast_add_router(brmctx, pmctx, &pmctx->ip6_rlist,
+                               &brmctx->ip6_mc_router_list);
 #endif
 }
 
-static void br_multicast_mark_router(struct net_bridge *br,
-                                    struct net_bridge_port *port,
+static void br_multicast_mark_router(struct net_bridge_mcast *brmctx,
+                                    struct net_bridge_mcast_port *pmctx,
                                     struct timer_list *timer,
                                     struct hlist_node *rlist,
                                     struct hlist_head *mc_router_list)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        unsigned long now = jiffies;
 
-       if (!port) {
+       if (!pmctx) {
                if (brmctx->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) {
                        if (!br_ip4_multicast_is_router(brmctx) &&
                            !br_ip6_multicast_is_router(brmctx))
-                               br_mc_router_state_change(br, true);
+                               br_mc_router_state_change(brmctx->br, true);
                        mod_timer(timer, now + brmctx->multicast_querier_interval);
                }
                return;
        }
 
-       if (port->multicast_ctx.multicast_router == MDB_RTR_TYPE_DISABLED ||
-           port->multicast_ctx.multicast_router == MDB_RTR_TYPE_PERM)
+       if (pmctx->multicast_router == MDB_RTR_TYPE_DISABLED ||
+           pmctx->multicast_router == MDB_RTR_TYPE_PERM)
                return;
 
-       br_multicast_add_router(brmctx, port, rlist, mc_router_list);
+       br_multicast_add_router(brmctx, pmctx, rlist, mc_router_list);
        mod_timer(timer, now + brmctx->multicast_querier_interval);
 }
 
-static void br_ip4_multicast_mark_router(struct net_bridge *br,
-                                        struct net_bridge_port *port)
+static void br_ip4_multicast_mark_router(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx)
 {
-       struct timer_list *timer = &br->multicast_ctx.ip4_mc_router_timer;
+       struct timer_list *timer = &brmctx->ip4_mc_router_timer;
        struct hlist_node *rlist = NULL;
 
-       if (port) {
-               timer = &port->multicast_ctx.ip4_mc_router_timer;
-               rlist = &port->multicast_ctx.ip4_rlist;
+       if (pmctx) {
+               timer = &pmctx->ip4_mc_router_timer;
+               rlist = &pmctx->ip4_rlist;
        }
 
-       br_multicast_mark_router(br, port, timer, rlist,
-                                &br->multicast_ctx.ip4_mc_router_list);
+       br_multicast_mark_router(brmctx, pmctx, timer, rlist,
+                                &brmctx->ip4_mc_router_list);
 }
 
-static void br_ip6_multicast_mark_router(struct net_bridge *br,
-                                        struct net_bridge_port *port)
+static void br_ip6_multicast_mark_router(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx)
 {
 #if IS_ENABLED(CONFIG_IPV6)
-       struct timer_list *timer = &br->multicast_ctx.ip6_mc_router_timer;
+       struct timer_list *timer = &brmctx->ip6_mc_router_timer;
        struct hlist_node *rlist = NULL;
 
-       if (port) {
-               timer = &port->multicast_ctx.ip6_mc_router_timer;
-               rlist = &port->multicast_ctx.ip6_rlist;
+       if (pmctx) {
+               timer = &pmctx->ip6_mc_router_timer;
+               rlist = &pmctx->ip6_rlist;
        }
 
-       br_multicast_mark_router(br, port, timer, rlist,
-                                &br->multicast_ctx.ip6_mc_router_list);
+       br_multicast_mark_router(brmctx, pmctx, timer, rlist,
+                                &brmctx->ip6_mc_router_list);
 #endif
 }
 
 static void
-br_ip4_multicast_query_received(struct net_bridge *br,
-                               struct net_bridge_port *port,
+br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx,
+                               struct net_bridge_mcast_port *pmctx,
                                struct bridge_mcast_other_query *query,
                                struct br_ip *saddr,
                                unsigned long max_delay)
 {
-       if (!br_ip4_multicast_select_querier(br, port, saddr->src.ip4))
+       if (!br_ip4_multicast_select_querier(brmctx, pmctx->port, saddr->src.ip4))
                return;
 
-       br_multicast_update_query_timer(br, query, max_delay);
-       br_ip4_multicast_mark_router(br, port);
+       br_multicast_update_query_timer(brmctx, query, max_delay);
+       br_ip4_multicast_mark_router(brmctx, pmctx);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
 static void
-br_ip6_multicast_query_received(struct net_bridge *br,
-                               struct net_bridge_port *port,
+br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx,
+                               struct net_bridge_mcast_port *pmctx,
                                struct bridge_mcast_other_query *query,
                                struct br_ip *saddr,
                                unsigned long max_delay)
 {
-       if (!br_ip6_multicast_select_querier(br, port, &saddr->src.ip6))
+       if (!br_ip6_multicast_select_querier(brmctx, pmctx->port, &saddr->src.ip6))
                return;
 
-       br_multicast_update_query_timer(br, query, max_delay);
-       br_ip6_multicast_mark_router(br, port);
+       br_multicast_update_query_timer(brmctx, query, max_delay);
+       br_ip6_multicast_mark_router(brmctx, pmctx);
 }
 #endif
 
-static void br_ip4_multicast_query(struct net_bridge *br,
-                                  struct net_bridge_port *port,
+static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx,
+                                  struct net_bridge_mcast_port *pmctx,
                                   struct sk_buff *skb,
                                   u16 vid)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        unsigned int transport_len = ip_transport_len(skb);
        const struct iphdr *iph = ip_hdr(skb);
        struct igmphdr *ih = igmp_hdr(skb);
        unsigned long now = jiffies;
        __be32 group;
 
-       spin_lock(&br->multicast_lock);
-       if (!netif_running(br->dev) ||
-           (port && port->state == BR_STATE_DISABLED))
+       spin_lock(&brmctx->br->multicast_lock);
+       if (!netif_running(brmctx->br->dev) ||
+           (pmctx && pmctx->port->state == BR_STATE_DISABLED))
                goto out;
 
        group = ih->group;
                saddr.proto = htons(ETH_P_IP);
                saddr.src.ip4 = iph->saddr;
 
-               br_ip4_multicast_query_received(br, port,
+               br_ip4_multicast_query_received(brmctx, pmctx,
                                                &brmctx->ip4_other_query,
                                                &saddr, max_delay);
                goto out;
        }
 
-       mp = br_mdb_ip4_get(br, group, vid);
+       mp = br_mdb_ip4_get(brmctx->br, group, vid);
        if (!mp)
                goto out;
 
                mod_timer(&mp->timer, now + max_delay);
 
        for (pp = &mp->ports;
-            (p = mlock_dereference(*pp, br)) != NULL;
+            (p = mlock_dereference(*pp, brmctx->br)) != NULL;
             pp = &p->next) {
                if (timer_pending(&p->timer) ?
                    time_after(p->timer.expires, now + max_delay) :
        }
 
 out:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock(&brmctx->br->multicast_lock);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static int br_ip6_multicast_query(struct net_bridge *br,
-                                 struct net_bridge_port *port,
+static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx,
+                                 struct net_bridge_mcast_port *pmctx,
                                  struct sk_buff *skb,
                                  u16 vid)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        unsigned int transport_len = ipv6_transport_len(skb);
        struct mld_msg *mld;
        struct net_bridge_mdb_entry *mp;
        bool is_general_query;
        int err = 0;
 
-       spin_lock(&br->multicast_lock);
-       if (!netif_running(br->dev) ||
-           (port && port->state == BR_STATE_DISABLED))
+       spin_lock(&brmctx->br->multicast_lock);
+       if (!netif_running(brmctx->br->dev) ||
+           (pmctx && pmctx->port->state == BR_STATE_DISABLED))
                goto out;
 
        if (transport_len == sizeof(*mld)) {
                saddr.proto = htons(ETH_P_IPV6);
                saddr.src.ip6 = ipv6_hdr(skb)->saddr;
 
-               br_ip6_multicast_query_received(br, port,
+               br_ip6_multicast_query_received(brmctx, pmctx,
                                                &brmctx->ip6_other_query,
                                                &saddr, max_delay);
                goto out;
                goto out;
        }
 
-       mp = br_mdb_ip6_get(br, group, vid);
+       mp = br_mdb_ip6_get(brmctx->br, group, vid);
        if (!mp)
                goto out;
 
                mod_timer(&mp->timer, now + max_delay);
 
        for (pp = &mp->ports;
-            (p = mlock_dereference(*pp, br)) != NULL;
+            (p = mlock_dereference(*pp, brmctx->br)) != NULL;
             pp = &p->next) {
                if (timer_pending(&p->timer) ?
                    time_after(p->timer.expires, now + max_delay) :
        }
 
 out:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock(&brmctx->br->multicast_lock);
        return err;
 }
 #endif
 
 static void
-br_multicast_leave_group(struct net_bridge *br,
-                        struct net_bridge_port *port,
+br_multicast_leave_group(struct net_bridge_mcast *brmctx,
+                        struct net_bridge_mcast_port *pmctx,
                         struct br_ip *group,
                         struct bridge_mcast_other_query *other_query,
                         struct bridge_mcast_own_query *own_query,
                         const unsigned char *src)
 {
-       struct net_bridge_mcast *brmctx = &br->multicast_ctx;
        struct net_bridge_mdb_entry *mp;
        struct net_bridge_port_group *p;
        unsigned long now;
        unsigned long time;
 
-       spin_lock(&br->multicast_lock);
-       if (!netif_running(br->dev) ||
-           (port && port->state == BR_STATE_DISABLED))
+       spin_lock(&brmctx->br->multicast_lock);
+       if (!netif_running(brmctx->br->dev) ||
+           (pmctx && pmctx->port->state == BR_STATE_DISABLED))
                goto out;
 
-       mp = br_mdb_ip_get(br, group);
+       mp = br_mdb_ip_get(brmctx->br, group);
        if (!mp)
                goto out;
 
-       if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
+       if (pmctx && (pmctx->port->flags & BR_MULTICAST_FAST_LEAVE)) {
                struct net_bridge_port_group __rcu **pp;
 
                for (pp = &mp->ports;
-                    (p = mlock_dereference(*pp, br)) != NULL;
+                    (p = mlock_dereference(*pp, brmctx->br)) != NULL;
                     pp = &p->next) {
-                       if (!br_port_group_equal(p, port, src))
+                       if (!br_port_group_equal(p, pmctx->port, src))
                                continue;
 
                        if (p->flags & MDB_PG_FLAGS_PERMANENT)
        if (timer_pending(&other_query->timer))
                goto out;
 
-       if (br_opt_get(br, BROPT_MULTICAST_QUERIER)) {
-               __br_multicast_send_query(br, port, NULL, NULL, &mp->addr,
+       if (br_opt_get(brmctx->br, BROPT_MULTICAST_QUERIER)) {
+               __br_multicast_send_query(brmctx, pmctx, NULL, NULL, &mp->addr,
                                          false, 0, NULL);
 
                time = jiffies + brmctx->multicast_last_member_count *
 
                mod_timer(&own_query->timer, time);
 
-               for (p = mlock_dereference(mp->ports, br);
+               for (p = mlock_dereference(mp->ports, brmctx->br);
                     p != NULL;
-                    p = mlock_dereference(p->next, br)) {
-                       if (!br_port_group_equal(p, port, src))
+                    p = mlock_dereference(p->next, brmctx->br)) {
+                       if (!br_port_group_equal(p, pmctx->port, src))
                                continue;
 
                        if (!hlist_unhashed(&p->mglist) &&
        time = now + brmctx->multicast_last_member_count *
                     brmctx->multicast_last_member_interval;
 
-       if (!port) {
+       if (!pmctx) {
                if (mp->host_joined &&
                    (timer_pending(&mp->timer) ?
                     time_after(mp->timer.expires, time) :
                goto out;
        }
 
-       for (p = mlock_dereference(mp->ports, br);
+       for (p = mlock_dereference(mp->ports, brmctx->br);
             p != NULL;
-            p = mlock_dereference(p->next, br)) {
-               if (p->key.port != port)
+            p = mlock_dereference(p->next, brmctx->br)) {
+               if (p->key.port != pmctx->port)
                        continue;
 
                if (!hlist_unhashed(&p->mglist) &&
                break;
        }
 out:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock(&brmctx->br->multicast_lock);
 }
 
-static void br_ip4_multicast_leave_group(struct net_bridge *br,
-                                        struct net_bridge_port *port,
+static void br_ip4_multicast_leave_group(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx,
                                         __be32 group,
                                         __u16 vid,
                                         const unsigned char *src)
        if (ipv4_is_local_multicast(group))
                return;
 
-       own_query = port ? &port->multicast_ctx.ip4_own_query :
-                          &br->multicast_ctx.ip4_own_query;
+       own_query = pmctx ? &pmctx->ip4_own_query : &brmctx->ip4_own_query;
 
        memset(&br_group, 0, sizeof(br_group));
        br_group.dst.ip4 = group;
        br_group.proto = htons(ETH_P_IP);
        br_group.vid = vid;
 
-       br_multicast_leave_group(br, port, &br_group,
-                                &br->multicast_ctx.ip4_other_query,
+       br_multicast_leave_group(brmctx, pmctx, &br_group,
+                                &brmctx->ip4_other_query,
                                 own_query, src);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static void br_ip6_multicast_leave_group(struct net_bridge *br,
-                                        struct net_bridge_port *port,
+static void br_ip6_multicast_leave_group(struct net_bridge_mcast *brmctx,
+                                        struct net_bridge_mcast_port *pmctx,
                                         const struct in6_addr *group,
                                         __u16 vid,
                                         const unsigned char *src)
        if (ipv6_addr_is_ll_all_nodes(group))
                return;
 
-       own_query = port ? &port->multicast_ctx.ip6_own_query :
-                          &br->multicast_ctx.ip6_own_query;
+       own_query = pmctx ? &pmctx->ip6_own_query : &brmctx->ip6_own_query;
 
        memset(&br_group, 0, sizeof(br_group));
        br_group.dst.ip6 = *group;
        br_group.proto = htons(ETH_P_IPV6);
        br_group.vid = vid;
 
-       br_multicast_leave_group(br, port, &br_group,
-                                &br->multicast_ctx.ip6_other_query,
+       br_multicast_leave_group(brmctx, pmctx, &br_group,
+                                &brmctx->ip6_other_query,
                                 own_query, src);
 }
 #endif
        u64_stats_update_end(&pstats->syncp);
 }
 
-static void br_multicast_pim(struct net_bridge *br,
-                            struct net_bridge_port *port,
+static void br_multicast_pim(struct net_bridge_mcast *brmctx,
+                            struct net_bridge_mcast_port *pmctx,
                             const struct sk_buff *skb)
 {
        unsigned int offset = skb_transport_offset(skb);
            pim_hdr_type(pimhdr) != PIM_TYPE_HELLO)
                return;
 
-       spin_lock(&br->multicast_lock);
-       br_ip4_multicast_mark_router(br, port);
-       spin_unlock(&br->multicast_lock);
+       spin_lock(&brmctx->br->multicast_lock);
+       br_ip4_multicast_mark_router(brmctx, pmctx);
+       spin_unlock(&brmctx->br->multicast_lock);
 }
 
-static int br_ip4_multicast_mrd_rcv(struct net_bridge *br,
-                                   struct net_bridge_port *port,
+static int br_ip4_multicast_mrd_rcv(struct net_bridge_mcast *brmctx,
+                                   struct net_bridge_mcast_port *pmctx,
                                    struct sk_buff *skb)
 {
        if (ip_hdr(skb)->protocol != IPPROTO_IGMP ||
            igmp_hdr(skb)->type != IGMP_MRDISC_ADV)
                return -ENOMSG;
 
-       spin_lock(&br->multicast_lock);
-       br_ip4_multicast_mark_router(br, port);
-       spin_unlock(&br->multicast_lock);
+       spin_lock(&brmctx->br->multicast_lock);
+       br_ip4_multicast_mark_router(brmctx, pmctx);
+       spin_unlock(&brmctx->br->multicast_lock);
 
        return 0;
 }
 
-static int br_multicast_ipv4_rcv(struct net_bridge *br,
-                                struct net_bridge_port *port,
+static int br_multicast_ipv4_rcv(struct net_bridge_mcast *brmctx,
+                                struct net_bridge_mcast_port *pmctx,
                                 struct sk_buff *skb,
                                 u16 vid)
 {
+       struct net_bridge_port *p = pmctx ? pmctx->port : NULL;
        const unsigned char *src;
        struct igmphdr *ih;
        int err;
                        BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
                } else if (pim_ipv4_all_pim_routers(ip_hdr(skb)->daddr)) {
                        if (ip_hdr(skb)->protocol == IPPROTO_PIM)
-                               br_multicast_pim(br, port, skb);
+                               br_multicast_pim(brmctx, pmctx, skb);
                } else if (ipv4_is_all_snoopers(ip_hdr(skb)->daddr)) {
-                       br_ip4_multicast_mrd_rcv(br, port, skb);
+                       br_ip4_multicast_mrd_rcv(brmctx, pmctx, skb);
                }
 
                return 0;
        } else if (err < 0) {
-               br_multicast_err_count(br, port, skb->protocol);
+               br_multicast_err_count(brmctx->br, p, skb->protocol);
                return err;
        }
 
        case IGMP_HOST_MEMBERSHIP_REPORT:
        case IGMPV2_HOST_MEMBERSHIP_REPORT:
                BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
-               err = br_ip4_multicast_add_group(br, port, ih->group, vid, src,
-                                                true);
+               err = br_ip4_multicast_add_group(brmctx, pmctx, ih->group, vid,
+                                                src, true);
                break;
        case IGMPV3_HOST_MEMBERSHIP_REPORT:
-               err = br_ip4_multicast_igmp3_report(br, port, skb, vid);
+               err = br_ip4_multicast_igmp3_report(brmctx, pmctx, skb, vid);
                break;
        case IGMP_HOST_MEMBERSHIP_QUERY:
-               br_ip4_multicast_query(br, port, skb, vid);
+               br_ip4_multicast_query(brmctx, pmctx, skb, vid);
                break;
        case IGMP_HOST_LEAVE_MESSAGE:
-               br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
+               br_ip4_multicast_leave_group(brmctx, pmctx, ih->group, vid, src);
                break;
        }
 
-       br_multicast_count(br, port, skb, BR_INPUT_SKB_CB(skb)->igmp,
+       br_multicast_count(brmctx->br, p, skb, BR_INPUT_SKB_CB(skb)->igmp,
                           BR_MCAST_DIR_RX);
 
        return err;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static void br_ip6_multicast_mrd_rcv(struct net_bridge *br,
-                                    struct net_bridge_port *port,
+static void br_ip6_multicast_mrd_rcv(struct net_bridge_mcast *brmctx,
+                                    struct net_bridge_mcast_port *pmctx,
                                     struct sk_buff *skb)
 {
        if (icmp6_hdr(skb)->icmp6_type != ICMPV6_MRDISC_ADV)
                return;
 
-       spin_lock(&br->multicast_lock);
-       br_ip6_multicast_mark_router(br, port);
-       spin_unlock(&br->multicast_lock);
+       spin_lock(&brmctx->br->multicast_lock);
+       br_ip6_multicast_mark_router(brmctx, pmctx);
+       spin_unlock(&brmctx->br->multicast_lock);
 }
 
-static int br_multicast_ipv6_rcv(struct net_bridge *br,
-                                struct net_bridge_port *port,
+static int br_multicast_ipv6_rcv(struct net_bridge_mcast *brmctx,
+                                struct net_bridge_mcast_port *pmctx,
                                 struct sk_buff *skb,
                                 u16 vid)
 {
+       struct net_bridge_port *p = pmctx ? pmctx->port : NULL;
        const unsigned char *src;
        struct mld_msg *mld;
        int err;
                        BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
                if (err == -ENODATA &&
                    ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr))
-                       br_ip6_multicast_mrd_rcv(br, port, skb);
+                       br_ip6_multicast_mrd_rcv(brmctx, pmctx, skb);
 
                return 0;
        } else if (err < 0) {
-               br_multicast_err_count(br, port, skb->protocol);
+               br_multicast_err_count(brmctx->br, p, skb->protocol);
                return err;
        }
 
        case ICMPV6_MGM_REPORT:
                src = eth_hdr(skb)->h_source;
                BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
-               err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid,
-                                                src, true);
+               err = br_ip6_multicast_add_group(brmctx, pmctx, &mld->mld_mca,
+                                                vid, src, true);
                break;
        case ICMPV6_MLD2_REPORT:
-               err = br_ip6_multicast_mld2_report(br, port, skb, vid);
+               err = br_ip6_multicast_mld2_report(brmctx, pmctx, skb, vid);
                break;
        case ICMPV6_MGM_QUERY:
-               err = br_ip6_multicast_query(br, port, skb, vid);
+               err = br_ip6_multicast_query(brmctx, pmctx, skb, vid);
                break;
        case ICMPV6_MGM_REDUCTION:
                src = eth_hdr(skb)->h_source;
-               br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
+               br_ip6_multicast_leave_group(brmctx, pmctx, &mld->mld_mca, vid,
+                                            src);
                break;
        }
 
-       br_multicast_count(br, port, skb, BR_INPUT_SKB_CB(skb)->igmp,
+       br_multicast_count(brmctx->br, p, skb, BR_INPUT_SKB_CB(skb)->igmp,
                           BR_MCAST_DIR_RX);
 
        return err;
 }
 #endif
 
-int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
+int br_multicast_rcv(struct net_bridge_mcast *brmctx,
+                    struct net_bridge_mcast_port *pmctx,
                     struct sk_buff *skb, u16 vid)
 {
        int ret = 0;
        BR_INPUT_SKB_CB(skb)->igmp = 0;
        BR_INPUT_SKB_CB(skb)->mrouters_only = 0;
 
-       if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
+       if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
                return 0;
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
-               ret = br_multicast_ipv4_rcv(br, port, skb, vid);
+               ret = br_multicast_ipv4_rcv(brmctx, pmctx, skb, vid);
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case htons(ETH_P_IPV6):
-               ret = br_multicast_ipv6_rcv(br, port, skb, vid);
+               ret = br_multicast_ipv6_rcv(brmctx, pmctx, skb, vid);
                break;
 #endif
        }
        return ret;
 }
 
-static void br_multicast_query_expired(struct net_bridge *br,
+static void br_multicast_query_expired(struct net_bridge_mcast *brmctx,
                                       struct bridge_mcast_own_query *query,
                                       struct bridge_mcast_querier *querier)
 {
-       spin_lock(&br->multicast_lock);
-       if (query->startup_sent < br->multicast_ctx.multicast_startup_query_count)
+       spin_lock(&brmctx->br->multicast_lock);
+       if (query->startup_sent < brmctx->multicast_startup_query_count)
                query->startup_sent++;
 
        RCU_INIT_POINTER(querier->port, NULL);
-       br_multicast_send_query(br, NULL, query);
-       spin_unlock(&br->multicast_lock);
+       br_multicast_send_query(brmctx, NULL, query);
+       spin_unlock(&brmctx->br->multicast_lock);
 }
 
 static void br_ip4_multicast_query_expired(struct timer_list *t)
        struct net_bridge_mcast *brmctx = from_timer(brmctx, t,
                                                     ip4_own_query.timer);
 
-       br_multicast_query_expired(brmctx->br, &brmctx->ip4_own_query,
+       br_multicast_query_expired(brmctx, &brmctx->ip4_own_query,
                                   &brmctx->ip4_querier);
 }
 
        struct net_bridge_mcast *brmctx = from_timer(brmctx, t,
                                                     ip6_own_query.timer);
 
-       br_multicast_query_expired(brmctx->br, &brmctx->ip6_own_query,
+       br_multicast_query_expired(brmctx, &brmctx->ip6_own_query,
                                   &brmctx->ip6_querier);
 }
 #endif
 }
 
 static void
-br_multicast_rport_del_notify(struct net_bridge_port *p, bool deleted)
+br_multicast_rport_del_notify(struct net_bridge_mcast_port *pmctx, bool deleted)
 {
        if (!deleted)
                return;
        /* For backwards compatibility for now, only notify if there is
         * no multicast router anymore for both IPv4 and IPv6.
         */
-       if (!hlist_unhashed(&p->multicast_ctx.ip4_rlist))
+       if (!hlist_unhashed(&pmctx->ip4_rlist))
                return;
 #if IS_ENABLED(CONFIG_IPV6)
-       if (!hlist_unhashed(&p->multicast_ctx.ip6_rlist))
+       if (!hlist_unhashed(&pmctx->ip6_rlist))
                return;
 #endif
 
-       br_rtr_notify(p->br->dev, p, RTM_DELMDB);
-       br_port_mc_router_state_change(p, false);
+       br_rtr_notify(pmctx->port->br->dev, pmctx->port, RTM_DELMDB);
+       br_port_mc_router_state_change(pmctx->port, false);
 
        /* don't allow timer refresh */
-       if (p->multicast_ctx.multicast_router == MDB_RTR_TYPE_TEMP)
-               p->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
+       if (pmctx->multicast_router == MDB_RTR_TYPE_TEMP)
+               pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
 }
 
 int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
 {
        struct net_bridge_mcast *brmctx = &p->br->multicast_ctx;
+       struct net_bridge_mcast_port *pmctx = &p->multicast_ctx;
        unsigned long now = jiffies;
        int err = -EINVAL;
        bool del = false;
 
        spin_lock(&p->br->multicast_lock);
-       if (p->multicast_ctx.multicast_router == val) {
+       if (pmctx->multicast_router == val) {
                /* Refresh the temp router port timer */
-               if (p->multicast_ctx.multicast_router == MDB_RTR_TYPE_TEMP) {
-                       mod_timer(&p->multicast_ctx.ip4_mc_router_timer,
+               if (pmctx->multicast_router == MDB_RTR_TYPE_TEMP) {
+                       mod_timer(&pmctx->ip4_mc_router_timer,
                                  now + brmctx->multicast_querier_interval);
 #if IS_ENABLED(CONFIG_IPV6)
-                       mod_timer(&p->multicast_ctx.ip6_mc_router_timer,
+                       mod_timer(&pmctx->ip6_mc_router_timer,
                                  now + brmctx->multicast_querier_interval);
 #endif
                }
        }
        switch (val) {
        case MDB_RTR_TYPE_DISABLED:
-               p->multicast_ctx.multicast_router = MDB_RTR_TYPE_DISABLED;
-               del |= br_ip4_multicast_rport_del(p);
-               del_timer(&p->multicast_ctx.ip4_mc_router_timer);
-               del |= br_ip6_multicast_rport_del(p);
+               pmctx->multicast_router = MDB_RTR_TYPE_DISABLED;
+               del |= br_ip4_multicast_rport_del(pmctx);
+               del_timer(&pmctx->ip4_mc_router_timer);
+               del |= br_ip6_multicast_rport_del(pmctx);
 #if IS_ENABLED(CONFIG_IPV6)
-               del_timer(&p->multicast_ctx.ip6_mc_router_timer);
+               del_timer(&pmctx->ip6_mc_router_timer);
 #endif
-               br_multicast_rport_del_notify(p, del);
+               br_multicast_rport_del_notify(pmctx, del);
                break;
        case MDB_RTR_TYPE_TEMP_QUERY:
-               p->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
-               del |= br_ip4_multicast_rport_del(p);
-               del |= br_ip6_multicast_rport_del(p);
-               br_multicast_rport_del_notify(p, del);
+               pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
+               del |= br_ip4_multicast_rport_del(pmctx);
+               del |= br_ip6_multicast_rport_del(pmctx);
+               br_multicast_rport_del_notify(pmctx, del);
                break;
        case MDB_RTR_TYPE_PERM:
-               p->multicast_ctx.multicast_router = MDB_RTR_TYPE_PERM;
-               del_timer(&p->multicast_ctx.ip4_mc_router_timer);
-               br_ip4_multicast_add_router(p->br, p);
+               pmctx->multicast_router = MDB_RTR_TYPE_PERM;
+               del_timer(&pmctx->ip4_mc_router_timer);
+               br_ip4_multicast_add_router(brmctx, pmctx);
 #if IS_ENABLED(CONFIG_IPV6)
-               del_timer(&p->multicast_ctx.ip6_mc_router_timer);
+               del_timer(&pmctx->ip6_mc_router_timer);
 #endif
-               br_ip6_multicast_add_router(p->br, p);
+               br_ip6_multicast_add_router(brmctx, pmctx);
                break;
        case MDB_RTR_TYPE_TEMP:
-               p->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP;
-               br_ip4_multicast_mark_router(p->br, p);
-               br_ip6_multicast_mark_router(p->br, p);
+               pmctx->multicast_router = MDB_RTR_TYPE_TEMP;
+               br_ip4_multicast_mark_router(brmctx, pmctx);
+               br_ip6_multicast_mark_router(brmctx, pmctx);
                break;
        default:
                goto unlock;
        return err;
 }
 
-static void br_multicast_start_querier(struct net_bridge *br,
+static void br_multicast_start_querier(struct net_bridge_mcast *brmctx,
                                       struct bridge_mcast_own_query *query)
 {
        struct net_bridge_port *port;
 
-       __br_multicast_open(br, query);
+       __br_multicast_open(brmctx->br, query);
 
        rcu_read_lock();
-       list_for_each_entry_rcu(port, &br->port_list, list) {
+       list_for_each_entry_rcu(port, &brmctx->br->port_list, list) {
                if (port->state == BR_STATE_DISABLED ||
                    port->state == BR_STATE_BLOCKING)
                        continue;
 
-               if (query == &br->multicast_ctx.ip4_own_query)
+               if (query == &brmctx->ip4_own_query)
                        br_multicast_enable(&port->multicast_ctx.ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
                else
 
        br_multicast_open(br);
        list_for_each_entry(port, &br->port_list, list)
-               __br_multicast_enable_port(port);
+               __br_multicast_enable_port_ctx(&port->multicast_ctx);
 
        change_snoopers = true;
 
        bool is_router;
 
        spin_lock_bh(&br->multicast_lock);
-       is_router = br_multicast_is_router(br, NULL);
+       is_router = br_multicast_is_router(&br->multicast_ctx, NULL);
        spin_unlock_bh(&br->multicast_lock);
        return is_router;
 }
        if (!timer_pending(&brmctx->ip4_other_query.timer))
                brmctx->ip4_other_query.delay_time = jiffies + max_delay;
 
-       br_multicast_start_querier(br, &brmctx->ip4_own_query);
+       br_multicast_start_querier(brmctx, &brmctx->ip4_own_query);
 
 #if IS_ENABLED(CONFIG_IPV6)
        if (!timer_pending(&brmctx->ip6_other_query.timer))
                brmctx->ip6_other_query.delay_time = jiffies + max_delay;
 
-       br_multicast_start_querier(br, &brmctx->ip6_own_query);
+       br_multicast_start_querier(brmctx, &brmctx->ip6_own_query);
 #endif
 
 unlock:
        memset(ð, 0, sizeof(eth));
        eth.h_proto = htons(proto);
 
-       ret = br_multicast_querier_exists(br, ð, NULL);
+       ret = br_multicast_querier_exists(&br->multicast_ctx, ð, NULL);
 
 unlock:
        rcu_read_unlock();
        u64_stats_update_end(&pstats->syncp);
 }
 
-void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
+void br_multicast_count(struct net_bridge *br,
+                       const struct net_bridge_port *p,
                        const struct sk_buff *skb, u8 type, u8 dir)
 {
        struct bridge_mcast_stats __percpu *stats;