blob: f2bf5a197ea3f78aa646d58615a6f35524229b99 [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);
Vlad Yasevich6cbdcee2013-02-13 12:00:13 +000031 v->num_vlans++;
Vlad Yasevich243a2e62013-02-13 12:00:09 +000032 return 0;
33}
34
35static 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);
Vlad Yasevich6cbdcee2013-02-13 12:00:13 +000048 v->num_vlans--;
Vlad Yasevich243a2e62013-02-13 12:00:09 +000049 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
59static 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
Vlad Yasevicha37b85c2013-02-13 12:00:10 +000069/* Called under RCU */
70bool 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
Vlad Yasevich85f46c62013-02-13 12:00:11 +000094/* Called under RCU. */
95bool 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
Vlad Yasevich243a2e62013-02-13 12:00:09 +0000114/* Must be protected by RTNL */
115int 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;
139out:
140 kfree(pv);
141 return err;
142}
143
144/* Must be protected by RTNL */
145int 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
159void 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
172int 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
182unlock:
183 rtnl_unlock();
184 return 0;
185}
186
187/* Must be protected by RTNL */
188int 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
216clean_up:
217 kfree(pv);
218 return err;
219}
220
221/* Must be protected by RTNL */
222int 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
235void 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}