aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2013-02-13 07:00:13 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-13 19:41:46 -0500
commit6cbdceeb1cb12c7d620161925a8c3e81daadb2e4 (patch)
tree81852fee23a380456cce4d2c1bb5ec52c7ff0013
parent407af3299ef1ac7e87ce3fb530e32a009d1a9efd (diff)
bridge: Dump vlan information from a bridge port
Using the RTM_GETLINK dump the vlan filter list of a given bridge port. The information depends on setting the filter flag similar to how nic VF info is dumped. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c3
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--include/uapi/linux/rtnetlink.h1
-rw-r--r--net/bridge/br_netlink.c94
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/bridge/br_vlan.c2
-rw-r--r--net/core/rtnetlink.c16
7 files changed, 104 insertions, 18 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 6999269b3a4a..4e2aa47193cb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7079,7 +7079,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
7079} 7079}
7080 7080
7081static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 7081static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
7082 struct net_device *dev) 7082 struct net_device *dev,
7083 u32 filter_mask)
7083{ 7084{
7084 struct ixgbe_adapter *adapter = netdev_priv(dev); 7085 struct ixgbe_adapter *adapter = netdev_priv(dev);
7085 u16 mode; 7086 u16 mode;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1b90f9401000..1964ca66df56 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1019,7 +1019,8 @@ struct net_device_ops {
1019 struct nlmsghdr *nlh); 1019 struct nlmsghdr *nlh);
1020 int (*ndo_bridge_getlink)(struct sk_buff *skb, 1020 int (*ndo_bridge_getlink)(struct sk_buff *skb,
1021 u32 pid, u32 seq, 1021 u32 pid, u32 seq,
1022 struct net_device *dev); 1022 struct net_device *dev,
1023 u32 filter_mask);
1023 int (*ndo_bridge_dellink)(struct net_device *dev, 1024 int (*ndo_bridge_dellink)(struct net_device *dev,
1024 struct nlmsghdr *nlh); 1025 struct nlmsghdr *nlh);
1025 int (*ndo_change_carrier)(struct net_device *dev, 1026 int (*ndo_change_carrier)(struct net_device *dev,
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 7a5eb196ade9..7a2144e1afae 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -630,6 +630,7 @@ struct tcamsg {
630 630
631/* New extended info filters for IFLA_EXT_MASK */ 631/* New extended info filters for IFLA_EXT_MASK */
632#define RTEXT_FILTER_VF (1 << 0) 632#define RTEXT_FILTER_VF (1 << 0)
633#define RTEXT_FILTER_BRVLAN (1 << 1)
633 634
634/* End of information exported to user level */ 635/* End of information exported to user level */
635 636
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 534a9f4587a9..fe1980d5a7e4 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -65,15 +65,21 @@ static int br_port_fill_attrs(struct sk_buff *skb,
65 * Create one netlink message for one interface 65 * Create one netlink message for one interface
66 * Contains port and master info as well as carrier and bridge state. 66 * Contains port and master info as well as carrier and bridge state.
67 */ 67 */
68static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port, 68static int br_fill_ifinfo(struct sk_buff *skb,
69 u32 pid, u32 seq, int event, unsigned int flags) 69 const struct net_bridge_port *port,
70 u32 pid, u32 seq, int event, unsigned int flags,
71 u32 filter_mask, const struct net_device *dev)
70{ 72{
71 const struct net_bridge *br = port->br; 73 const struct net_bridge *br;
72 const struct net_device *dev = port->dev;
73 struct ifinfomsg *hdr; 74 struct ifinfomsg *hdr;
74 struct nlmsghdr *nlh; 75 struct nlmsghdr *nlh;
75 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; 76 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
76 77
78 if (port)
79 br = port->br;
80 else
81 br = netdev_priv(dev);
82
77 br_debug(br, "br_fill_info event %d port %s master %s\n", 83 br_debug(br, "br_fill_info event %d port %s master %s\n",
78 event, dev->name, br->dev->name); 84 event, dev->name, br->dev->name);
79 85
@@ -99,7 +105,7 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
99 nla_put_u32(skb, IFLA_LINK, dev->iflink))) 105 nla_put_u32(skb, IFLA_LINK, dev->iflink)))
100 goto nla_put_failure; 106 goto nla_put_failure;
101 107
102 if (event == RTM_NEWLINK) { 108 if (event == RTM_NEWLINK && port) {
103 struct nlattr *nest 109 struct nlattr *nest
104 = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED); 110 = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
105 111
@@ -108,6 +114,40 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
108 nla_nest_end(skb, nest); 114 nla_nest_end(skb, nest);
109 } 115 }
110 116
117 /* Check if the VID information is requested */
118 if (filter_mask & RTEXT_FILTER_BRVLAN) {
119 struct nlattr *af;
120 const struct net_port_vlans *pv;
121 struct bridge_vlan_info vinfo;
122 u16 vid;
123
124 if (port)
125 pv = nbp_get_vlan_info(port);
126 else
127 pv = br_get_vlan_info(br);
128
129 if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN))
130 goto done;
131
132 af = nla_nest_start(skb, IFLA_AF_SPEC);
133 if (!af)
134 goto nla_put_failure;
135
136 for (vid = find_first_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN);
137 vid < BR_VLAN_BITMAP_LEN;
138 vid = find_next_bit(pv->vlan_bitmap,
139 BR_VLAN_BITMAP_LEN, vid+1)) {
140 vinfo.vid = vid;
141 vinfo.flags = 0;
142 if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
143 sizeof(vinfo), &vinfo))
144 goto nla_put_failure;
145 }
146
147 nla_nest_end(skb, af);
148 }
149
150done:
111 return nlmsg_end(skb, nlh); 151 return nlmsg_end(skb, nlh);
112 152
113nla_put_failure: 153nla_put_failure:
@@ -135,7 +175,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port)
135 if (skb == NULL) 175 if (skb == NULL)
136 goto errout; 176 goto errout;
137 177
138 err = br_fill_ifinfo(skb, port, 0, 0, event, 0); 178 err = br_fill_ifinfo(skb, port, 0, 0, event, 0, 0, port->dev);
139 if (err < 0) { 179 if (err < 0) {
140 /* -EMSGSIZE implies BUG in br_nlmsg_size() */ 180 /* -EMSGSIZE implies BUG in br_nlmsg_size() */
141 WARN_ON(err == -EMSGSIZE); 181 WARN_ON(err == -EMSGSIZE);
@@ -154,16 +194,17 @@ errout:
154 * Dump information about all ports, in response to GETLINK 194 * Dump information about all ports, in response to GETLINK
155 */ 195 */
156int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, 196int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
157 struct net_device *dev) 197 struct net_device *dev, u32 filter_mask)
158{ 198{
159 int err = 0; 199 int err = 0;
160 struct net_bridge_port *port = br_port_get_rcu(dev); 200 struct net_bridge_port *port = br_port_get_rcu(dev);
161 201
162 /* not a bridge port */ 202 /* not a bridge port and */
163 if (!port) 203 if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN))
164 goto out; 204 goto out;
165 205
166 err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI); 206 err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI,
207 filter_mask, dev);
167out: 208out:
168 return err; 209 return err;
169} 210}
@@ -395,6 +436,29 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
395 return 0; 436 return 0;
396} 437}
397 438
439static size_t br_get_link_af_size(const struct net_device *dev)
440{
441 struct net_port_vlans *pv;
442
443 if (br_port_exists(dev))
444 pv = nbp_get_vlan_info(br_port_get_rcu(dev));
445 else if (dev->priv_flags & IFF_EBRIDGE)
446 pv = br_get_vlan_info((struct net_bridge *)netdev_priv(dev));
447 else
448 return 0;
449
450 if (!pv)
451 return 0;
452
453 /* Each VLAN is returned in bridge_vlan_info along with flags */
454 return pv->num_vlans * nla_total_size(sizeof(struct bridge_vlan_info));
455}
456
457struct rtnl_af_ops br_af_ops = {
458 .family = AF_BRIDGE,
459 .get_link_af_size = br_get_link_af_size,
460};
461
398struct rtnl_link_ops br_link_ops __read_mostly = { 462struct rtnl_link_ops br_link_ops __read_mostly = {
399 .kind = "bridge", 463 .kind = "bridge",
400 .priv_size = sizeof(struct net_bridge),