aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2013-04-18 22:04:28 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-19 14:45:27 -0400
commit80d5c3689b886308247da295a228a54df49a44f6 (patch)
treece7b1e6898c3f9fea945e67fd06b125dfcc61fe7 /net/8021q
parentf646968f8f7c624587de729115d802372b9063dd (diff)
net: vlan: prepare for 802.1ad VLAN filtering offload
Change the rx_{add,kill}_vid callbacks to take a protocol argument in preparation of 802.1ad support. The protocol argument used so far is always htons(ETH_P_8021Q). Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q')
-rw-r--r--net/8021q/vlan.c10
-rw-r--r--net/8021q/vlan_core.c47
2 files changed, 31 insertions, 26 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index d913feed0757..447c5c93434f 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -112,7 +112,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
112 * VLAN is not 0 (leave it there for 802.1p). 112 * VLAN is not 0 (leave it there for 802.1p).
113 */ 113 */
114 if (vlan_id) 114 if (vlan_id)
115 vlan_vid_del(real_dev, vlan_id); 115 vlan_vid_del(real_dev, htons(ETH_P_8021Q), vlan_id);
116 116
117 /* Get rid of the vlan's reference to real_dev */ 117 /* Get rid of the vlan's reference to real_dev */
118 dev_put(real_dev); 118 dev_put(real_dev);
@@ -142,7 +142,7 @@ int register_vlan_dev(struct net_device *dev)
142 struct vlan_group *grp; 142 struct vlan_group *grp;
143 int err; 143 int err;
144 144
145 err = vlan_vid_add(real_dev, vlan_id); 145 err = vlan_vid_add(real_dev, htons(ETH_P_8021Q), vlan_id);
146 if (err) 146 if (err)
147 return err; 147 return err;
148 148
@@ -195,7 +195,7 @@ out_uninit_gvrp:
195 if (grp->nr_vlan_devs == 0) 195 if (grp->nr_vlan_devs == 0)
196 vlan_gvrp_uninit_applicant(real_dev); 196 vlan_gvrp_uninit_applicant(real_dev);
197out_vid_del: 197out_vid_del:
198 vlan_vid_del(real_dev, vlan_id); 198 vlan_vid_del(real_dev, htons(ETH_P_8021Q), vlan_id);
199 return err; 199 return err;
200} 200}
201 201
@@ -350,7 +350,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
350 (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { 350 (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
351 pr_info("adding VLAN 0 to HW filter on device %s\n", 351 pr_info("adding VLAN 0 to HW filter on device %s\n",
352 dev->name); 352 dev->name);
353 vlan_vid_add(dev, 0); 353 vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
354 } 354 }
355 355
356 vlan_info = rtnl_dereference(dev->vlan_info); 356 vlan_info = rtnl_dereference(dev->vlan_info);
@@ -416,7 +416,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
416 416
417 case NETDEV_DOWN: 417 case NETDEV_DOWN:
418 if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) 418 if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
419 vlan_vid_del(dev, 0); 419 vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
420 420
421 /* Put all VLANs for this dev in the down state too. */ 421 /* Put all VLANs for this dev in the down state too. */
422 for (i = 0; i < VLAN_N_VID; i++) { 422 for (i = 0; i < VLAN_N_VID; i++) {
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 3df29d344704..04e3b95a0d48 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -185,35 +185,37 @@ static struct vlan_info *vlan_info_alloc(struct net_device *dev)
185 185
186struct vlan_vid_info { 186struct vlan_vid_info {
187 struct list_head list; 187 struct list_head list;
188 unsigned short vid; 188 __be16 proto;
189 u16 vid;
189 int refcount; 190 int refcount;
190}; 191};
191 192
192static struct vlan_vid_info *vlan_vid_info_get(struct vlan_info *vlan_info, 193static struct vlan_vid_info *vlan_vid_info_get(struct vlan_info *vlan_info,
193 unsigned short vid) 194 __be16 proto, u16 vid)
194{ 195{
195 struct vlan_vid_info *vid_info; 196 struct vlan_vid_info *vid_info;
196 197
197 list_for_each_entry(vid_info, &vlan_info->vid_list, list) { 198 list_for_each_entry(vid_info, &vlan_info->vid_list, list) {
198 if (vid_info->vid == vid) 199 if (vid_info->proto == proto && vid_info->vid == vid)
199 return vid_info; 200 return vid_info;
200 } 201 }
201 return NULL; 202 return NULL;
202} 203}
203 204
204static struct vlan_vid_info *vlan_vid_info_alloc(unsigned short vid) 205static struct vlan_vid_info *vlan_vid_info_alloc(__be16 proto, u16 vid)
205{ 206{
206 struct vlan_vid_info *vid_info; 207 struct vlan_vid_info *vid_info;
207 208
208 vid_info = kzalloc(sizeof(struct vlan_vid_info), GFP_KERNEL); 209 vid_info = kzalloc(sizeof(struct vlan_vid_info), GFP_KERNEL);
209 if (!vid_info) 210 if (!vid_info)
210 return NULL; 211 return NULL;
212 vid_info->proto = proto;
211 vid_info->vid = vid; 213 vid_info->vid = vid;
212 214
213 return vid_info; 215 return vid_info;
214} 216}
215 217
216static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid, 218static int __vlan_vid_add(struct vlan_info *vlan_info, __be16 proto, u16 vid,
217 struct vlan_vid_info **pvid_info) 219 struct vlan_vid_info **pvid_info)
218{ 220{
219 struct net_device *dev = vlan_info->real_dev; 221 struct net_device *dev = vlan_info->real_dev;
@@ -221,12 +223,13 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid,
221 struct vlan_vid_info *vid_info; 223 struct vlan_vid_info *vid_info;
222 int err; 224 int err;
223 225
224 vid_info = vlan_vid_info_alloc(vid); 226 vid_info = vlan_vid_info_alloc(proto, vid);
225 if (!vid_info) 227 if (!vid_info)
226 return -ENOMEM; 228 return -ENOMEM;
227 229
228 if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { 230 if (proto == htons(ETH_P_8021Q) &&
229 err = ops->ndo_vlan_rx_add_vid(dev, vid); 231 dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
232 err = ops->ndo_vlan_rx_add_vid(dev, proto, vid);
230 if (err) { 233 if (err) {
231 kfree(vid_info); 234 kfree(vid_info);
232 return err; 235 return err;
@@ -238,7 +241,7 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid,
238 return 0; 241 return 0;
239} 242}
240 243
241int vlan_vid_add(struct net_device *dev, unsigned short vid) 244int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid)
242{ 245{
243 struct vlan_info *vlan_info; 246 struct vlan_info *vlan_info;
244 struct vlan_vid_info *vid_info; 247 struct vlan_vid_info *vid_info;
@@ -254,9 +257,9 @@ int vlan_vid_add(struct net_device *dev, unsigned short vid)
254 return -ENOMEM; 257 return -ENOMEM;
255 vlan_info_created = true; 258 vlan_info_created = true;
256 } 259 }
257 vid_info = vlan_vid_info_get(vlan_info, vid); 260 vid_info = vlan_vid_info_get(vlan_info, proto, vid);
258 if (!vid_info) { 261 if (!vid_info) {
259 err = __vlan_vid_add(vlan_info, vid, &vid_info); 262 err = __vlan_vid_add(vlan_info, proto, vid, &vid_info);
260 if (err) 263 if (err)
261 goto out_free_vlan_info; 264 goto out_free_vlan_info;
262 } 265 }
@@ -279,14 +282,16 @@ static void __vlan_vid_del(struct vlan_info *vlan_info,
279{ 282{
280 struct net_device *dev = vlan_info->real_dev; 283 struct net_device *dev = vlan_info->real_dev;
281 const struct net_device_ops *ops = dev->netdev_ops; 284 const struct net_device_ops *ops = dev->netdev_ops;
282 unsigned short vid = vid_info->vid; 285 __be16 proto = vid_info->proto;
286 u16 vid = vid_info->vid;
283 int err; 287 int err;
284 288
285 if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { 289 if (proto == htons(ETH_P_8021Q) &&
286 err = ops->ndo_vlan_rx_kill_vid(dev, vid); 290 dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
291 err = ops->ndo_vlan_rx_kill_vid(dev, proto, vid);
287 if (err) { 292 if (err) {
288 pr_warn("failed to kill vid %d for device %s\n", 293 pr_warn("failed to kill vid %04x/%d for device %s\n",
289 vid, dev->name); 294 proto, vid, dev->name);
290 } 295 }
291 } 296 }
292 list_del(&vid_info->list); 297 list_del(&vid_info->list);
@@ -294,7 +299,7 @@ static void __vlan_vid_del(struct vlan_info *vlan_info,
294 vlan_info->nr_vids--; 299 vlan_info->nr_vids--;
295} 300}
296 301
297void vlan_vid_del(struct net_device *dev, unsigned short vid) 302void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid)
298{ 303{
299 struct vlan_info *vlan_info; 304 struct vlan_info *vlan_info;
300 struct vlan_vid_info *vid_info; 305 struct vlan_vid_info *vid_info;
@@ -305,7 +310,7 @@ void vlan_vid_del(struct net_device *dev, unsigned short vid)
305 if (!vlan_info) 310 if (!vlan_info)
306 return; 311 return;
307 312
308 vid_info = vlan_vid_info_get(vlan_info, vid); 313 vid_info = vlan_vid_info_get(vlan_info, proto, vid);
309 if (!vid_info) 314 if (!vid_info)
310 return; 315 return;
311 vid_info->refcount--; 316 vid_info->refcount--;
@@ -333,7 +338,7 @@ int vlan_vids_add_by_dev(struct net_device *dev,
333 return 0; 338 return 0;
334 339
335 list_for_each_entry(vid_info, &vlan_info->vid_list, list) { 340 list_for_each_entry(vid_info, &vlan_info->vid_list, list) {
336 err = vlan_vid_add(dev, vid_info->vid); 341 err = vlan_vid_add(dev, vid_info->proto, vid_info->vid);
337 if (err) 342 if (err)
338 goto unwind; 343 goto unwind;
339 } 344 }
@@ -343,7 +348,7 @@ unwind:
343 list_for_each_entry_continue_reverse(vid_info, 348 list_for_each_entry_continue_reverse(vid_info,
344 &vlan_info->vid_list, 349 &vlan_info->vid_list,
345 list) { 350 list) {
346 vlan_vid_del(dev, vid_info->vid); 351 vlan_vid_del(dev, vid_info->proto, vid_info->vid);
347 } 352 }
348 353
349 return err; 354 return err;
@@ -363,7 +368,7 @@ void vlan_vids_del_by_dev(struct net_device *dev,
363 return; 368 return;
364 369
365 list_for_each_entry(vid_info, &vlan_info->vid_list, list) 370 list_for_each_entry(vid_info, &vlan_info->vid_list, list)
366 vlan_vid_del(dev, vid_info->vid); 371 vlan_vid_del(dev, vid_info->proto, vid_info->vid);
367} 372}
368EXPORT_SYMBOL(vlan_vids_del_by_dev); 373EXPORT_SYMBOL(vlan_vids_del_by_dev);
369 374