]> Pileus Git - ~andy/linux/blobdiff - net/bridge/br_netlink.c
bridge: Add a flag to control unicast packet flood.
[~andy/linux] / net / bridge / br_netlink.c
index 299fc5f40a26c12ef39786d8bc3885c0c96ca7be..1fc30abd3a523912376ce01fcae932f3b6b8c746 100644 (file)
@@ -30,6 +30,8 @@ static inline size_t br_port_info_size(void)
                + nla_total_size(1)     /* IFLA_BRPORT_GUARD */
                + nla_total_size(1)     /* IFLA_BRPORT_PROTECT */
                + nla_total_size(1)     /* IFLA_BRPORT_FAST_LEAVE */
+               + nla_total_size(1)     /* IFLA_BRPORT_LEARNING */
+               + nla_total_size(1)     /* IFLA_BRPORT_UNICAST_FLOOD */
                + 0;
 }
 
@@ -56,7 +58,9 @@ static int br_port_fill_attrs(struct sk_buff *skb,
            nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
            nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
            nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) ||
-           nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)))
+           nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
+           nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
+           nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, !!(p->flags & BR_FLOOD)))
                return -EMSGSIZE;
 
        return 0;
@@ -136,10 +140,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
 
                pvid = br_get_pvid(pv);
-               for (vid = find_first_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN);
-                    vid < BR_VLAN_BITMAP_LEN;
-                    vid = find_next_bit(pv->vlan_bitmap,
-                                        BR_VLAN_BITMAP_LEN, vid+1)) {
+               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
                        vinfo.vid = vid;
                        vinfo.flags = 0;
                        if (vid == pvid)
@@ -284,6 +285,8 @@ static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
        [IFLA_BRPORT_MODE]      = { .type = NLA_U8 },
        [IFLA_BRPORT_GUARD]     = { .type = NLA_U8 },
        [IFLA_BRPORT_PROTECT]   = { .type = NLA_U8 },
+       [IFLA_BRPORT_LEARNING]  = { .type = NLA_U8 },
+       [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
 };
 
 /* Change the state of the port and notify spanning tree */
@@ -331,6 +334,8 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
        br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
        br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
        br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
+       br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
+       br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
 
        if (tb[IFLA_BRPORT_COST]) {
                err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
@@ -355,17 +360,14 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
 /* Change state and parameters on port. */
 int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 {
-       struct ifinfomsg *ifm;
        struct nlattr *protinfo;
        struct nlattr *afspec;
        struct net_bridge_port *p;
        struct nlattr *tb[IFLA_BRPORT_MAX + 1];
-       int err;
-
-       ifm = nlmsg_data(nlh);
+       int err = 0;
 
-       protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
-       afspec = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_AF_SPEC);
+       protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
+       afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
        if (!protinfo && !afspec)
                return 0;
 
@@ -373,7 +375,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
        /* We want to accept dev as bridge itself if the AF_SPEC
         * is set to see if someone is setting vlan info on the brigde
         */
-       if (!p && ((dev->priv_flags & IFF_EBRIDGE) && !afspec))
+       if (!p && !afspec)
                return -EINVAL;
 
        if (p && protinfo) {
@@ -414,14 +416,11 @@ out:
 /* Delete port information */
 int br_dellink(struct net_device *dev, struct nlmsghdr *nlh)
 {
-       struct ifinfomsg *ifm;
        struct nlattr *afspec;
        struct net_bridge_port *p;
        int err;
 
-       ifm = nlmsg_data(nlh);
-
-       afspec = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_AF_SPEC);
+       afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
        if (!afspec)
                return 0;