]> Pileus Git - ~andy/linux/blob - net/bridge/br_vlan.c
bridge: Dump vlan information from a bridge port
[~andy/linux] / net / bridge / br_vlan.c
1 #include <linux/kernel.h>
2 #include <linux/netdevice.h>
3 #include <linux/rtnetlink.h>
4 #include <linux/slab.h>
5
6 #include "br_private.h"
7
8 static int __vlan_add(struct net_port_vlans *v, u16 vid)
9 {
10         int err;
11
12         if (test_bit(vid, v->vlan_bitmap))
13                 return -EEXIST;
14
15         if (v->port_idx && vid) {
16                 struct net_device *dev = v->parent.port->dev;
17
18                 /* Add VLAN to the device filter if it is supported.
19                  * Stricly speaking, this is not necessary now, since devices
20                  * are made promiscuous by the bridge, but if that ever changes
21                  * this code will allow tagged traffic to enter the bridge.
22                  */
23                 if (dev->features & NETIF_F_HW_VLAN_FILTER) {
24                         err = dev->netdev_ops->ndo_vlan_rx_add_vid(dev, vid);
25                         if (err)
26                                 return err;
27                 }
28         }
29
30         set_bit(vid, v->vlan_bitmap);
31         v->num_vlans++;
32         return 0;
33 }
34
35 static int __vlan_del(struct net_port_vlans *v, u16 vid)
36 {
37         if (!test_bit(vid, v->vlan_bitmap))
38                 return -EINVAL;
39
40         if (v->port_idx && vid) {
41                 struct net_device *dev = v->parent.port->dev;
42
43                 if (dev->features & NETIF_F_HW_VLAN_FILTER)
44                         dev->netdev_ops->ndo_vlan_rx_kill_vid(dev, vid);
45         }
46
47         clear_bit(vid, v->vlan_bitmap);
48         v->num_vlans--;
49         if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
50                 if (v->port_idx)
51                         rcu_assign_pointer(v->parent.port->vlan_info, NULL);
52                 else
53                         rcu_assign_pointer(v->parent.br->vlan_info, NULL);
54                 kfree_rcu(v, rcu);
55         }
56         return 0;
57 }
58
59 static void __vlan_flush(struct net_port_vlans *v)
60 {
61         bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
62         if (v->port_idx)
63                 rcu_assign_pointer(v->parent.port->vlan_info, NULL);
64         else
65                 rcu_assign_pointer(v->parent.br->vlan_info, NULL);
66         kfree_rcu(v, rcu);
67 }
68
69 /* Called under RCU */
70 bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
71                         struct sk_buff *skb)
72 {
73         u16 vid;
74
75         /* If VLAN filtering is disabled on the bridge, all packets are
76          * permitted.
77          */
78         if (!br->vlan_enabled)
79                 return true;
80
81         /* If there are no vlan in the permitted list, all packets are
82          * rejected.
83          */
84         if (!v)
85                 return false;
86
87         br_vlan_get_tag(skb, &vid);
88         if (test_bit(vid, v->vlan_bitmap))
89                 return true;
90
91         return false;
92 }
93
94 /* Called under RCU. */
95 bool br_allowed_egress(struct net_bridge *br,
96                        const struct net_port_vlans *v,
97                        const struct sk_buff *skb)
98 {
99         u16 vid;
100
101         if (!br->vlan_enabled)
102                 return true;
103
104         if (!v)
105                 return false;
106
107         br_vlan_get_tag(skb, &vid);
108         if (test_bit(vid, v->vlan_bitmap))
109                 return true;
110
111         return false;
112 }
113
114 /* Must be protected by RTNL */
115 int br_vlan_add(struct net_bridge *br, u16 vid)
116 {
117         struct net_port_vlans *pv = NULL;
118         int err;
119
120         ASSERT_RTNL();
121
122         pv = rtnl_dereference(br->vlan_info);
123         if (pv)
124                 return __vlan_add(pv, vid);
125
126         /* Create port vlan infomration
127          */
128         pv = kzalloc(sizeof(*pv), GFP_KERNEL);
129         if (!pv)
130                 return -ENOMEM;
131
132         pv->parent.br = br;
133         err = __vlan_add(pv, vid);
134         if (err)
135                 goto out;
136
137         rcu_assign_pointer(br->vlan_info, pv);
138         return 0;
139 out:
140         kfree(pv);
141         return err;
142 }
143
144 /* Must be protected by RTNL */
145 int br_vlan_delete(struct net_bridge *br, u16 vid)
146 {
147         struct net_port_vlans *pv;
148
149         ASSERT_RTNL();
150
151         pv = rtnl_dereference(br->vlan_info);
152         if (!pv)
153                 return -EINVAL;
154
155         __vlan_del(pv, vid);
156         return 0;
157 }
158
159 void br_vlan_flush(struct net_bridge *br)
160 {
161         struct net_port_vlans *pv;
162
163         ASSERT_RTNL();
164
165         pv = rtnl_dereference(br->vlan_info);
166         if (!pv)
167                 return;
168
169         __vlan_flush(pv);
170 }
171
172 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
173 {
174         if (!rtnl_trylock())
175                 return restart_syscall();
176
177         if (br->vlan_enabled == val)
178                 goto unlock;
179
180         br->vlan_enabled = val;
181
182 unlock:
183         rtnl_unlock();
184         return 0;
185 }
186
187 /* Must be protected by RTNL */
188 int nbp_vlan_add(struct net_bridge_port *port, u16 vid)
189 {
190         struct net_port_vlans *pv = NULL;
191         int err;
192
193         ASSERT_RTNL();
194
195         pv = rtnl_dereference(port->vlan_info);
196         if (pv)
197                 return __vlan_add(pv, vid);
198
199         /* Create port vlan infomration
200          */
201         pv = kzalloc(sizeof(*pv), GFP_KERNEL);
202         if (!pv) {
203                 err = -ENOMEM;
204                 goto clean_up;
205         }
206
207         pv->port_idx = port->port_no;
208         pv->parent.port = port;
209         err = __vlan_add(pv, vid);
210         if (err)
211                 goto clean_up;
212
213         rcu_assign_pointer(port->vlan_info, pv);
214         return 0;
215
216 clean_up:
217         kfree(pv);
218         return err;
219 }
220
221 /* Must be protected by RTNL */
222 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
223 {
224         struct net_port_vlans *pv;
225
226         ASSERT_RTNL();
227
228         pv = rtnl_dereference(port->vlan_info);
229         if (!pv)
230                 return -EINVAL;
231
232         return __vlan_del(pv, vid);
233 }
234
235 void nbp_vlan_flush(struct net_bridge_port *port)
236 {
237         struct net_port_vlans *pv;
238
239         ASSERT_RTNL();
240
241         pv = rtnl_dereference(port->vlan_info);
242         if (!pv)
243                 return;
244
245         __vlan_flush(pv);
246 }