Merge branch 'bridge-netlink'
authorDavid S. Miller <davem@davemloft.net>
Sun, 4 Oct 2015 23:46:14 +0000 (16:46 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 4 Oct 2015 23:46:14 +0000 (16:46 -0700)
Nikolay Aleksandrov says:

====================
bridge: complete netlink support

This set completes the bridge device's netlink support and makes it
possible to view and configure everything that can be configured via
sysfs. I have tested all of these (setting and getting). There're a few
longer line warnings about the br_get_size() ifla comments but I think we
should have them to know what has been accounted for. I have used the sysfs
interface as a guide of what and how to set. As usual I'll send the
corresponding iproute2 patches later.
The bridge port's netlink interface will be completed after this set gets
applied in some form.

This patch-set is on top of my last vlan cleanups set:
http://www.spinics.net/lists/netdev/msg346005.html
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/if_link.h
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_vlan.c

index 3a5f263cfc2ff9a5887195ebedd46de593c29cb3..c5b15bfeabe2196d0bd92a01e1356a6ab3a038e2 100644 (file)
@@ -232,11 +232,47 @@ enum {
        IFLA_BR_PRIORITY,
        IFLA_BR_VLAN_FILTERING,
        IFLA_BR_VLAN_PROTOCOL,
+       IFLA_BR_GROUP_FWD_MASK,
+       IFLA_BR_ROOT_ID,
+       IFLA_BR_BRIDGE_ID,
+       IFLA_BR_ROOT_PORT,
+       IFLA_BR_ROOT_PATH_COST,
+       IFLA_BR_TOPOLOGY_CHANGE,
+       IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
+       IFLA_BR_HELLO_TIMER,
+       IFLA_BR_TCN_TIMER,
+       IFLA_BR_TOPOLOGY_CHANGE_TIMER,
+       IFLA_BR_GC_TIMER,
+       IFLA_BR_GROUP_ADDR,
+       IFLA_BR_FDB_FLUSH,
+       IFLA_BR_MCAST_ROUTER,
+       IFLA_BR_MCAST_SNOOPING,
+       IFLA_BR_MCAST_QUERY_USE_IFADDR,
+       IFLA_BR_MCAST_QUERIER,
+       IFLA_BR_MCAST_HASH_ELASTICITY,
+       IFLA_BR_MCAST_HASH_MAX,
+       IFLA_BR_MCAST_LAST_MEMBER_CNT,
+       IFLA_BR_MCAST_STARTUP_QUERY_CNT,
+       IFLA_BR_MCAST_LAST_MEMBER_INTVL,
+       IFLA_BR_MCAST_MEMBERSHIP_INTVL,
+       IFLA_BR_MCAST_QUERIER_INTVL,
+       IFLA_BR_MCAST_QUERY_INTVL,
+       IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
+       IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
+       IFLA_BR_NF_CALL_IPTABLES,
+       IFLA_BR_NF_CALL_IP6TABLES,
+       IFLA_BR_NF_CALL_ARPTABLES,
+       IFLA_BR_VLAN_DEFAULT_PVID,
        __IFLA_BR_MAX,
 };
 
 #define IFLA_BR_MAX    (__IFLA_BR_MAX - 1)
 
+struct ifla_bridge_id {
+       __u8    prio[2];
+       __u8    addr[6]; /* ETH_ALEN */
+};
+
 enum {
        BRIDGE_MODE_UNSPEC,
        BRIDGE_MODE_HAIRPIN,
index c3186198d46dbb2d8515b60db621d97a6c4a058b..70efe2edde2bf77d25f3a585fdcce0ea51748cf1 100644 (file)
@@ -764,6 +764,27 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
        [IFLA_BR_PRIORITY] = { .type = NLA_U16 },
        [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 },
        [IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 },
+       [IFLA_BR_GROUP_FWD_MASK] = { .type = NLA_U16 },
+       [IFLA_BR_GROUP_ADDR] = { .type = NLA_BINARY,
+                                .len  = ETH_ALEN },
+       [IFLA_BR_MCAST_ROUTER] = { .type = NLA_U8 },
+       [IFLA_BR_MCAST_SNOOPING] = { .type = NLA_U8 },
+       [IFLA_BR_MCAST_QUERY_USE_IFADDR] = { .type = NLA_U8 },
+       [IFLA_BR_MCAST_QUERIER] = { .type = NLA_U8 },
+       [IFLA_BR_MCAST_HASH_ELASTICITY] = { .type = NLA_U32 },
+       [IFLA_BR_MCAST_HASH_MAX] = { .type = NLA_U32 },
+       [IFLA_BR_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 },
+       [IFLA_BR_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 },
+       [IFLA_BR_MCAST_LAST_MEMBER_INTVL] = { .type = NLA_U64 },
+       [IFLA_BR_MCAST_MEMBERSHIP_INTVL] = { .type = NLA_U64 },
+       [IFLA_BR_MCAST_QUERIER_INTVL] = { .type = NLA_U64 },
+       [IFLA_BR_MCAST_QUERY_INTVL] = { .type = NLA_U64 },
+       [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 },
+       [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 },
+       [IFLA_BR_NF_CALL_IPTABLES] = { .type = NLA_U8 },
+       [IFLA_BR_NF_CALL_IP6TABLES] = { .type = NLA_U8 },
+       [IFLA_BR_NF_CALL_ARPTABLES] = { .type = NLA_U8 },
+       [IFLA_BR_VLAN_DEFAULT_PVID] = { .type = NLA_U16 },
 };
 
 static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
@@ -827,6 +848,158 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
                if (err)
                        return err;
        }
+
+       if (data[IFLA_BR_VLAN_DEFAULT_PVID]) {
+               __u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]);
+
+               err = __br_vlan_set_default_pvid(br, defpvid);
+               if (err)
+                       return err;
+       }
+#endif
+
+       if (data[IFLA_BR_GROUP_FWD_MASK]) {
+               u16 fwd_mask = nla_get_u16(data[IFLA_BR_GROUP_FWD_MASK]);
+
+               if (fwd_mask & BR_GROUPFWD_RESTRICTED)
+                       return -EINVAL;
+               br->group_fwd_mask = fwd_mask;
+       }
+
+       if (data[IFLA_BR_GROUP_ADDR]) {
+               u8 new_addr[ETH_ALEN];
+
+               if (nla_len(data[IFLA_BR_GROUP_ADDR]) != ETH_ALEN)
+                       return -EINVAL;
+               memcpy(new_addr, nla_data(data[IFLA_BR_GROUP_ADDR]), ETH_ALEN);
+               if (!is_link_local_ether_addr(new_addr))
+                       return -EINVAL;
+               if (new_addr[5] == 1 ||         /* 802.3x Pause address */
+                   new_addr[5] == 2 ||         /* 802.3ad Slow protocols */
+                   new_addr[5] == 3)           /* 802.1X PAE address */
+                       return -EINVAL;
+               spin_lock_bh(&br->lock);
+               memcpy(br->group_addr, new_addr, sizeof(br->group_addr));
+               spin_unlock_bh(&br->lock);
+               br->group_addr_set = true;
+               br_recalculate_fwd_mask(br);
+       }
+
+       if (data[IFLA_BR_FDB_FLUSH])
+               br_fdb_flush(br);
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+       if (data[IFLA_BR_MCAST_ROUTER]) {
+               u8 multicast_router = nla_get_u8(data[IFLA_BR_MCAST_ROUTER]);
+
+               err = br_multicast_set_router(br, multicast_router);
+               if (err)
+                       return err;
+       }
+
+       if (data[IFLA_BR_MCAST_SNOOPING]) {
+               u8 mcast_snooping = nla_get_u8(data[IFLA_BR_MCAST_SNOOPING]);
+
+               err = br_multicast_toggle(br, mcast_snooping);
+               if (err)
+                       return err;
+       }
+
+       if (data[IFLA_BR_MCAST_QUERY_USE_IFADDR]) {
+               u8 val;
+
+               val = nla_get_u8(data[IFLA_BR_MCAST_QUERY_USE_IFADDR]);
+               br->multicast_query_use_ifaddr = !!val;
+       }
+
+       if (data[IFLA_BR_MCAST_QUERIER]) {
+               u8 mcast_querier = nla_get_u8(data[IFLA_BR_MCAST_QUERIER]);
+
+               err = br_multicast_set_querier(br, mcast_querier);
+               if (err)
+                       return err;
+       }
+
+       if (data[IFLA_BR_MCAST_HASH_ELASTICITY]) {
+               u32 val = nla_get_u32(data[IFLA_BR_MCAST_HASH_ELASTICITY]);
+
+               br->hash_elasticity = val;
+       }
+
+       if (data[IFLA_BR_MCAST_HASH_MAX]) {
+               u32 hash_max = nla_get_u32(data[IFLA_BR_MCAST_HASH_MAX]);
+
+               err = br_multicast_set_hash_max(br, hash_max);
+               if (err)
+                       return err;
+       }
+
+       if (data[IFLA_BR_MCAST_LAST_MEMBER_CNT]) {
+               u32 val = nla_get_u32(data[IFLA_BR_MCAST_LAST_MEMBER_CNT]);
+
+               br->multicast_last_member_count = val;
+       }
+
+       if (data[IFLA_BR_MCAST_STARTUP_QUERY_CNT]) {
+               u32 val = nla_get_u32(data[IFLA_BR_MCAST_STARTUP_QUERY_CNT]);
+
+               br->multicast_startup_query_count = val;
+       }
+
+       if (data[IFLA_BR_MCAST_LAST_MEMBER_INTVL]) {
+               u64 val = nla_get_u64(data[IFLA_BR_MCAST_LAST_MEMBER_INTVL]);
+
+               br->multicast_last_member_interval = clock_t_to_jiffies(val);
+       }
+
+       if (data[IFLA_BR_MCAST_MEMBERSHIP_INTVL]) {
+               u64 val = nla_get_u64(data[IFLA_BR_MCAST_MEMBERSHIP_INTVL]);
+
+               br->multicast_membership_interval = clock_t_to_jiffies(val);
+       }
+
+       if (data[IFLA_BR_MCAST_QUERIER_INTVL]) {
+               u64 val = nla_get_u64(data[IFLA_BR_MCAST_QUERIER_INTVL]);
+
+               br->multicast_querier_interval = clock_t_to_jiffies(val);
+       }
+
+       if (data[IFLA_BR_MCAST_QUERY_INTVL]) {
+               u64 val = nla_get_u64(data[IFLA_BR_MCAST_QUERY_INTVL]);
+
+               br->multicast_query_interval = clock_t_to_jiffies(val);
+       }
+
+       if (data[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) {
+               u64 val = nla_get_u64(data[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]);
+
+               br->multicast_query_response_interval = clock_t_to_jiffies(val);
+       }
+
+       if (data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) {
+               u64 val = nla_get_u64(data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]);
+
+               br->multicast_startup_query_interval = clock_t_to_jiffies(val);
+       }
+#endif
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+       if (data[IFLA_BR_NF_CALL_IPTABLES]) {
+               u8 val = nla_get_u8(data[IFLA_BR_NF_CALL_IPTABLES]);
+
+               br->nf_call_iptables = val ? true : false;
+       }
+
+       if (data[IFLA_BR_NF_CALL_IP6TABLES]) {
+               u8 val = nla_get_u8(data[IFLA_BR_NF_CALL_IP6TABLES]);
+
+               br->nf_call_ip6tables = val ? true : false;
+       }
+
+       if (data[IFLA_BR_NF_CALL_ARPTABLES]) {
+               u8 val = nla_get_u8(data[IFLA_BR_NF_CALL_ARPTABLES]);
+
+               br->nf_call_arptables = val ? true : false;
+       }
 #endif
 
        return 0;
@@ -843,6 +1016,40 @@ static size_t br_get_size(const struct net_device *brdev)
               nla_total_size(sizeof(u8)) +     /* IFLA_BR_VLAN_FILTERING */
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
               nla_total_size(sizeof(__be16)) + /* IFLA_BR_VLAN_PROTOCOL */
+              nla_total_size(sizeof(u16)) +    /* IFLA_BR_VLAN_DEFAULT_PVID */
+#endif
+              nla_total_size(sizeof(u16)) +    /* IFLA_BR_GROUP_FWD_MASK */
+              nla_total_size(sizeof(struct ifla_bridge_id)) +   /* IFLA_BR_ROOT_ID */
+              nla_total_size(sizeof(struct ifla_bridge_id)) +   /* IFLA_BR_BRIDGE_ID */
+              nla_total_size(sizeof(u16)) +    /* IFLA_BR_ROOT_PORT */
+              nla_total_size(sizeof(u32)) +    /* IFLA_BR_ROOT_PATH_COST */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_TOPOLOGY_CHANGE */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_TOPOLOGY_CHANGE_DETECTED */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_HELLO_TIMER */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_TCN_TIMER */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_TOPOLOGY_CHANGE_TIMER */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_GC_TIMER */
+              nla_total_size(ETH_ALEN) +       /* IFLA_BR_GROUP_ADDR */
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_MCAST_ROUTER */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_MCAST_SNOOPING */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_MCAST_QUERY_USE_IFADDR */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_MCAST_QUERIER */
+              nla_total_size(sizeof(u32)) +    /* IFLA_BR_MCAST_HASH_ELASTICITY */
+              nla_total_size(sizeof(u32)) +    /* IFLA_BR_MCAST_HASH_MAX */
+              nla_total_size(sizeof(u32)) +    /* IFLA_BR_MCAST_LAST_MEMBER_CNT */
+              nla_total_size(sizeof(u32)) +    /* IFLA_BR_MCAST_STARTUP_QUERY_CNT */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_MCAST_LAST_MEMBER_INTVL */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_MCAST_MEMBERSHIP_INTVL */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_MCAST_QUERIER_INTVL */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_MCAST_QUERY_INTVL */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_MCAST_QUERY_RESPONSE_INTVL */
+              nla_total_size(sizeof(u64)) +    /* IFLA_BR_MCAST_STARTUP_QUERY_INTVL */
+#endif
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_IPTABLES */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_IP6TABLES */
+              nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_ARPTABLES */
 #endif
               0;
 }
@@ -850,13 +1057,28 @@ static size_t br_get_size(const struct net_device *brdev)
 static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
 {
        struct net_bridge *br = netdev_priv(brdev);
+       u64 hello_timer, tcn_timer, topology_change_timer, gc_timer, clockval;
        u32 forward_delay = jiffies_to_clock_t(br->forward_delay);
        u32 hello_time = jiffies_to_clock_t(br->hello_time);
        u32 age_time = jiffies_to_clock_t(br->max_age);
        u32 ageing_time = jiffies_to_clock_t(br->ageing_time);
        u32 stp_enabled = br->stp_enabled;
        u16 priority = (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1];
+       u16 group_fwd_mask = br->group_fwd_mask;
        u8 vlan_enabled = br_vlan_enabled(br);
+       struct ifla_bridge_id root_id, bridge_id;
+
+       memset(&bridge_id, 0, sizeof(bridge_id));
+       memset(&root_id, 0, sizeof(root_id));
+       memcpy(root_id.prio, br->designated_root.prio, sizeof(root_id.prio));
+       memcpy(root_id.addr, br->designated_root.addr, sizeof(root_id.addr));
+       memcpy(bridge_id.prio, br->bridge_id.prio, sizeof(bridge_id.prio));
+       memcpy(bridge_id.addr, br->bridge_id.addr, sizeof(bridge_id.addr));
+       hello_timer = br_timer_value(&br->hello_timer);
+       tcn_timer = br_timer_value(&br->tcn_timer);
+       topology_change_timer = br_timer_value(&br->topology_change_timer);
+       gc_timer = br_timer_value(&br->gc_timer);
+       clockval = 0;
 
        if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) ||
            nla_put_u32(skb, IFLA_BR_HELLO_TIME, hello_time) ||
@@ -864,11 +1086,69 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
            nla_put_u32(skb, IFLA_BR_AGEING_TIME, ageing_time) ||
            nla_put_u32(skb, IFLA_BR_STP_STATE, stp_enabled) ||
            nla_put_u16(skb, IFLA_BR_PRIORITY, priority) ||
-           nla_put_u8(skb, IFLA_BR_VLAN_FILTERING, vlan_enabled))
+           nla_put_u8(skb, IFLA_BR_VLAN_FILTERING, vlan_enabled) ||
+           nla_put_u16(skb, IFLA_BR_GROUP_FWD_MASK, group_fwd_mask) ||
+           nla_put(skb, IFLA_BR_ROOT_ID, sizeof(root_id), &root_id) ||
+           nla_put(skb, IFLA_BR_BRIDGE_ID, sizeof(bridge_id), &bridge_id) ||
+           nla_put_u16(skb, IFLA_BR_ROOT_PORT, br->root_port) ||
+           nla_put_u32(skb, IFLA_BR_ROOT_PATH_COST, br->root_path_cost) ||
+           nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE, br->topology_change) ||
+           nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
+                      br->topology_change_detected) ||
+           nla_put_u64(skb, IFLA_BR_HELLO_TIMER, hello_timer) ||
+           nla_put_u64(skb, IFLA_BR_TCN_TIMER, tcn_timer) ||
+           nla_put_u64(skb, IFLA_BR_TOPOLOGY_CHANGE_TIMER,
+                       topology_change_timer) ||
+           nla_put_u64(skb, IFLA_BR_GC_TIMER, gc_timer) ||
+           nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr))
                return -EMSGSIZE;
 
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
-       if (nla_put_be16(skb, IFLA_BR_VLAN_PROTOCOL, br->vlan_proto))
+       if (nla_put_be16(skb, IFLA_BR_VLAN_PROTOCOL, br->vlan_proto) ||
+           nla_put_u16(skb, IFLA_BR_VLAN_DEFAULT_PVID, br->default_pvid))
+               return -EMSGSIZE;
+#endif
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+       if (nla_put_u8(skb, IFLA_BR_MCAST_ROUTER, br->multicast_router) ||
+           nla_put_u8(skb, IFLA_BR_MCAST_SNOOPING, !br->multicast_disabled) ||
+           nla_put_u8(skb, IFLA_BR_MCAST_QUERY_USE_IFADDR,
+                      br->multicast_query_use_ifaddr) ||
+           nla_put_u8(skb, IFLA_BR_MCAST_QUERIER, br->multicast_querier) ||
+           nla_put_u32(skb, IFLA_BR_MCAST_HASH_ELASTICITY,
+                       br->hash_elasticity) ||
+           nla_put_u32(skb, IFLA_BR_MCAST_HASH_MAX, br->hash_max) ||
+           nla_put_u32(skb, IFLA_BR_MCAST_LAST_MEMBER_CNT,
+                       br->multicast_last_member_count) ||
+           nla_put_u32(skb, IFLA_BR_MCAST_STARTUP_QUERY_CNT,
+                       br->multicast_startup_query_count))
+               return -EMSGSIZE;
+
+       clockval = jiffies_to_clock_t(br->multicast_last_member_interval);
+       if (nla_put_u64(skb, IFLA_BR_MCAST_LAST_MEMBER_INTVL, clockval))
+               return -EMSGSIZE;
+       clockval = jiffies_to_clock_t(br->multicast_membership_interval);
+       if (nla_put_u64(skb, IFLA_BR_MCAST_MEMBERSHIP_INTVL, clockval))
+               return -EMSGSIZE;
+       clockval = jiffies_to_clock_t(br->multicast_querier_interval);
+       if (nla_put_u64(skb, IFLA_BR_MCAST_QUERIER_INTVL, clockval))
+               return -EMSGSIZE;
+       clockval = jiffies_to_clock_t(br->multicast_query_interval);
+       if (nla_put_u64(skb, IFLA_BR_MCAST_QUERY_INTVL, clockval))
+               return -EMSGSIZE;
+       clockval = jiffies_to_clock_t(br->multicast_query_response_interval);
+       if (nla_put_u64(skb, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, clockval))
+               return -EMSGSIZE;
+       clockval = jiffies_to_clock_t(br->multicast_startup_query_interval);
+       if (nla_put_u64(skb, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, clockval))
+               return -EMSGSIZE;
+#endif
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+       if (nla_put_u8(skb, IFLA_BR_NF_CALL_IPTABLES,
+                      br->nf_call_iptables ? 1 : 0) ||
+           nla_put_u8(skb, IFLA_BR_NF_CALL_IP6TABLES,
+                      br->nf_call_ip6tables ? 1 : 0) ||
+           nla_put_u8(skb, IFLA_BR_NF_CALL_ARPTABLES,
+                      br->nf_call_arptables ? 1 : 0))
                return -EMSGSIZE;
 #endif
 
index 1ff6a0faef3f0626cfa7073a9f66f39c91de68bf..09d3ecbcb4f02046430788e4c885aa49acbeb219 100644 (file)
@@ -690,6 +690,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto);
 int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
 int br_vlan_init(struct net_bridge *br);
 int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
+int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid);
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
 void nbp_vlan_flush(struct net_bridge_port *port);
index b879111582f0d6aaf9531c1713eadae5aa0541fa..eae07ee9bfe00c9661f7e227e72d083ca3dcbc19 100644 (file)
@@ -727,7 +727,7 @@ static void br_vlan_disable_default_pvid(struct net_bridge *br)
        br->default_pvid = 0;
 }
 
-static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
+int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
 {
        const struct net_bridge_vlan *pvent;
        struct net_bridge_port *p;
@@ -735,6 +735,11 @@ static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
        int err = 0;
        unsigned long *changed;
 
+       if (!pvid) {
+               br_vlan_disable_default_pvid(br);
+               return 0;
+       }
+
        changed = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long),
                          GFP_KERNEL);
        if (!changed)
@@ -825,12 +830,7 @@ int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
                err = -EPERM;
                goto unlock;
        }
-
-       if (!pvid)
-               br_vlan_disable_default_pvid(br);
-       else
-               err = __br_vlan_set_default_pvid(br, pvid);
-
+       err = __br_vlan_set_default_pvid(br, pvid);
 unlock:
        rtnl_unlock();
        return err;
This page took 0.038461 seconds and 5 git commands to generate.