@@ -51,14 +51,18 @@ const char vlan_version[] = DRV_VERSION;
5151
5252/* End of global variables definitions. */
5353
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 )
5556{
5657 struct net_device * * array ;
58+ unsigned int pidx , vidx ;
5759 unsigned int size ;
5860
5961 ASSERT_RTNL ();
6062
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 ];
6266 if (array != NULL )
6367 return 0 ;
6468
@@ -67,7 +71,7 @@ static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id)
6771 if (array == NULL )
6872 return - ENOBUFS ;
6973
70- vg -> vlan_devices_arrays [vlan_id / VLAN_GROUP_ARRAY_PART_LEN ] = array ;
74+ vg -> vlan_devices_arrays [pidx ][ vidx ] = array ;
7175 return 0 ;
7276}
7377
@@ -93,7 +97,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
9397 if (vlan -> flags & VLAN_FLAG_GVRP )
9498 vlan_gvrp_request_leave (dev );
9599
96- vlan_group_set_device (grp , vlan_id , NULL );
100+ vlan_group_set_device (grp , vlan -> vlan_proto , vlan_id , NULL );
97101 /* Because unregister_netdevice_queue() makes sure at least one rcu
98102 * grace period is respected before device freeing,
99103 * we dont need to call synchronize_net() here.
@@ -112,13 +116,14 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
112116 * VLAN is not 0 (leave it there for 802.1p).
113117 */
114118 if (vlan_id )
115- vlan_vid_del (real_dev , htons ( ETH_P_8021Q ) , vlan_id );
119+ vlan_vid_del (real_dev , vlan -> vlan_proto , vlan_id );
116120
117121 /* Get rid of the vlan's reference to real_dev */
118122 dev_put (real_dev );
119123}
120124
121- int vlan_check_real_dev (struct net_device * real_dev , u16 vlan_id )
125+ int vlan_check_real_dev (struct net_device * real_dev ,
126+ __be16 protocol , u16 vlan_id )
122127{
123128 const char * name = real_dev -> name ;
124129
@@ -127,7 +132,7 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
127132 return - EOPNOTSUPP ;
128133 }
129134
130- if (vlan_find_dev (real_dev , vlan_id ) != NULL )
135+ if (vlan_find_dev (real_dev , protocol , vlan_id ) != NULL )
131136 return - EEXIST ;
132137
133138 return 0 ;
@@ -142,7 +147,7 @@ int register_vlan_dev(struct net_device *dev)
142147 struct vlan_group * grp ;
143148 int err ;
144149
145- err = vlan_vid_add (real_dev , htons ( ETH_P_8021Q ) , vlan_id );
150+ err = vlan_vid_add (real_dev , vlan -> vlan_proto , vlan_id );
146151 if (err )
147152 return err ;
148153
@@ -160,7 +165,7 @@ int register_vlan_dev(struct net_device *dev)
160165 goto out_uninit_gvrp ;
161166 }
162167
163- err = vlan_group_prealloc_vid (grp , vlan_id );
168+ err = vlan_group_prealloc_vid (grp , vlan -> vlan_proto , vlan_id );
164169 if (err < 0 )
165170 goto out_uninit_mvrp ;
166171
@@ -181,7 +186,7 @@ int register_vlan_dev(struct net_device *dev)
181186 /* So, got the sucker initialized, now lets place
182187 * it into our local structure.
183188 */
184- vlan_group_set_device (grp , vlan_id , dev );
189+ vlan_group_set_device (grp , vlan -> vlan_proto , vlan_id , dev );
185190 grp -> nr_vlan_devs ++ ;
186191
187192 return 0 ;
@@ -195,7 +200,7 @@ int register_vlan_dev(struct net_device *dev)
195200 if (grp -> nr_vlan_devs == 0 )
196201 vlan_gvrp_uninit_applicant (real_dev );
197202out_vid_del :
198- vlan_vid_del (real_dev , htons ( ETH_P_8021Q ) , vlan_id );
203+ vlan_vid_del (real_dev , vlan -> vlan_proto , vlan_id );
199204 return err ;
200205}
201206
@@ -213,7 +218,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
213218 if (vlan_id >= VLAN_VID_MASK )
214219 return - ERANGE ;
215220
216- err = vlan_check_real_dev (real_dev , vlan_id );
221+ err = vlan_check_real_dev (real_dev , htons ( ETH_P_8021Q ), vlan_id );
217222 if (err < 0 )
218223 return err ;
219224
@@ -255,6 +260,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
255260 new_dev -> mtu = real_dev -> mtu ;
256261 new_dev -> priv_flags |= (real_dev -> priv_flags & IFF_UNICAST_FLT );
257262
263+ vlan_dev_priv (new_dev )-> vlan_proto = htons (ETH_P_8021Q );
258264 vlan_dev_priv (new_dev )-> vlan_id = vlan_id ;
259265 vlan_dev_priv (new_dev )-> real_dev = real_dev ;
260266 vlan_dev_priv (new_dev )-> dent = NULL ;
@@ -341,6 +347,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
341347 int i , flgs ;
342348 struct net_device * vlandev ;
343349 struct vlan_dev_priv * vlan ;
350+ bool last = false;
344351 LIST_HEAD (list );
345352
346353 if (is_vlan_dev (dev ))
@@ -365,22 +372,13 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
365372 switch (event ) {
366373 case NETDEV_CHANGE :
367374 /* Propagate real device state to vlan devices */
368- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
369- vlandev = vlan_group_get_device (grp , i );
370- if (!vlandev )
371- continue ;
372-
375+ vlan_group_for_each_dev (grp , i , vlandev )
373376 netif_stacked_transfer_operstate (dev , vlandev );
374- }
375377 break ;
376378
377379 case NETDEV_CHANGEADDR :
378380 /* Adjust unicast filters on underlying device */
379- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
380- vlandev = vlan_group_get_device (grp , i );
381- if (!vlandev )
382- continue ;
383-
381+ vlan_group_for_each_dev (grp , i , vlandev ) {
384382 flgs = vlandev -> flags ;
385383 if (!(flgs & IFF_UP ))
386384 continue ;
@@ -390,11 +388,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
390388 break ;
391389
392390 case NETDEV_CHANGEMTU :
393- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
394- vlandev = vlan_group_get_device (grp , i );
395- if (!vlandev )
396- continue ;
397-
391+ vlan_group_for_each_dev (grp , i , vlandev ) {
398392 if (vlandev -> mtu <= dev -> mtu )
399393 continue ;
400394
@@ -404,26 +398,16 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
404398
405399 case NETDEV_FEAT_CHANGE :
406400 /* Propagate device features to underlying device */
407- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
408- vlandev = vlan_group_get_device (grp , i );
409- if (!vlandev )
410- continue ;
411-
401+ vlan_group_for_each_dev (grp , i , vlandev )
412402 vlan_transfer_features (dev , vlandev );
413- }
414-
415403 break ;
416404
417405 case NETDEV_DOWN :
418406 if (dev -> features & NETIF_F_HW_VLAN_CTAG_FILTER )
419407 vlan_vid_del (dev , htons (ETH_P_8021Q ), 0 );
420408
421409 /* Put all VLANs for this dev in the down state too. */
422- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
423- vlandev = vlan_group_get_device (grp , i );
424- if (!vlandev )
425- continue ;
426-
410+ vlan_group_for_each_dev (grp , i , vlandev ) {
427411 flgs = vlandev -> flags ;
428412 if (!(flgs & IFF_UP ))
429413 continue ;
@@ -437,11 +421,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
437421
438422 case NETDEV_UP :
439423 /* Put all VLANs for this dev in the up state too. */
440- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
441- vlandev = vlan_group_get_device (grp , i );
442- if (!vlandev )
443- continue ;
444-
424+ vlan_group_for_each_dev (grp , i , vlandev ) {
445425 flgs = vlandev -> flags ;
446426 if (flgs & IFF_UP )
447427 continue ;
@@ -458,17 +438,15 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
458438 if (dev -> reg_state != NETREG_UNREGISTERING )
459439 break ;
460440
461- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
462- vlandev = vlan_group_get_device (grp , i );
463- if (!vlandev )
464- continue ;
465-
441+ vlan_group_for_each_dev (grp , i , vlandev ) {
466442 /* removal of last vid destroys vlan_info, abort
467443 * afterwards */
468444 if (vlan_info -> nr_vids == 1 )
469- i = VLAN_N_VID ;
445+ last = true ;
470446
471447 unregister_vlan_dev (vlandev , & list );
448+ if (last )
449+ break ;
472450 }
473451 unregister_netdevice_many (& list );
474452 break ;
@@ -482,13 +460,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
482460 case NETDEV_NOTIFY_PEERS :
483461 case NETDEV_BONDING_FAILOVER :
484462 /* Propagate to vlan devices */
485- for (i = 0 ; i < VLAN_N_VID ; i ++ ) {
486- vlandev = vlan_group_get_device (grp , i );
487- if (!vlandev )
488- continue ;
489-
463+ vlan_group_for_each_dev (grp , i , vlandev )
490464 call_netdevice_notifiers (event , vlandev );
491- }
492465 break ;
493466 }
494467
0 commit comments