Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: vlan: prepare for 802.1ad support

Make the encapsulation protocol value a property of VLAN devices and change
the device lookup functions to take the protocol value into account.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Patrick McHardy and committed by
David S. Miller
1fd9b1fc 80d5c368

+108 -84
+5 -3
drivers/net/bonding/bond_main.c
··· 782 782 783 783 /* rejoin all groups on vlan devices */ 784 784 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { 785 - vlan_dev = __vlan_find_dev_deep(bond_dev, 785 + vlan_dev = __vlan_find_dev_deep(bond_dev, htons(ETH_P_8021Q), 786 786 vlan->vlan_id); 787 787 if (vlan_dev) 788 788 __bond_resend_igmp_join_requests(vlan_dev); ··· 2512 2512 2513 2513 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { 2514 2514 rcu_read_lock(); 2515 - vlan_dev = __vlan_find_dev_deep(bond->dev, vlan->vlan_id); 2515 + vlan_dev = __vlan_find_dev_deep(bond->dev, htons(ETH_P_8021Q), 2516 + vlan->vlan_id); 2516 2517 rcu_read_unlock(); 2517 2518 if (vlan_dev && ip == bond_confirm_addr(vlan_dev, 0, ip)) 2518 2519 return 1; ··· 2542 2541 return; 2543 2542 } 2544 2543 if (vlan_id) { 2545 - skb = vlan_put_tag(skb, vlan_id); 2544 + skb = vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_id); 2546 2545 if (!skb) { 2547 2546 pr_err("failed to insert VLAN tag\n"); 2548 2547 return; ··· 2604 2603 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { 2605 2604 rcu_read_lock(); 2606 2605 vlan_dev = __vlan_find_dev_deep(bond->dev, 2606 + htons(ETH_P_8021Q), 2607 2607 vlan->vlan_id); 2608 2608 rcu_read_unlock(); 2609 2609 if (vlan_dev == rt->dst.dev) {
+1 -1
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
··· 185 185 if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) { 186 186 rcu_read_lock(); 187 187 if (vlan && vlan != VLAN_VID_MASK) { 188 - dev = __vlan_find_dev_deep(dev, vlan); 188 + dev = __vlan_find_dev_deep(dev, htons(ETH_P_8021Q), vlan); 189 189 } else if (netif_is_bond_slave(dev)) { 190 190 struct net_device *upper_dev; 191 191
+1 -1
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
··· 3346 3346 3347 3347 rcu_read_lock(); 3348 3348 for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) { 3349 - dev = __vlan_find_dev_deep(netdev, vid); 3349 + dev = __vlan_find_dev_deep(netdev, htons(ETH_P_8021Q), vid); 3350 3350 if (!dev) 3351 3351 continue; 3352 3352 qlcnic_config_indev_addr(adapter, dev, event);
+1 -1
include/linux/if_vlan.h
··· 86 86 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 87 87 88 88 extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, 89 - u16 vlan_id); 89 + __be16 vlan_proto, u16 vlan_id); 90 90 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); 91 91 extern u16 vlan_dev_vlan_id(const struct net_device *dev); 92 92
+30 -57
net/8021q/vlan.c
··· 51 51 52 52 /* End of global variables definitions. */ 53 53 54 - static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id) 54 + static int vlan_group_prealloc_vid(struct vlan_group *vg, 55 + __be16 vlan_proto, u16 vlan_id) 55 56 { 56 57 struct net_device **array; 58 + unsigned int pidx, vidx; 57 59 unsigned int size; 58 60 59 61 ASSERT_RTNL(); 60 62 61 - array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; 63 + pidx = vlan_proto_idx(vlan_proto); 64 + vidx = vlan_id / VLAN_GROUP_ARRAY_PART_LEN; 65 + array = vg->vlan_devices_arrays[pidx][vidx]; 62 66 if (array != NULL) 63 67 return 0; 64 68 ··· 71 67 if (array == NULL) 72 68 return -ENOBUFS; 73 69 74 - vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN] = array; 70 + vg->vlan_devices_arrays[pidx][vidx] = array; 75 71 return 0; 76 72 } 77 73 ··· 97 93 if (vlan->flags & VLAN_FLAG_GVRP) 98 94 vlan_gvrp_request_leave(dev); 99 95 100 - vlan_group_set_device(grp, vlan_id, NULL); 96 + vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL); 101 97 /* Because unregister_netdevice_queue() makes sure at least one rcu 102 98 * grace period is respected before device freeing, 103 99 * we dont need to call synchronize_net() here. ··· 116 112 * VLAN is not 0 (leave it there for 802.1p). 117 113 */ 118 114 if (vlan_id) 119 - vlan_vid_del(real_dev, htons(ETH_P_8021Q), vlan_id); 115 + vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); 120 116 121 117 /* Get rid of the vlan's reference to real_dev */ 122 118 dev_put(real_dev); 123 119 } 124 120 125 - int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) 121 + int vlan_check_real_dev(struct net_device *real_dev, 122 + __be16 protocol, u16 vlan_id) 126 123 { 127 124 const char *name = real_dev->name; 128 125 ··· 132 127 return -EOPNOTSUPP; 133 128 } 134 129 135 - if (vlan_find_dev(real_dev, vlan_id) != NULL) 130 + if (vlan_find_dev(real_dev, protocol, vlan_id) != NULL) 136 131 return -EEXIST; 137 132 138 133 return 0; ··· 147 142 struct vlan_group *grp; 148 143 int err; 149 144 150 - err = vlan_vid_add(real_dev, htons(ETH_P_8021Q), vlan_id); 145 + err = vlan_vid_add(real_dev, vlan->vlan_proto, vlan_id); 151 146 if (err) 152 147 return err; 153 148 ··· 165 160 goto out_uninit_gvrp; 166 161 } 167 162 168 - err = vlan_group_prealloc_vid(grp, vlan_id); 163 + err = vlan_group_prealloc_vid(grp, vlan->vlan_proto, vlan_id); 169 164 if (err < 0) 170 165 goto out_uninit_mvrp; 171 166 ··· 186 181 /* So, got the sucker initialized, now lets place 187 182 * it into our local structure. 188 183 */ 189 - vlan_group_set_device(grp, vlan_id, dev); 184 + vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, dev); 190 185 grp->nr_vlan_devs++; 191 186 192 187 return 0; ··· 200 195 if (grp->nr_vlan_devs == 0) 201 196 vlan_gvrp_uninit_applicant(real_dev); 202 197 out_vid_del: 203 - vlan_vid_del(real_dev, htons(ETH_P_8021Q), vlan_id); 198 + vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); 204 199 return err; 205 200 } 206 201 ··· 218 213 if (vlan_id >= VLAN_VID_MASK) 219 214 return -ERANGE; 220 215 221 - err = vlan_check_real_dev(real_dev, vlan_id); 216 + err = vlan_check_real_dev(real_dev, htons(ETH_P_8021Q), vlan_id); 222 217 if (err < 0) 223 218 return err; 224 219 ··· 260 255 new_dev->mtu = real_dev->mtu; 261 256 new_dev->priv_flags |= (real_dev->priv_flags & IFF_UNICAST_FLT); 262 257 258 + vlan_dev_priv(new_dev)->vlan_proto = htons(ETH_P_8021Q); 263 259 vlan_dev_priv(new_dev)->vlan_id = vlan_id; 264 260 vlan_dev_priv(new_dev)->real_dev = real_dev; 265 261 vlan_dev_priv(new_dev)->dent = NULL; ··· 347 341 int i, flgs; 348 342 struct net_device *vlandev; 349 343 struct vlan_dev_priv *vlan; 344 + bool last = false; 350 345 LIST_HEAD(list); 351 346 352 347 if (is_vlan_dev(dev)) ··· 372 365 switch (event) { 373 366 case NETDEV_CHANGE: 374 367 /* Propagate real device state to vlan devices */ 375 - for (i = 0; i < VLAN_N_VID; i++) { 376 - vlandev = vlan_group_get_device(grp, i); 377 - if (!vlandev) 378 - continue; 379 - 368 + vlan_group_for_each_dev(grp, i, vlandev) 380 369 netif_stacked_transfer_operstate(dev, vlandev); 381 - } 382 370 break; 383 371 384 372 case NETDEV_CHANGEADDR: 385 373 /* Adjust unicast filters on underlying device */ 386 - for (i = 0; i < VLAN_N_VID; i++) { 387 - vlandev = vlan_group_get_device(grp, i); 388 - if (!vlandev) 389 - continue; 390 - 374 + vlan_group_for_each_dev(grp, i, vlandev) { 391 375 flgs = vlandev->flags; 392 376 if (!(flgs & IFF_UP)) 393 377 continue; ··· 388 390 break; 389 391 390 392 case NETDEV_CHANGEMTU: 391 - for (i = 0; i < VLAN_N_VID; i++) { 392 - vlandev = vlan_group_get_device(grp, i); 393 - if (!vlandev) 394 - continue; 395 - 393 + vlan_group_for_each_dev(grp, i, vlandev) { 396 394 if (vlandev->mtu <= dev->mtu) 397 395 continue; 398 396 ··· 398 404 399 405 case NETDEV_FEAT_CHANGE: 400 406 /* Propagate device features to underlying device */ 401 - for (i = 0; i < VLAN_N_VID; i++) { 402 - vlandev = vlan_group_get_device(grp, i); 403 - if (!vlandev) 404 - continue; 405 - 407 + vlan_group_for_each_dev(grp, i, vlandev) 406 408 vlan_transfer_features(dev, vlandev); 407 - } 408 - 409 409 break; 410 410 411 411 case NETDEV_DOWN: ··· 407 419 vlan_vid_del(dev, htons(ETH_P_8021Q), 0); 408 420 409 421 /* Put all VLANs for this dev in the down state too. */ 410 - for (i = 0; i < VLAN_N_VID; i++) { 411 - vlandev = vlan_group_get_device(grp, i); 412 - if (!vlandev) 413 - continue; 414 - 422 + vlan_group_for_each_dev(grp, i, vlandev) { 415 423 flgs = vlandev->flags; 416 424 if (!(flgs & IFF_UP)) 417 425 continue; ··· 421 437 422 438 case NETDEV_UP: 423 439 /* Put all VLANs for this dev in the up state too. */ 424 - for (i = 0; i < VLAN_N_VID; i++) { 425 - vlandev = vlan_group_get_device(grp, i); 426 - if (!vlandev) 427 - continue; 428 - 440 + vlan_group_for_each_dev(grp, i, vlandev) { 429 441 flgs = vlandev->flags; 430 442 if (flgs & IFF_UP) 431 443 continue; ··· 438 458 if (dev->reg_state != NETREG_UNREGISTERING) 439 459 break; 440 460 441 - for (i = 0; i < VLAN_N_VID; i++) { 442 - vlandev = vlan_group_get_device(grp, i); 443 - if (!vlandev) 444 - continue; 445 - 461 + vlan_group_for_each_dev(grp, i, vlandev) { 446 462 /* removal of last vid destroys vlan_info, abort 447 463 * afterwards */ 448 464 if (vlan_info->nr_vids == 1) 449 - i = VLAN_N_VID; 465 + last = true; 450 466 451 467 unregister_vlan_dev(vlandev, &list); 468 + if (last) 469 + break; 452 470 } 453 471 unregister_netdevice_many(&list); 454 472 break; ··· 460 482 case NETDEV_NOTIFY_PEERS: 461 483 case NETDEV_BONDING_FAILOVER: 462 484 /* Propagate to vlan devices */ 463 - for (i = 0; i < VLAN_N_VID; i++) { 464 - vlandev = vlan_group_get_device(grp, i); 465 - if (!vlandev) 466 - continue; 467 - 485 + vlan_group_for_each_dev(grp, i, vlandev) 468 486 call_netdevice_notifiers(event, vlandev); 469 - } 470 487 break; 471 488 } 472 489
+45 -9
net/8021q/vlan.h
··· 49 49 * @ingress_priority_map: ingress priority mappings 50 50 * @nr_egress_mappings: number of egress priority mappings 51 51 * @egress_priority_map: hash of egress priority mappings 52 + * @vlan_proto: VLAN encapsulation protocol 52 53 * @vlan_id: VLAN identifier 53 54 * @flags: device flags 54 55 * @real_dev: underlying netdevice ··· 63 62 unsigned int nr_egress_mappings; 64 63 struct vlan_priority_tci_mapping *egress_priority_map[16]; 65 64 65 + __be16 vlan_proto; 66 66 u16 vlan_id; 67 67 u16 flags; 68 68 ··· 89 87 #define VLAN_GROUP_ARRAY_SPLIT_PARTS 8 90 88 #define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS) 91 89 90 + enum vlan_protos { 91 + VLAN_PROTO_8021Q = 0, 92 + VLAN_PROTO_NUM, 93 + }; 94 + 92 95 struct vlan_group { 93 96 unsigned int nr_vlan_devs; 94 97 struct hlist_node hlist; /* linked list */ 95 - struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; 98 + struct net_device **vlan_devices_arrays[VLAN_PROTO_NUM] 99 + [VLAN_GROUP_ARRAY_SPLIT_PARTS]; 96 100 }; 97 101 98 102 struct vlan_info { ··· 111 103 struct rcu_head rcu; 112 104 }; 113 105 114 - static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, 115 - u16 vlan_id) 106 + static inline unsigned int vlan_proto_idx(__be16 proto) 107 + { 108 + switch (proto) { 109 + case __constant_htons(ETH_P_8021Q): 110 + return VLAN_PROTO_8021Q; 111 + default: 112 + BUG(); 113 + } 114 + } 115 + 116 + static inline struct net_device *__vlan_group_get_device(struct vlan_group *vg, 117 + unsigned int pidx, 118 + u16 vlan_id) 116 119 { 117 120 struct net_device **array; 118 - array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; 121 + 122 + array = vg->vlan_devices_arrays[pidx] 123 + [vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; 119 124 return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL; 120 125 } 121 126 127 + static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, 128 + __be16 vlan_proto, 129 + u16 vlan_id) 130 + { 131 + return __vlan_group_get_device(vg, vlan_proto_idx(vlan_proto), vlan_id); 132 + } 133 + 122 134 static inline void vlan_group_set_device(struct vlan_group *vg, 123 - u16 vlan_id, 135 + __be16 vlan_proto, u16 vlan_id, 124 136 struct net_device *dev) 125 137 { 126 138 struct net_device **array; 127 139 if (!vg) 128 140 return; 129 - array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; 141 + array = vg->vlan_devices_arrays[vlan_proto_idx(vlan_proto)] 142 + [vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; 130 143 array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev; 131 144 } 132 145 133 146 /* Must be invoked with rcu_read_lock or with RTNL. */ 134 147 static inline struct net_device *vlan_find_dev(struct net_device *real_dev, 135 - u16 vlan_id) 148 + __be16 vlan_proto, u16 vlan_id) 136 149 { 137 150 struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); 138 151 139 152 if (vlan_info) 140 - return vlan_group_get_device(&vlan_info->grp, vlan_id); 153 + return vlan_group_get_device(&vlan_info->grp, 154 + vlan_proto, vlan_id); 141 155 142 156 return NULL; 143 157 } 158 + 159 + #define vlan_group_for_each_dev(grp, i, dev) \ 160 + for ((i) = 0; i < VLAN_PROTO_NUM * VLAN_N_VID; i++) \ 161 + if (((dev) = __vlan_group_get_device((grp), (i) / VLAN_N_VID, \ 162 + (i) % VLAN_N_VID))) 144 163 145 164 /* found in vlan_dev.c */ 146 165 void vlan_dev_set_ingress_priority(const struct net_device *dev, ··· 177 142 int vlan_dev_change_flags(const struct net_device *dev, u32 flag, u32 mask); 178 143 void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); 179 144 180 - int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id); 145 + int vlan_check_real_dev(struct net_device *real_dev, 146 + __be16 protocol, u16 vlan_id); 181 147 void vlan_setup(struct net_device *dev); 182 148 int register_vlan_dev(struct net_device *dev); 183 149 void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
+6 -4
net/8021q/vlan_core.c
··· 12 12 struct net_device *vlan_dev; 13 13 struct vlan_pcpu_stats *rx_stats; 14 14 15 - vlan_dev = vlan_find_dev(skb->dev, vlan_id); 15 + vlan_dev = vlan_find_dev(skb->dev, htons(ETH_P_8021Q), vlan_id); 16 16 if (!vlan_dev) 17 17 return false; 18 18 ··· 62 62 63 63 /* Must be invoked with rcu_read_lock. */ 64 64 struct net_device *__vlan_find_dev_deep(struct net_device *dev, 65 - u16 vlan_id) 65 + __be16 vlan_proto, u16 vlan_id) 66 66 { 67 67 struct vlan_info *vlan_info = rcu_dereference(dev->vlan_info); 68 68 69 69 if (vlan_info) { 70 - return vlan_group_get_device(&vlan_info->grp, vlan_id); 70 + return vlan_group_get_device(&vlan_info->grp, 71 + vlan_proto, vlan_id); 71 72 } else { 72 73 /* 73 74 * Lower devices of master uppers (bonding, team) do not have ··· 79 78 80 79 upper_dev = netdev_master_upper_dev_get_rcu(dev); 81 80 if (upper_dev) 82 - return __vlan_find_dev_deep(upper_dev, vlan_id); 81 + return __vlan_find_dev_deep(upper_dev, 82 + vlan_proto, vlan_id); 83 83 } 84 84 85 85 return NULL;
+4 -3
net/8021q/vlan_dev.c
··· 99 99 const void *daddr, const void *saddr, 100 100 unsigned int len) 101 101 { 102 + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); 102 103 struct vlan_hdr *vhdr; 103 104 unsigned int vhdrlen = 0; 104 105 u16 vlan_tci = 0; ··· 121 120 else 122 121 vhdr->h_vlan_encapsulated_proto = htons(len); 123 122 124 - skb->protocol = htons(ETH_P_8021Q); 125 - type = ETH_P_8021Q; 123 + skb->protocol = vlan->vlan_proto; 124 + type = ntohs(vlan->vlan_proto); 126 125 vhdrlen = VLAN_HLEN; 127 126 } 128 127 ··· 162 161 * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING 163 162 * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... 164 163 */ 165 - if (veth->h_vlan_proto != htons(ETH_P_8021Q) || 164 + if (veth->h_vlan_proto != vlan->vlan_proto || 166 165 vlan->flags & VLAN_FLAG_REORDER_HDR) { 167 166 u16 vlan_tci; 168 167 vlan_tci = vlan->vlan_id;
+4
net/8021q/vlan_gvrp.c
··· 32 32 const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); 33 33 __be16 vlan_id = htons(vlan->vlan_id); 34 34 35 + if (vlan->vlan_proto != htons(ETH_P_8021Q)) 36 + return 0; 35 37 return garp_request_join(vlan->real_dev, &vlan_gvrp_app, 36 38 &vlan_id, sizeof(vlan_id), GVRP_ATTR_VID); 37 39 } ··· 43 41 const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); 44 42 __be16 vlan_id = htons(vlan->vlan_id); 45 43 44 + if (vlan->vlan_proto != htons(ETH_P_8021Q)) 45 + return; 46 46 garp_request_leave(vlan->real_dev, &vlan_gvrp_app, 47 47 &vlan_id, sizeof(vlan_id), GVRP_ATTR_VID); 48 48 }
+4
net/8021q/vlan_mvrp.c
··· 38 38 const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); 39 39 __be16 vlan_id = htons(vlan->vlan_id); 40 40 41 + if (vlan->vlan_proto != htons(ETH_P_8021Q)) 42 + return 0; 41 43 return mrp_request_join(vlan->real_dev, &vlan_mrp_app, 42 44 &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID); 43 45 } ··· 49 47 const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); 50 48 __be16 vlan_id = htons(vlan->vlan_id); 51 49 50 + if (vlan->vlan_proto != htons(ETH_P_8021Q)) 51 + return; 52 52 mrp_request_leave(vlan->real_dev, &vlan_mrp_app, 53 53 &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID); 54 54 }
+5 -4
net/8021q/vlan_netlink.c
··· 118 118 if (!real_dev) 119 119 return -ENODEV; 120 120 121 - vlan->vlan_id = nla_get_u16(data[IFLA_VLAN_ID]); 122 - vlan->real_dev = real_dev; 123 - vlan->flags = VLAN_FLAG_REORDER_HDR; 121 + vlan->vlan_proto = htons(ETH_P_8021Q); 122 + vlan->vlan_id = nla_get_u16(data[IFLA_VLAN_ID]); 123 + vlan->real_dev = real_dev; 124 + vlan->flags = VLAN_FLAG_REORDER_HDR; 124 125 125 - err = vlan_check_real_dev(real_dev, vlan->vlan_id); 126 + err = vlan_check_real_dev(real_dev, vlan->vlan_proto, vlan->vlan_id); 126 127 if (err < 0) 127 128 return err; 128 129
+2 -1
net/bridge/br_netfilter.c
··· 535 535 if (brnf_pass_vlan_indev == 0 || !vlan_tx_tag_present(skb)) 536 536 return br; 537 537 538 - vlan = __vlan_find_dev_deep(br, vlan_tx_tag_get(skb) & VLAN_VID_MASK); 538 + vlan = __vlan_find_dev_deep(br, htons(ETH_P_8021Q), 539 + vlan_tx_tag_get(skb) & VLAN_VID_MASK); 539 540 540 541 return vlan ? vlan : br; 541 542 }