1 From 36cd0ffbab8a65f44ae13fb200bfb5a8f9ea68de Mon Sep 17 00:00:00 2001
2 From: Roopa Prabhu <roopa@cumulusnetworks.com>
3 Date: Sat, 10 Jan 2015 07:31:14 -0800
4 Subject: bridge: new function to pack vlans into ranges during gets
6 This patch adds new function to pack vlans into ranges
7 whereever applicable using the flags BRIDGE_VLAN_INFO_RANGE_BEGIN
8 and BRIDGE VLAN_INFO_RANGE_END
10 Old vlan packing code is moved to a new function and continues to be
11 called when filter_mask is RTEXT_FILTER_BRVLAN.
13 Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
16 diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
17 index 6f616a2..0b03879 100644
18 --- a/net/bridge/br_netlink.c
19 +++ b/net/bridge/br_netlink.c
20 @@ -67,6 +67,118 @@ static int br_port_fill_attrs(struct sk_buff *skb,
24 +static int br_fill_ifvlaninfo_range(struct sk_buff *skb, u16 vid_start,
25 + u16 vid_end, u16 flags)
27 + struct bridge_vlan_info vinfo;
29 + if ((vid_end - vid_start) > 0) {
30 + /* add range to skb */
31 + vinfo.vid = vid_start;
32 + vinfo.flags = flags | BRIDGE_VLAN_INFO_RANGE_BEGIN;
33 + if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
34 + sizeof(vinfo), &vinfo))
35 + goto nla_put_failure;
37 + vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
39 + vinfo.vid = vid_end;
40 + vinfo.flags = flags | BRIDGE_VLAN_INFO_RANGE_END;
41 + if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
42 + sizeof(vinfo), &vinfo))
43 + goto nla_put_failure;
45 + vinfo.vid = vid_start;
46 + vinfo.flags = flags;
47 + if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
48 + sizeof(vinfo), &vinfo))
49 + goto nla_put_failure;
58 +static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
59 + const struct net_port_vlans *pv)
61 + u16 vid_range_start = 0, vid_range_end = 0;
62 + u16 vid_range_flags;
63 + u16 pvid, vid, flags;
66 + /* Pack IFLA_BRIDGE_VLAN_INFO's for every vlan
67 + * and mark vlan info with begin and end flags
68 + * if vlaninfo represents a range
70 + pvid = br_get_pvid(pv);
71 + for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
74 + flags |= BRIDGE_VLAN_INFO_PVID;
76 + if (test_bit(vid, pv->untagged_bitmap))
77 + flags |= BRIDGE_VLAN_INFO_UNTAGGED;
79 + if (vid_range_start == 0) {
81 + } else if ((vid - vid_range_end) == 1 &&
82 + flags == vid_range_flags) {
83 + vid_range_end = vid;
86 + err = br_fill_ifvlaninfo_range(skb, vid_range_start,
94 + vid_range_start = vid;
95 + vid_range_end = vid;
96 + vid_range_flags = flags;
99 + /* Call it once more to send any left over vlans */
100 + err = br_fill_ifvlaninfo_range(skb, vid_range_start,
109 +static int br_fill_ifvlaninfo(struct sk_buff *skb,
110 + const struct net_port_vlans *pv)
112 + struct bridge_vlan_info vinfo;
115 + pvid = br_get_pvid(pv);
116 + for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
120 + vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
122 + if (test_bit(vid, pv->untagged_bitmap))
123 + vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
125 + if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
126 + sizeof(vinfo), &vinfo))
127 + goto nla_put_failure;
137 * Create one netlink message for one interface
138 * Contains port and master info as well as carrier and bridge state.
139 @@ -121,12 +233,11 @@ static int br_fill_ifinfo(struct sk_buff *skb,
142 /* Check if the VID information is requested */
143 - if (filter_mask & RTEXT_FILTER_BRVLAN) {
145 + if ((filter_mask & RTEXT_FILTER_BRVLAN) ||
146 + (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
147 const struct net_port_vlans *pv;
148 - struct bridge_vlan_info vinfo;
155 pv = nbp_get_vlan_info(port);
156 @@ -140,21 +251,12 @@ static int br_fill_ifinfo(struct sk_buff *skb,
158 goto nla_put_failure;
160 - pvid = br_get_pvid(pv);
161 - for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
165 - vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
167 - if (test_bit(vid, pv->untagged_bitmap))
168 - vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
170 - if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
171 - sizeof(vinfo), &vinfo))
172 - goto nla_put_failure;
175 + if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
176 + err = br_fill_ifvlaninfo_compressed(skb, pv);
178 + err = br_fill_ifvlaninfo(skb, pv);
180 + goto nla_put_failure;
181 nla_nest_end(skb, af);
184 @@ -209,7 +311,8 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
186 struct net_bridge_port *port = br_port_get_rtnl(dev);
188 - if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN))
189 + if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN) &&
190 + !(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED))
193 err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI,