diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 55f47cadb11403..6ac5313e1cb8de 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -135,34 +135,49 @@ static void br_port_clear_promisc(struct net_bridge_port *p) void br_manage_promisc(struct net_bridge *br) { struct net_bridge_port *p; - bool set_all = false; - - /* If vlan filtering is disabled or bridge interface is placed - * into promiscuous mode, place all ports in promiscuous mode. - */ - if ((br->dev->flags & IFF_PROMISC) || !br_vlan_enabled(br->dev)) - set_all = true; list_for_each_entry(p, &br->port_list, list) { - if (set_all) { + /* Offloaded ports have a separate address database for + * forwarding, which is managed through switchdev and not + * through dev_uc_add(), so the promiscuous concept makes no + * sense for them. Avoid updating promiscuity in that case. + */ + if (p->offload_count) { + br_port_clear_promisc(p); + continue; + } + + /* If bridge is promiscuous, unconditionally place all ports + * in promiscuous mode too. This allows the bridge device to + * locally receive all unknown traffic. + */ + if (br->dev->flags & IFF_PROMISC) { + br_port_set_promisc(p); + continue; + } + + /* If vlan filtering is disabled, place all ports in + * promiscuous mode. + */ + if (!br_vlan_enabled(br->dev)) { br_port_set_promisc(p); - } else { - /* If the number of auto-ports is <= 1, then all other - * ports will have their output configuration - * statically specified through fdbs. Since ingress - * on the auto-port becomes forwarding/egress to other - * ports and egress configuration is statically known, - * we can say that ingress configuration of the - * auto-port is also statically known. - * This lets us disable promiscuous mode and write - * this config to hw. - */ - if (br->auto_cnt == 0 || - (br->auto_cnt == 1 && br_auto_port(p))) - br_port_clear_promisc(p); - else - br_port_set_promisc(p); + continue; } + + /* If the number of auto-ports is <= 1, then all other ports + * will have their output configuration statically specified + * through fdbs. Since ingress on the auto-port becomes + * forwarding/egress to other ports and egress configuration is + * statically known, we can say that ingress configuration of + * the auto-port is also statically known. + * This lets us disable promiscuous mode and write this config + * to hw. + */ + if (br->auto_cnt == 0 || + (br->auto_cnt == 1 && br_auto_port(p))) + br_port_clear_promisc(p); + else + br_port_set_promisc(p); } }