blob: 8b4bcd8ff46e3e5ffde53a026b2ec7770722899c [file] [log] [blame]
Vlad Yasevich243a2e62013-02-13 12:00:09 +00001#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
8static 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 return 0;
32}
33
34static int __vlan_del(struct net_port_vlans *v, u16 vid)
35{
36 if (!test_bit(vid, v->vlan_bitmap))
37 return -EINVAL;
38
39 if (v->port_idx && vid) {
40 struct net_device *dev = v->parent.port->dev;
41
42 if (dev->features & NETIF_F_HW_VLAN_FILTER)
43 dev->netdev_ops->ndo_vlan_rx_kill_vid(dev, vid);
44 }
45
46 clear_bit(vid, v->vlan_bitmap);
47 if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
48 if (v->port_idx)
49 rcu_assign_pointer(v->parent.port->vlan_info, NULL);
50 else
51 rcu_assign_pointer(v->parent.br->vlan_info, NULL);
52 kfree_rcu(v, rcu);
53 }
54 return 0;
55}
56
57static void __vlan_flush(struct net_port_vlans *v)
58{
59 bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
60 if (v->port_idx)
61 rcu_assign_pointer(v->parent.port->vlan_info, NULL);
62 else
63 rcu_assign_pointer(v->parent.br->vlan_info, NULL);
64 kfree_rcu(v, rcu);
65}
66
Vlad Yasevicha37b85c2013-02-13 12:00:10 +000067/* Called under RCU */
68bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
69 struct sk_buff *skb)
70{
71 u16 vid;
72
73 /* If VLAN filtering is disabled on the bridge, all packets are
74 * permitted.
75 */
76 if (!br->vlan_enabled)
77 return true;
78
79 /* If there are no vlan in the permitted list, all packets are
80 * rejected.
81 */
82 if (!v)
83 return false;
84
85 br_vlan_get_tag(skb, &vid);
86 if (test_bit(vid, v->vlan_bitmap))
87 return true;
88
89 return false;
90}
91
Vlad Yasevich243a2e62013-02-13 12:00:09 +000092/* Must be protected by RTNL */
93int br_vlan_add(struct net_bridge *br, u16 vid)
94{
95 struct net_port_vlans *pv = NULL;
96 int err;
97
98 ASSERT_RTNL();
99
100 pv = rtnl_dereference(br->vlan_info);
101 if (pv)
102 return __vlan_add(pv, vid);
103
104 /* Create port vlan infomration
105 */
106 pv = kzalloc(sizeof(*pv), GFP_KERNEL);
107 if (!pv)
108 return -ENOMEM;
109
110 pv->parent.br = br;
111 err = __vlan_add(pv, vid);
112 if (err)
113 goto out;
114
115 rcu_assign_pointer(br->vlan_info, pv);
116 return 0;
117out:
118 kfree(pv);
119 return err;
120}
121
122/* Must be protected by RTNL */
123int br_vlan_delete(struct net_bridge *br, u16 vid)
124{
125 struct net_port_vlans *pv;
126
127 ASSERT_RTNL();
128
129 pv = rtnl_dereference(br->vlan_info);
130 if (!pv)
131 return -EINVAL;
132
133 __vlan_del(pv, vid);
134 return 0;
135}
136
137void br_vlan_flush(struct net_bridge *br)
138{
139 struct net_port_vlans *pv;
140
141 ASSERT_RTNL();
142
143 pv = rtnl_dereference(br->vlan_info);
144 if (!pv)
145 return;
146
147 __vlan_flush(pv);
148}
149
150int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
151{
152 if (!rtnl_trylock())
153 return restart_syscall();
154
155 if (br->vlan_enabled == val)
156 goto unlock;
157
158 br->vlan_enabled = val;
159
160unlock:
161 rtnl_unlock();
162 return 0;
163}
164
165/* Must be protected by RTNL */
166int nbp_vlan_add(struct net_bridge_port *port, u16 vid)
167{
168 struct net_port_vlans *pv = NULL;
169 int err;
170
171 ASSERT_RTNL();
172
173 pv = rtnl_dereference(port->vlan_info);
174 if (pv)
175 return __vlan_add(pv, vid);
176
177 /* Create port vlan infomration
178 */
179 pv = kzalloc(sizeof(*pv), GFP_KERNEL);
180 if (!pv) {
181 err = -ENOMEM;
182 goto clean_up;
183 }
184
185 pv->port_idx = port->port_no;
186 pv->parent.port = port;
187 err = __vlan_add(pv, vid);
188 if (err)
189 goto clean_up;
190
191 rcu_assign_pointer(port->vlan_info, pv);
192 return 0;
193
194clean_up:
195 kfree(pv);
196 return err;
197}
198
199/* Must be protected by RTNL */
200int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
201{
202 struct net_port_vlans *pv;
203
204 ASSERT_RTNL();
205
206 pv = rtnl_dereference(port->vlan_info);
207 if (!pv)
208 return -EINVAL;
209
210 return __vlan_del(pv, vid);
211}
212
213void nbp_vlan_flush(struct net_bridge_port *port)
214{
215 struct net_port_vlans *pv;
216
217 ASSERT_RTNL();
218
219 pv = rtnl_dereference(port->vlan_info);
220 if (!pv)
221 return;
222
223 __vlan_flush(pv);
224}