]> Pileus Git - ~andy/linux/blob - net/bridge/br_vlan.c
bridge: Fix handling stacked vlan tags
[~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 void __vlan_add_pvid(struct net_port_vlans *v, u16 vid)
9 {
10         if (v->pvid == vid)
11                 return;
12
13         smp_wmb();
14         v->pvid = vid;
15 }
16
17 static void __vlan_delete_pvid(struct net_port_vlans *v, u16 vid)
18 {
19         if (v->pvid != vid)
20                 return;
21
22         smp_wmb();
23         v->pvid = 0;
24 }
25
26 static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags)
27 {
28         if (flags & BRIDGE_VLAN_INFO_PVID)
29                 __vlan_add_pvid(v, vid);
30
31         if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
32                 set_bit(vid, v->untagged_bitmap);
33 }
34
35 static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
36 {
37         struct net_bridge_port *p = NULL;
38         struct net_bridge *br;
39         struct net_device *dev;
40         int err;
41
42         if (test_bit(vid, v->vlan_bitmap)) {
43                 __vlan_add_flags(v, vid, flags);
44                 return 0;
45         }
46
47         if (v->port_idx) {
48                 p = v->parent.port;
49                 br = p->br;
50                 dev = p->dev;
51         } else {
52                 br = v->parent.br;
53                 dev = br->dev;
54         }
55
56         if (p) {
57                 /* Add VLAN to the device filter if it is supported.
58                  * Stricly speaking, this is not necessary now, since
59                  * devices are made promiscuous by the bridge, but if
60                  * that ever changes this code will allow tagged
61                  * traffic to enter the bridge.
62                  */
63                 err = vlan_vid_add(dev, htons(ETH_P_8021Q), vid);
64                 if (err)
65                         return err;
66         }
67
68         err = br_fdb_insert(br, p, dev->dev_addr, vid);
69         if (err) {
70                 br_err(br, "failed insert local address into bridge "
71                        "forwarding table\n");
72                 goto out_filt;
73         }
74
75         set_bit(vid, v->vlan_bitmap);
76         v->num_vlans++;
77         __vlan_add_flags(v, vid, flags);
78
79         return 0;
80
81 out_filt:
82         if (p)
83                 vlan_vid_del(dev, htons(ETH_P_8021Q), vid);
84         return err;
85 }
86
87 static int __vlan_del(struct net_port_vlans *v, u16 vid)
88 {
89         if (!test_bit(vid, v->vlan_bitmap))
90                 return -EINVAL;
91
92         __vlan_delete_pvid(v, vid);
93         clear_bit(vid, v->untagged_bitmap);
94
95         if (v->port_idx)
96                 vlan_vid_del(v->parent.port->dev, htons(ETH_P_8021Q), vid);
97
98         clear_bit(vid, v->vlan_bitmap);
99         v->num_vlans--;
100         if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) {
101                 if (v->port_idx)
102                         rcu_assign_pointer(v->parent.port->vlan_info, NULL);
103                 else
104                         rcu_assign_pointer(v->parent.br->vlan_info, NULL);
105                 kfree_rcu(v, rcu);
106         }
107         return 0;
108 }
109
110 static void __vlan_flush(struct net_port_vlans *v)
111 {
112         smp_wmb();
113         v->pvid = 0;
114         bitmap_zero(v->vlan_bitmap, VLAN_N_VID);
115         if (v->port_idx)
116                 rcu_assign_pointer(v->parent.port->vlan_info, NULL);
117         else
118                 rcu_assign_pointer(v->parent.br->vlan_info, NULL);
119         kfree_rcu(v, rcu);
120 }
121
122 struct sk_buff *br_handle_vlan(struct net_bridge *br,
123                                const struct net_port_vlans *pv,
124                                struct sk_buff *skb)
125 {
126         u16 vid;
127
128         if (!br->vlan_enabled)
129                 goto out;
130
131         /* At this point, we know that the frame was filtered and contains
132          * a valid vlan id.  If the vlan id is set in the untagged bitmap,
133          * send untagged; otherwise, send tagged.
134          */
135         br_vlan_get_tag(skb, &vid);
136         if (test_bit(vid, pv->untagged_bitmap))
137                 skb->vlan_tci = 0;
138
139 out:
140         return skb;
141 }
142
143 /* Called under RCU */
144 bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
145                         struct sk_buff *skb, u16 *vid)
146 {
147         int err;
148
149         /* If VLAN filtering is disabled on the bridge, all packets are
150          * permitted.
151          */
152         if (!br->vlan_enabled)
153                 return true;
154
155         /* If there are no vlan in the permitted list, all packets are
156          * rejected.
157          */
158         if (!v)
159                 return false;
160
161         /* If vlan tx offload is disabled on bridge device and frame was
162          * sent from vlan device on the bridge device, it does not have
163          * HW accelerated vlan tag.
164          */
165         if (unlikely(!vlan_tx_tag_present(skb) &&
166                      (skb->protocol == htons(ETH_P_8021Q) ||
167                       skb->protocol == htons(ETH_P_8021AD)))) {
168                 skb = vlan_untag(skb);
169                 if (unlikely(!skb))
170                         return false;
171         }
172
173         err = br_vlan_get_tag(skb, vid);
174         if (!*vid) {
175                 u16 pvid = br_get_pvid(v);
176
177                 /* Frame had a tag with VID 0 or did not have a tag.
178                  * See if pvid is set on this port.  That tells us which
179                  * vlan untagged or priority-tagged traffic belongs to.
180                  */
181                 if (pvid == VLAN_N_VID)
182                         return false;
183
184                 /* PVID is set on this port.  Any untagged or priority-tagged
185                  * ingress frame is considered to belong to this vlan.
186                  */
187                 *vid = pvid;
188                 if (likely(err))
189                         /* Untagged Frame. */
190                         __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid);
191                 else
192                         /* Priority-tagged Frame.
193                          * At this point, We know that skb->vlan_tci had
194                          * VLAN_TAG_PRESENT bit and its VID field was 0x000.
195                          * We update only VID field and preserve PCP field.
196                          */
197                         skb->vlan_tci |= pvid;
198
199                 return true;
200         }
201
202         /* Frame had a valid vlan tag.  See if vlan is allowed */
203         if (test_bit(*vid, v->vlan_bitmap))
204                 return true;
205
206         return false;
207 }
208
209 /* Called under RCU. */
210 bool br_allowed_egress(struct net_bridge *br,
211                        const struct net_port_vlans *v,
212                        const struct sk_buff *skb)
213 {
214         u16 vid;
215
216         if (!br->vlan_enabled)
217                 return true;
218
219         if (!v)
220                 return false;
221
222         br_vlan_get_tag(skb, &vid);
223         if (test_bit(vid, v->vlan_bitmap))
224                 return true;
225
226         return false;
227 }
228
229 /* Must be protected by RTNL.
230  * Must be called with vid in range from 1 to 4094 inclusive.
231  */
232 int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
233 {
234         struct net_port_vlans *pv = NULL;
235         int err;
236
237         ASSERT_RTNL();
238
239         pv = rtnl_dereference(br->vlan_info);
240         if (pv)
241                 return __vlan_add(pv, vid, flags);
242
243         /* Create port vlan infomration
244          */
245         pv = kzalloc(sizeof(*pv), GFP_KERNEL);
246         if (!pv)
247                 return -ENOMEM;
248
249         pv->parent.br = br;
250         err = __vlan_add(pv, vid, flags);
251         if (err)
252                 goto out;
253
254         rcu_assign_pointer(br->vlan_info, pv);
255         return 0;
256 out:
257         kfree(pv);
258         return err;
259 }
260
261 /* Must be protected by RTNL.
262  * Must be called with vid in range from 1 to 4094 inclusive.
263  */
264 int br_vlan_delete(struct net_bridge *br, u16 vid)
265 {
266         struct net_port_vlans *pv;
267
268         ASSERT_RTNL();
269
270         pv = rtnl_dereference(br->vlan_info);
271         if (!pv)
272                 return -EINVAL;
273
274         br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid);
275
276         __vlan_del(pv, vid);
277         return 0;
278 }
279
280 void br_vlan_flush(struct net_bridge *br)
281 {
282         struct net_port_vlans *pv;
283
284         ASSERT_RTNL();
285         pv = rtnl_dereference(br->vlan_info);
286         if (!pv)
287                 return;
288
289         __vlan_flush(pv);
290 }
291
292 bool br_vlan_find(struct net_bridge *br, u16 vid)
293 {
294         struct net_port_vlans *pv;
295         bool found = false;
296
297         rcu_read_lock();
298         pv = rcu_dereference(br->vlan_info);
299
300         if (!pv)
301                 goto out;
302
303         if (test_bit(vid, pv->vlan_bitmap))
304                 found = true;
305
306 out:
307         rcu_read_unlock();
308         return found;
309 }
310
311 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
312 {
313         if (!rtnl_trylock())
314                 return restart_syscall();
315
316         if (br->vlan_enabled == val)
317                 goto unlock;
318
319         br->vlan_enabled = val;
320
321 unlock:
322         rtnl_unlock();
323         return 0;
324 }
325
326 /* Must be protected by RTNL.
327  * Must be called with vid in range from 1 to 4094 inclusive.
328  */
329 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
330 {
331         struct net_port_vlans *pv = NULL;
332         int err;
333
334         ASSERT_RTNL();
335
336         pv = rtnl_dereference(port->vlan_info);
337         if (pv)
338                 return __vlan_add(pv, vid, flags);
339
340         /* Create port vlan infomration
341          */
342         pv = kzalloc(sizeof(*pv), GFP_KERNEL);
343         if (!pv) {
344                 err = -ENOMEM;
345                 goto clean_up;
346         }
347
348         pv->port_idx = port->port_no;
349         pv->parent.port = port;
350         err = __vlan_add(pv, vid, flags);
351         if (err)
352                 goto clean_up;
353
354         rcu_assign_pointer(port->vlan_info, pv);
355         return 0;
356
357 clean_up:
358         kfree(pv);
359         return err;
360 }
361
362 /* Must be protected by RTNL.
363  * Must be called with vid in range from 1 to 4094 inclusive.
364  */
365 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
366 {
367         struct net_port_vlans *pv;
368
369         ASSERT_RTNL();
370
371         pv = rtnl_dereference(port->vlan_info);
372         if (!pv)
373                 return -EINVAL;
374
375         br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid);
376
377         return __vlan_del(pv, vid);
378 }
379
380 void nbp_vlan_flush(struct net_bridge_port *port)
381 {
382         struct net_port_vlans *pv;
383         u16 vid;
384
385         ASSERT_RTNL();
386
387         pv = rtnl_dereference(port->vlan_info);
388         if (!pv)
389                 return;
390
391         for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID)
392                 vlan_vid_del(port->dev, htons(ETH_P_8021Q), vid);
393
394         __vlan_flush(pv);
395 }
396
397 bool nbp_vlan_find(struct net_bridge_port *port, u16 vid)
398 {
399         struct net_port_vlans *pv;
400         bool found = false;
401
402         rcu_read_lock();
403         pv = rcu_dereference(port->vlan_info);
404
405         if (!pv)
406                 goto out;
407
408         if (test_bit(vid, pv->vlan_bitmap))
409                 found = true;
410
411 out:
412         rcu_read_unlock();
413         return found;
414 }