Ticket #16982: 645-bridge_multicast_to_unicast.patch

File 645-bridge_multicast_to_unicast.patch, 10.3 KB (added by yohimba@…, 4 years ago)

Patch for AA 12.09

  • net/bridge/br_forward.c

    diff -Nrup a/net/bridge/br_forward.c b/net/bridge/br_forward.c
    a b out: 
    160160        return p; 
    161161} 
    162162 
     163static struct net_bridge_port *maybe_deliver_addr( 
     164        struct net_bridge_port *prev, struct net_bridge_port *p, 
     165        struct sk_buff *skb, const unsigned char *addr, 
     166        void (*__packet_hook)(const struct net_bridge_port *p, 
     167                              struct sk_buff *skb)) 
     168{ 
     169        struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; 
     170 
     171        if (!should_deliver(p, skb)) 
     172                return prev; 
     173 
     174        skb = skb_copy(skb, GFP_ATOMIC); 
     175        if (!skb) { 
     176                dev->stats.tx_dropped++; 
     177                return prev; 
     178        } 
     179 
     180        memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN); 
     181        __packet_hook(p, skb); 
     182 
     183        return prev; 
     184} 
     185 
    163186/* called under bridge lock */ 
    164187static void br_flood(struct net_bridge *br, struct sk_buff *skb, 
    165188                     struct sk_buff *skb0, 
    static void br_multicast_flood(struct ne 
    222245        struct net_bridge_port *prev = NULL; 
    223246        struct net_bridge_port_group *p; 
    224247        struct hlist_node *rp; 
     248        const unsigned char *addr; 
    225249 
    226250        rp = rcu_dereference(hlist_first_rcu(&br->router_list)); 
    227251        p = mdst ? rcu_dereference(mdst->ports) : NULL; 
    static void br_multicast_flood(struct ne 
    232256                rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : 
    233257                             NULL; 
    234258 
    235                 port = (unsigned long)lport > (unsigned long)rport ? 
    236                        lport : rport; 
    237  
    238                 prev = maybe_deliver(prev, port, skb, __packet_hook); 
     259                if ((unsigned long)lport > (unsigned long)rport) { 
     260                        port = lport; 
     261                        addr = p->unicast ? p->eth_addr : NULL; 
     262                } else { 
     263                        port = rport; 
     264                        addr = NULL; 
     265                } 
     266 
     267                if (addr) 
     268                        prev = maybe_deliver_addr(prev, port, skb, addr, __packet_hook); 
     269                else 
     270                        prev = maybe_deliver(prev, port, skb, __packet_hook); 
    239271                if (IS_ERR(prev)) 
    240272                        goto out; 
    241273 
  • net/bridge/br_multicast.c

    diff -Nrup a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
    a b out: 
    628628        return mp; 
    629629} 
    630630 
     631static bool br_port_group_equal(struct net_bridge_port_group *p, 
     632                                struct net_bridge_port *port, 
     633                                const unsigned char *src) 
     634{ 
     635        if (p->port != port) 
     636                return false; 
     637 
     638        if (!p->unicast) 
     639                return true; 
     640 
     641        if (!src) 
     642                return false; 
     643 
     644        return !compare_ether_addr(src, p->eth_addr); 
     645} 
     646 
    631647static int br_multicast_add_group(struct net_bridge *br, 
    632648                                  struct net_bridge_port *port, 
    633                                   struct br_ip *group) 
     649                                  struct br_ip *group, 
     650                                  const unsigned char *src) 
    634651{ 
    635652        struct net_bridge_mdb_entry *mp; 
    636653        struct net_bridge_port_group *p; 
    static int br_multicast_add_group(struct 
    657674        for (pp = &mp->ports; 
    658675             (p = mlock_dereference(*pp, br)) != NULL; 
    659676             pp = &p->next) { 
    660                 if (p->port == port) 
     677                if (br_port_group_equal(p, port, src)) 
    661678                        goto found; 
    662679                if ((unsigned long)p->port < (unsigned long)port) 
    663680                        break; 
    static int br_multicast_add_group(struct 
    674691        hlist_add_head(&p->mglist, &port->mglist); 
    675692        setup_timer(&p->timer, br_multicast_port_group_expired, 
    676693                    (unsigned long)p); 
     694        if ((port->flags & BR_MULTICAST_TO_UCAST) && src) { 
     695                memcpy(p->eth_addr, src, ETH_ALEN); 
     696                p->unicast = true; 
     697        } 
    677698 
    678699        rcu_assign_pointer(*pp, p); 
    679700 
    err: 
    689710 
    690711static int br_ip4_multicast_add_group(struct net_bridge *br, 
    691712                                      struct net_bridge_port *port, 
    692                                       __be32 group) 
     713                                      __be32 group, const unsigned char *src) 
    693714{ 
    694715        struct br_ip br_group; 
    695716 
    static int br_ip4_multicast_add_group(st 
    699720        br_group.u.ip4 = group; 
    700721        br_group.proto = htons(ETH_P_IP); 
    701722 
    702         return br_multicast_add_group(br, port, &br_group); 
     723        return br_multicast_add_group(br, port, &br_group, src); 
    703724} 
    704725 
    705726#if IS_ENABLED(CONFIG_IPV6) 
    706727static int br_ip6_multicast_add_group(struct net_bridge *br, 
    707728                                      struct net_bridge_port *port, 
    708                                       const struct in6_addr *group) 
     729                                      const struct in6_addr *group, const unsigned char *src) 
    709730{ 
    710731        struct br_ip br_group; 
    711732 
    static int br_ip6_multicast_add_group(st 
    715736        br_group.u.ip6 = *group; 
    716737        br_group.proto = htons(ETH_P_IPV6); 
    717738 
    718         return br_multicast_add_group(br, port, &br_group); 
     739        return br_multicast_add_group(br, port, &br_group, src); 
    719740} 
    720741#endif 
    721742 
    static int br_ip4_multicast_igmp3_report 
    867888                                         struct net_bridge_port *port, 
    868889                                         struct sk_buff *skb) 
    869890{ 
     891        const unsigned char *src = eth_hdr(skb)->h_source; 
    870892        struct igmpv3_report *ih; 
    871893        struct igmpv3_grec *grec; 
    872894        int i; 
    static int br_ip4_multicast_igmp3_report 
    910932                        continue; 
    911933                } 
    912934 
    913                 err = br_ip4_multicast_add_group(br, port, group); 
     935                err = br_ip4_multicast_add_group(br, port, group, src); 
    914936                if (err) 
    915937                        break; 
    916938        } 
    static int br_ip6_multicast_mld2_report( 
    923945                                        struct net_bridge_port *port, 
    924946                                        struct sk_buff *skb) 
    925947{ 
     948        const unsigned char *src = eth_hdr(skb)->h_source; 
    926949        struct icmp6hdr *icmp6h; 
    927950        struct mld2_grec *grec; 
    928951        int i; 
    static int br_ip6_multicast_mld2_report( 
    970993                        continue; 
    971994                } 
    972995 
    973                 err = br_ip6_multicast_add_group(br, port, &grec->grec_mca); 
     996                err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, src); 
    974997                if (!err) 
    975998                        break; 
    976999        } 
    out: 
    11881211 
    11891212static void br_multicast_leave_group(struct net_bridge *br, 
    11901213                                     struct net_bridge_port *port, 
    1191                                      struct br_ip *group) 
     1214                                     struct br_ip *group, 
     1215                                     const unsigned char *src) 
    11921216{ 
    11931217        struct net_bridge_mdb_htable *mdb; 
    11941218        struct net_bridge_mdb_entry *mp; 
    static void br_multicast_leave_group(str 
    12251249        for (p = mlock_dereference(mp->ports, br); 
    12261250             p != NULL; 
    12271251             p = mlock_dereference(p->next, br)) { 
    1228                 if (p->port != port) 
     1252                if (!br_port_group_equal(p, port, src)) 
    12291253                        continue; 
    12301254 
    12311255                if (!hlist_unhashed(&p->mglist) && 
    out: 
    12441268 
    12451269static void br_ip4_multicast_leave_group(struct net_bridge *br, 
    12461270                                         struct net_bridge_port *port, 
    1247                                          __be32 group) 
     1271                                         __be32 group, const unsigned char *src) 
    12481272{ 
    12491273        struct br_ip br_group; 
    12501274 
    static void br_ip4_multicast_leave_group 
    12541278        br_group.u.ip4 = group; 
    12551279        br_group.proto = htons(ETH_P_IP); 
    12561280 
    1257         br_multicast_leave_group(br, port, &br_group); 
     1281        br_multicast_leave_group(br, port, &br_group, src); 
    12581282} 
    12591283 
    12601284#if IS_ENABLED(CONFIG_IPV6) 
    12611285static void br_ip6_multicast_leave_group(struct net_bridge *br, 
    12621286                                         struct net_bridge_port *port, 
    1263                                          const struct in6_addr *group) 
     1287                                         const struct in6_addr *group, 
     1288                                         const unsigned char *src) 
    12641289{ 
    12651290        struct br_ip br_group; 
    12661291 
    static void br_ip6_multicast_leave_group 
    12701295        br_group.u.ip6 = *group; 
    12711296        br_group.proto = htons(ETH_P_IPV6); 
    12721297 
    1273         br_multicast_leave_group(br, port, &br_group); 
     1298        br_multicast_leave_group(br, port, &br_group, src); 
    12741299} 
    12751300#endif 
    12761301 
    static int br_multicast_ipv4_rcv(struct 
    12781303                                 struct net_bridge_port *port, 
    12791304                                 struct sk_buff *skb) 
    12801305{ 
     1306        const unsigned char *src = eth_hdr(skb)->h_source; 
    12811307        struct sk_buff *skb2 = skb; 
    12821308        const struct iphdr *iph; 
    12831309        struct igmphdr *ih; 
    static int br_multicast_ipv4_rcv(struct 
    13511377        case IGMP_HOST_MEMBERSHIP_REPORT: 
    13521378        case IGMPV2_HOST_MEMBERSHIP_REPORT: 
    13531379                BR_INPUT_SKB_CB(skb)->mrouters_only = 1; 
    1354                 err = br_ip4_multicast_add_group(br, port, ih->group); 
     1380                err = br_ip4_multicast_add_group(br, port, ih->group, src); 
    13551381                break; 
    13561382        case IGMPV3_HOST_MEMBERSHIP_REPORT: 
    13571383                err = br_ip4_multicast_igmp3_report(br, port, skb2); 
    static int br_multicast_ipv4_rcv(struct 
    1363                 br_ip4_multicast_leave_group(br, port, ih->group); 
     1389                br_ip4_multicast_leave_group(br, port, ih->group, src); 
    13641390                break; 
    13651391        } 
    13661392 
    static int br_multicast_ipv6_rcv(struct 
    13771403                                 struct net_bridge_port *port, 
    13781404                                 struct sk_buff *skb) 
    13791405{ 
     1406        const unsigned char *src = eth_hdr(skb)->h_source; 
    13801407        struct sk_buff *skb2; 
    13811408        const struct ipv6hdr *ip6h; 
    13821409        u8 icmp6_type; 
    static int br_multicast_ipv6_rcv(struct 
    14801507                } 
    14811508                mld = (struct mld_msg *)skb_transport_header(skb2); 
    14821509                BR_INPUT_SKB_CB(skb)->mrouters_only = 1; 
    1483                 err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); 
     1510                err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, src); 
    14841511                break; 
    14851512            } 
    14861513        case ICMPV6_MLD2_REPORT: 
    static int br_multicast_ipv6_rcv(struct 
    14971524                        goto out; 
    14981525                } 
    14991526                mld = (struct mld_msg *)skb_transport_header(skb2); 
    1500                 br_ip6_multicast_leave_group(br, port, &mld->mld_mca); 
     1527                br_ip6_multicast_leave_group(br, port, &mld->mld_mca, src); 
    15011528            } 
    15021529        } 
    15031530 
  • net/bridge/br_private.h

    diff -Nrup a/net/bridge/br_private.h b/net/bridge/br_private.h
    a b struct net_bridge_port_group { 
    8383        struct rcu_head                 rcu; 
    8484        struct timer_list               timer; 
    8585        struct br_ip                    addr; 
     86 
     87        unsigned char                   eth_addr[ETH_ALEN]; 
     88        bool                            unicast; 
    8689}; 
    8790 
    8891struct net_bridge_mdb_entry 
    struct net_bridge_port 
    136139        unsigned long                   flags; 
    137140#define BR_HAIRPIN_MODE         0x00000001 
    138141#define BR_ISOLATE_MODE         0x00000002 
     142#define BR_MULTICAST_TO_UCAST   0x00000040 
    139143 
    140144#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 
    141145        u32                             multicast_startup_queries_sent; 
  • net/bridge/br_sysfs_if.c

    diff -Nrup a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
    a b struct brport_attribute brport_attr_##_n 
    3434        .store  = _store,                                       \ 
    3535}; 
    3636 
     37#define BRPORT_ATTR_FLAG(_name, _mask)                          \ 
     38static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \ 
     39{                                                               \ 
     40        return sprintf(buf, "%d\n", !!(p->flags & _mask));      \ 
     41}                                                               \ 
     42static int store_##_name(struct net_bridge_port *p, unsigned long v) \ 
     43{                                                               \ 
     44        unsigned long flags = p->flags;                         \ 
     45        if (v)                                                  \ 
     46                flags |= _mask;                                 \ 
     47        else                                                    \ 
     48                flags &= ~_mask;                                \ 
     49        if (flags != p->flags) {                                \ 
     50                p->flags = flags;                               \ 
     51                br_ifinfo_notify(RTM_NEWLINK, p);               \ 
     52        }                                                       \ 
     53        return 0;                                               \ 
     54}                                                               \ 
     55static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR,                    \ 
     56                   show_##_name, store_##_name) 
     57 
    3758static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) 
    3859{ 
    3960        return sprintf(buf, "%d\n", p->path_cost); 
    static int store_multicast_router(struct 
    178199} 
    179200static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, 
    180201                   store_multicast_router); 
     202BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UCAST); 
    181203#endif 
    182204 
    183205static struct brport_attribute *brport_attrs[] = { 
    static struct brport_attribute *brport_a 
    200222        &brport_attr_isolate_mode, 
    201223#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 
    202224        &brport_attr_multicast_router, 
     225        &brport_attr_multicast_to_unicast, 
    203226#endif 
    204227        NULL 
    205228};