diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-13 15:05:22 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:14:38 -0400 |
commit | c17d8874f9959070552fddf1b4e1d73c0c144c0f (patch) | |
tree | ea5a61e37f71218f8cb69033293a55631511b470 /net/8021q | |
parent | 9ba2cd656021e7f70038ba9d551224e04d0bfcef (diff) |
[VLAN]: Convert name-based configuration functions to struct netdevice *
Move the device lookup and checks to the ioctl handler under the RTNL and
change all name-based interfaces to take a struct net_device * instead.
This allows to use them from a netlink interface, which identifies devices
based on ifindex not name. It also avoids races between the ioctl interface
and the (upcoming) netlink interface since now all changes happen under the
RTNL.
As a nice side effect this greatly simplifies error handling in the helper
functions and fixes a number of incorrect error codes like -EINVAL for
device not found.
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.c | 153 | ||||
-rw-r--r-- | net/8021q/vlan.h | 13 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 142 |
3 files changed, 109 insertions, 199 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index de78c9dd713b..3678f0719934 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -278,43 +278,16 @@ static int unregister_vlan_dev(struct net_device *real_dev, | |||
278 | return ret; | 278 | return ret; |
279 | } | 279 | } |
280 | 280 | ||
281 | static int unregister_vlan_device(const char *vlan_IF_name) | 281 | static int unregister_vlan_device(struct net_device *dev) |
282 | { | 282 | { |
283 | struct net_device *dev = NULL; | ||
284 | int ret; | 283 | int ret; |
285 | 284 | ||
285 | ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, | ||
286 | VLAN_DEV_INFO(dev)->vlan_id); | ||
287 | unregister_netdevice(dev); | ||
286 | 288 | ||
287 | dev = dev_get_by_name(vlan_IF_name); | 289 | if (ret == 1) |
288 | ret = -EINVAL; | 290 | ret = 0; |
289 | if (dev) { | ||
290 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
291 | rtnl_lock(); | ||
292 | |||
293 | ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, | ||
294 | VLAN_DEV_INFO(dev)->vlan_id); | ||
295 | |||
296 | dev_put(dev); | ||
297 | unregister_netdevice(dev); | ||
298 | |||
299 | rtnl_unlock(); | ||
300 | |||
301 | if (ret == 1) | ||
302 | ret = 0; | ||
303 | } else { | ||
304 | printk(VLAN_ERR | ||
305 | "%s: ERROR: Tried to remove a non-vlan device " | ||
306 | "with VLAN code, name: %s priv_flags: %hX\n", | ||
307 | __FUNCTION__, dev->name, dev->priv_flags); | ||
308 | dev_put(dev); | ||
309 | ret = -EPERM; | ||
310 | } | ||
311 | } else { | ||
312 | #ifdef VLAN_DEBUG | ||
313 | printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__); | ||
314 | #endif | ||
315 | ret = -EINVAL; | ||
316 | } | ||
317 | |||
318 | return ret; | 291 | return ret; |
319 | } | 292 | } |
320 | 293 | ||
@@ -378,12 +351,11 @@ static struct lock_class_key vlan_netdev_xmit_lock_key; | |||
378 | * Returns the device that was created, or NULL if there was | 351 | * Returns the device that was created, or NULL if there was |
379 | * an error of some kind. | 352 | * an error of some kind. |
380 | */ | 353 | */ |
381 | static struct net_device *register_vlan_device(const char *eth_IF_name, | 354 | static struct net_device *register_vlan_device(struct net_device *real_dev, |
382 | unsigned short VLAN_ID) | 355 | unsigned short VLAN_ID) |
383 | { | 356 | { |
384 | struct vlan_group *grp; | 357 | struct vlan_group *grp; |
385 | struct net_device *new_dev; | 358 | struct net_device *new_dev; |
386 | struct net_device *real_dev; /* the ethernet device */ | ||
387 | char name[IFNAMSIZ]; | 359 | char name[IFNAMSIZ]; |
388 | int i; | 360 | int i; |
389 | 361 | ||
@@ -395,46 +367,36 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, | |||
395 | if (VLAN_ID >= VLAN_VID_MASK) | 367 | if (VLAN_ID >= VLAN_VID_MASK) |
396 | goto out_ret_null; | 368 | goto out_ret_null; |
397 | 369 | ||
398 | /* find the device relating to eth_IF_name. */ | ||
399 | real_dev = dev_get_by_name(eth_IF_name); | ||
400 | if (!real_dev) | ||
401 | goto out_ret_null; | ||
402 | |||
403 | if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { | 370 | if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { |
404 | printk(VLAN_DBG "%s: VLANs not supported on %s.\n", | 371 | printk(VLAN_DBG "%s: VLANs not supported on %s.\n", |
405 | __FUNCTION__, real_dev->name); | 372 | __FUNCTION__, real_dev->name); |
406 | goto out_put_dev; | 373 | goto out_ret_null; |
407 | } | 374 | } |
408 | 375 | ||
409 | if ((real_dev->features & NETIF_F_HW_VLAN_RX) && | 376 | if ((real_dev->features & NETIF_F_HW_VLAN_RX) && |
410 | !real_dev->vlan_rx_register) { | 377 | !real_dev->vlan_rx_register) { |
411 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", | 378 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", |
412 | __FUNCTION__, real_dev->name); | 379 | __FUNCTION__, real_dev->name); |
413 | goto out_put_dev; | 380 | goto out_ret_null; |
414 | } | 381 | } |
415 | 382 | ||
416 | if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && | 383 | if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && |
417 | (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { | 384 | (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { |
418 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", | 385 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", |
419 | __FUNCTION__, real_dev->name); | 386 | __FUNCTION__, real_dev->name); |
420 | goto out_put_dev; | 387 | goto out_ret_null; |
421 | } | 388 | } |
422 | 389 | ||
423 | /* From this point on, all the data structures must remain | ||
424 | * consistent. | ||
425 | */ | ||
426 | rtnl_lock(); | ||
427 | |||
428 | /* The real device must be up and operating in order to | 390 | /* The real device must be up and operating in order to |
429 | * assosciate a VLAN device with it. | 391 | * assosciate a VLAN device with it. |
430 | */ | 392 | */ |
431 | if (!(real_dev->flags & IFF_UP)) | 393 | if (!(real_dev->flags & IFF_UP)) |
432 | goto out_unlock; | 394 | goto out_ret_null; |
433 | 395 | ||
434 | if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) { | 396 | if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) { |
435 | /* was already registered. */ | 397 | /* was already registered. */ |
436 | printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); | 398 | printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); |
437 | goto out_unlock; | 399 | goto out_ret_null; |
438 | } | 400 | } |
439 | 401 | ||
440 | /* Gotta set up the fields for the device. */ | 402 | /* Gotta set up the fields for the device. */ |
@@ -471,7 +433,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, | |||
471 | vlan_setup); | 433 | vlan_setup); |
472 | 434 | ||
473 | if (new_dev == NULL) | 435 | if (new_dev == NULL) |
474 | goto out_unlock; | 436 | goto out_ret_null; |
475 | 437 | ||
476 | #ifdef VLAN_DEBUG | 438 | #ifdef VLAN_DEBUG |
477 | printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); | 439 | printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); |
@@ -577,9 +539,8 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, | |||
577 | if (real_dev->features & NETIF_F_HW_VLAN_FILTER) | 539 | if (real_dev->features & NETIF_F_HW_VLAN_FILTER) |
578 | real_dev->vlan_rx_add_vid(real_dev, VLAN_ID); | 540 | real_dev->vlan_rx_add_vid(real_dev, VLAN_ID); |
579 | 541 | ||
580 | rtnl_unlock(); | 542 | /* Account for reference in struct vlan_dev_info */ |
581 | 543 | dev_hold(real_dev); | |
582 | |||
583 | #ifdef VLAN_DEBUG | 544 | #ifdef VLAN_DEBUG |
584 | printk(VLAN_DBG "Allocated new device successfully, returning.\n"); | 545 | printk(VLAN_DBG "Allocated new device successfully, returning.\n"); |
585 | #endif | 546 | #endif |
@@ -590,17 +551,11 @@ out_free_arrays: | |||
590 | 551 | ||
591 | out_free_unregister: | 552 | out_free_unregister: |
592 | unregister_netdev(new_dev); | 553 | unregister_netdev(new_dev); |
593 | goto out_unlock; | 554 | goto out_ret_null; |
594 | 555 | ||
595 | out_free_newdev: | 556 | out_free_newdev: |
596 | free_netdev(new_dev); | 557 | free_netdev(new_dev); |
597 | 558 | ||
598 | out_unlock: | ||
599 | rtnl_unlock(); | ||
600 | |||
601 | out_put_dev: | ||
602 | dev_put(real_dev); | ||
603 | |||
604 | out_ret_null: | 559 | out_ret_null: |
605 | return NULL; | 560 | return NULL; |
606 | } | 561 | } |
@@ -693,9 +648,10 @@ out: | |||
693 | */ | 648 | */ |
694 | static int vlan_ioctl_handler(void __user *arg) | 649 | static int vlan_ioctl_handler(void __user *arg) |
695 | { | 650 | { |
696 | int err = 0; | 651 | int err; |
697 | unsigned short vid = 0; | 652 | unsigned short vid = 0; |
698 | struct vlan_ioctl_args args; | 653 | struct vlan_ioctl_args args; |
654 | struct net_device *dev = NULL; | ||
699 | 655 | ||
700 | if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) | 656 | if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) |
701 | return -EFAULT; | 657 | return -EFAULT; |
@@ -708,35 +664,61 @@ static int vlan_ioctl_handler(void __user *arg) | |||
708 | printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd); | 664 | printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd); |
709 | #endif | 665 | #endif |
710 | 666 | ||
667 | rtnl_lock(); | ||
668 | |||
711 | switch (args.cmd) { | 669 | switch (args.cmd) { |
712 | case SET_VLAN_INGRESS_PRIORITY_CMD: | 670 | case SET_VLAN_INGRESS_PRIORITY_CMD: |
671 | case SET_VLAN_EGRESS_PRIORITY_CMD: | ||
672 | case SET_VLAN_FLAG_CMD: | ||
673 | case ADD_VLAN_CMD: | ||
674 | case DEL_VLAN_CMD: | ||
675 | case GET_VLAN_REALDEV_NAME_CMD: | ||
676 | case GET_VLAN_VID_CMD: | ||
677 | err = -ENODEV; | ||
678 | dev = __dev_get_by_name(args.device1); | ||
679 | if (!dev) | ||
680 | goto out; | ||
681 | |||
682 | err = -EINVAL; | ||
683 | if (args.cmd != ADD_VLAN_CMD && | ||
684 | !(dev->priv_flags & IFF_802_1Q_VLAN)) | ||
685 | goto out; | ||
686 | } | ||
687 | |||
688 | switch (args.cmd) { | ||
689 | case SET_VLAN_INGRESS_PRIORITY_CMD: | ||
690 | err = -EPERM; | ||
713 | if (!capable(CAP_NET_ADMIN)) | 691 | if (!capable(CAP_NET_ADMIN)) |
714 | return -EPERM; | 692 | break; |
715 | err = vlan_dev_set_ingress_priority(args.device1, | 693 | vlan_dev_set_ingress_priority(dev, |
716 | args.u.skb_priority, | 694 | args.u.skb_priority, |
717 | args.vlan_qos); | 695 | args.vlan_qos); |
718 | break; | 696 | break; |
719 | 697 | ||
720 | case SET_VLAN_EGRESS_PRIORITY_CMD: | 698 | case SET_VLAN_EGRESS_PRIORITY_CMD: |
699 | err = -EPERM; | ||
721 | if (!capable(CAP_NET_ADMIN)) | 700 | if (!capable(CAP_NET_ADMIN)) |
722 | return -EPERM; | 701 | break; |
723 | err = vlan_dev_set_egress_priority(args.device1, | 702 | err = vlan_dev_set_egress_priority(dev, |
724 | args.u.skb_priority, | 703 | args.u.skb_priority, |
725 | args.vlan_qos); | 704 | args.vlan_qos); |
726 | break; | 705 | break; |
727 | 706 | ||
728 | case SET_VLAN_FLAG_CMD: | 707 | case SET_VLAN_FLAG_CMD: |
708 | err = -EPERM; | ||
729 | if (!capable(CAP_NET_ADMIN)) | 709 | if (!capable(CAP_NET_ADMIN)) |
730 | return -EPERM; | 710 | break; |
731 | err = vlan_dev_set_vlan_flag(args.device1, | 711 | err = vlan_dev_set_vlan_flag(dev, |
732 | args.u.flag, | 712 | args.u.flag, |
733 | args.vlan_qos); | 713 | args.vlan_qos); |
734 | break; | 714 | break; |
735 | 715 | ||
736 | case SET_VLAN_NAME_TYPE_CMD: | 716 | case SET_VLAN_NAME_TYPE_CMD: |
717 | err = -EPERM; | ||
737 | if (!capable(CAP_NET_ADMIN)) | 718 | if (!capable(CAP_NET_ADMIN)) |
738 | return -EPERM; | 719 | return -EPERM; |
739 | if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) { | 720 | if ((args.u.name_type >= 0) && |
721 | (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { | ||
740 | vlan_name_type = args.u.name_type; | 722 | vlan_name_type = args.u.name_type; |
741 | err = 0; | 723 | err = 0; |
742 | } else { | 724 | } else { |
@@ -745,13 +727,10 @@ static int vlan_ioctl_handler(void __user *arg) | |||
745 | break; | 727 | break; |
746 | 728 | ||
747 | case ADD_VLAN_CMD: | 729 | case ADD_VLAN_CMD: |
730 | err = -EPERM; | ||
748 | if (!capable(CAP_NET_ADMIN)) | 731 | if (!capable(CAP_NET_ADMIN)) |
749 | return -EPERM; | 732 | break; |
750 | /* we have been given the name of the Ethernet Device we want to | 733 | if (register_vlan_device(dev, args.u.VID)) { |
751 | * talk to: args.dev1 We also have the | ||
752 | * VLAN ID: args.u.VID | ||
753 | */ | ||
754 | if (register_vlan_device(args.device1, args.u.VID)) { | ||
755 | err = 0; | 734 | err = 0; |
756 | } else { | 735 | } else { |
757 | err = -EINVAL; | 736 | err = -EINVAL; |
@@ -759,12 +738,10 @@ static int vlan_ioctl_handler(void __user *arg) | |||
759 | break; | 738 | break; |
760 | 739 | ||
761 | case DEL_VLAN_CMD: | 740 | case DEL_VLAN_CMD: |
741 | err = -EPERM; | ||
762 | if (!capable(CAP_NET_ADMIN)) | 742 | if (!capable(CAP_NET_ADMIN)) |
763 | return -EPERM; | 743 | break; |
764 | /* Here, the args.dev1 is the actual VLAN we want | 744 | err = unregister_vlan_device(dev); |
765 | * to get rid of. | ||
766 | */ | ||
767 | err = unregister_vlan_device(args.device1); | ||
768 | break; | 745 | break; |
769 | 746 | ||
770 | case GET_VLAN_INGRESS_PRIORITY_CMD: | 747 | case GET_VLAN_INGRESS_PRIORITY_CMD: |
@@ -788,9 +765,7 @@ static int vlan_ioctl_handler(void __user *arg) | |||
788 | err = -EINVAL; | 765 | err = -EINVAL; |
789 | break; | 766 | break; |
790 | case GET_VLAN_REALDEV_NAME_CMD: | 767 | case GET_VLAN_REALDEV_NAME_CMD: |
791 | err = vlan_dev_get_realdev_name(args.device1, args.u.device2); | 768 | vlan_dev_get_realdev_name(dev, args.u.device2); |
792 | if (err) | ||
793 | goto out; | ||
794 | if (copy_to_user(arg, &args, | 769 | if (copy_to_user(arg, &args, |
795 | sizeof(struct vlan_ioctl_args))) { | 770 | sizeof(struct vlan_ioctl_args))) { |
796 | err = -EFAULT; | 771 | err = -EFAULT; |
@@ -798,9 +773,7 @@ static int vlan_ioctl_handler(void __user *arg) | |||
798 | break; | 773 | break; |
799 | 774 | ||
800 | case GET_VLAN_VID_CMD: | 775 | case GET_VLAN_VID_CMD: |
801 | err = vlan_dev_get_vid(args.device1, &vid); | 776 | vlan_dev_get_vid(dev, &vid); |
802 | if (err) | ||
803 | goto out; | ||
804 | args.u.VID = vid; | 777 | args.u.VID = vid; |
805 | if (copy_to_user(arg, &args, | 778 | if (copy_to_user(arg, &args, |
806 | sizeof(struct vlan_ioctl_args))) { | 779 | sizeof(struct vlan_ioctl_args))) { |
@@ -812,9 +785,11 @@ static int vlan_ioctl_handler(void __user *arg) | |||
812 | /* pass on to underlying device instead?? */ | 785 | /* pass on to underlying device instead?? */ |
813 | printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", | 786 | printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", |
814 | __FUNCTION__, args.cmd); | 787 | __FUNCTION__, args.cmd); |
815 | return -EINVAL; | 788 | err = -EINVAL; |
789 | break; | ||
816 | } | 790 | } |
817 | out: | 791 | out: |
792 | rtnl_unlock(); | ||
818 | return err; | 793 | return err; |
819 | } | 794 | } |
820 | 795 | ||
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 1976cdba8f72..b83739017e9d 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -62,11 +62,14 @@ int vlan_dev_set_mac_address(struct net_device *dev, void* addr); | |||
62 | int vlan_dev_open(struct net_device* dev); | 62 | int vlan_dev_open(struct net_device* dev); |
63 | int vlan_dev_stop(struct net_device* dev); | 63 | int vlan_dev_stop(struct net_device* dev); |
64 | int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); | 64 | int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); |
65 | int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); | 65 | void vlan_dev_set_ingress_priority(const struct net_device *dev, |
66 | int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); | 66 | u32 skb_prio, short vlan_prio); |
67 | int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val); | 67 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
68 | int vlan_dev_get_realdev_name(const char* dev_name, char* result); | 68 | u32 skb_prio, short vlan_prio); |
69 | int vlan_dev_get_vid(const char* dev_name, unsigned short* result); | 69 | int vlan_dev_set_vlan_flag(const struct net_device *dev, |
70 | u32 flag, short flag_val); | ||
71 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); | ||
72 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result); | ||
70 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); | 73 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); |
71 | 74 | ||
72 | #endif /* !(__BEN_VLAN_802_1Q_INC__) */ | 75 | #endif /* !(__BEN_VLAN_802_1Q_INC__) */ |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ec46084f44b4..05a23601f670 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -534,136 +534,68 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) | |||
534 | return 0; | 534 | return 0; |
535 | } | 535 | } |
536 | 536 | ||
537 | int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) | 537 | void vlan_dev_set_ingress_priority(const struct net_device *dev, |
538 | u32 skb_prio, short vlan_prio) | ||
538 | { | 539 | { |
539 | struct net_device *dev = dev_get_by_name(dev_name); | 540 | VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio; |
540 | |||
541 | if (dev) { | ||
542 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
543 | /* see if a priority mapping exists.. */ | ||
544 | VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio; | ||
545 | dev_put(dev); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | dev_put(dev); | ||
550 | } | ||
551 | return -EINVAL; | ||
552 | } | 541 | } |
553 | 542 | ||
554 | int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) | 543 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
544 | u32 skb_prio, short vlan_prio) | ||
555 | { | 545 | { |
556 | struct net_device *dev = dev_get_by_name(dev_name); | ||
557 | struct vlan_priority_tci_mapping *mp = NULL; | 546 | struct vlan_priority_tci_mapping *mp = NULL; |
558 | struct vlan_priority_tci_mapping *np; | 547 | struct vlan_priority_tci_mapping *np; |
559 | 548 | ||
560 | if (dev) { | 549 | /* See if a priority mapping exists.. */ |
561 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 550 | mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; |
562 | /* See if a priority mapping exists.. */ | 551 | while (mp) { |
563 | mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; | 552 | if (mp->priority == skb_prio) { |
564 | while (mp) { | 553 | mp->vlan_qos = ((vlan_prio << 13) & 0xE000); |
565 | if (mp->priority == skb_prio) { | 554 | return 0; |
566 | mp->vlan_qos = ((vlan_prio << 13) & 0xE000); | ||
567 | dev_put(dev); | ||
568 | return 0; | ||
569 | } | ||
570 | mp = mp->next; | ||
571 | } | ||
572 | |||
573 | /* Create a new mapping then. */ | ||
574 | mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; | ||
575 | np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); | ||
576 | if (np) { | ||
577 | np->next = mp; | ||
578 | np->priority = skb_prio; | ||
579 | np->vlan_qos = ((vlan_prio << 13) & 0xE000); | ||
580 | VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np; | ||
581 | dev_put(dev); | ||
582 | return 0; | ||
583 | } else { | ||
584 | dev_put(dev); | ||
585 | return -ENOBUFS; | ||
586 | } | ||
587 | } | 555 | } |
588 | dev_put(dev); | 556 | mp = mp->next; |
589 | } | 557 | } |
590 | return -EINVAL; | 558 | |
559 | /* Create a new mapping then. */ | ||
560 | mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; | ||
561 | np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); | ||
562 | if (!np) | ||
563 | return -ENOBUFS; | ||
564 | |||
565 | np->next = mp; | ||
566 | np->priority = skb_prio; | ||
567 | np->vlan_qos = ((vlan_prio << 13) & 0xE000); | ||
568 | VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np; | ||
569 | return 0; | ||
591 | } | 570 | } |
592 | 571 | ||
593 | /* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */ | 572 | /* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */ |
594 | int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val) | 573 | int vlan_dev_set_vlan_flag(const struct net_device *dev, |
574 | u32 flag, short flag_val) | ||
595 | { | 575 | { |
596 | struct net_device *dev = dev_get_by_name(dev_name); | 576 | /* verify flag is supported */ |
597 | 577 | if (flag == 1) { | |
598 | if (dev) { | 578 | if (flag_val) { |
599 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 579 | VLAN_DEV_INFO(dev)->flags |= 1; |
600 | /* verify flag is supported */ | ||
601 | if (flag == 1) { | ||
602 | if (flag_val) { | ||
603 | VLAN_DEV_INFO(dev)->flags |= 1; | ||
604 | } else { | ||
605 | VLAN_DEV_INFO(dev)->flags &= ~1; | ||
606 | } | ||
607 | dev_put(dev); | ||
608 | return 0; | ||
609 | } else { | ||
610 | printk(KERN_ERR "%s: flag %i is not valid.\n", | ||
611 | __FUNCTION__, (int)(flag)); | ||
612 | dev_put(dev); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | } else { | 580 | } else { |
616 | printk(KERN_ERR | 581 | VLAN_DEV_INFO(dev)->flags &= ~1; |
617 | "%s: %s is not a vlan device, priv_flags: %hX.\n", | ||
618 | __FUNCTION__, dev->name, dev->priv_flags); | ||
619 | dev_put(dev); | ||
620 | } | 582 | } |
621 | } else { | 583 | return 0; |
622 | printk(KERN_ERR "%s: Could not find device: %s\n", | ||
623 | __FUNCTION__, dev_name); | ||
624 | } | 584 | } |
625 | 585 | printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag); | |
626 | return -EINVAL; | 586 | return -EINVAL; |
627 | } | 587 | } |
628 | 588 | ||
629 | 589 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result) | |
630 | int vlan_dev_get_realdev_name(const char *dev_name, char* result) | ||
631 | { | 590 | { |
632 | struct net_device *dev = dev_get_by_name(dev_name); | 591 | strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23); |
633 | int rv = 0; | ||
634 | if (dev) { | ||
635 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
636 | strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23); | ||
637 | rv = 0; | ||
638 | } else { | ||
639 | rv = -EINVAL; | ||
640 | } | ||
641 | dev_put(dev); | ||
642 | } else { | ||
643 | rv = -ENODEV; | ||
644 | } | ||
645 | return rv; | ||
646 | } | 592 | } |
647 | 593 | ||
648 | int vlan_dev_get_vid(const char *dev_name, unsigned short* result) | 594 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result) |
649 | { | 595 | { |
650 | struct net_device *dev = dev_get_by_name(dev_name); | 596 | *result = VLAN_DEV_INFO(dev)->vlan_id; |
651 | int rv = 0; | ||
652 | if (dev) { | ||
653 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
654 | *result = VLAN_DEV_INFO(dev)->vlan_id; | ||
655 | rv = 0; | ||
656 | } else { | ||
657 | rv = -EINVAL; | ||
658 | } | ||
659 | dev_put(dev); | ||
660 | } else { | ||
661 | rv = -ENODEV; | ||
662 | } | ||
663 | return rv; | ||
664 | } | 597 | } |
665 | 598 | ||
666 | |||
667 | int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p) | 599 | int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p) |
668 | { | 600 | { |
669 | struct sockaddr *addr = (struct sockaddr *)(addr_struct_p); | 601 | struct sockaddr *addr = (struct sockaddr *)(addr_struct_p); |