diff options
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/vlan.c | 3 | ||||
-rw-r--r-- | net/8021q/vlan.h | 1 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 167 |
3 files changed, 24 insertions, 147 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index abb9900edb3f..cda936b77d22 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -373,10 +373,11 @@ void vlan_setup(struct net_device *new_dev) | |||
373 | new_dev->open = vlan_dev_open; | 373 | new_dev->open = vlan_dev_open; |
374 | new_dev->stop = vlan_dev_stop; | 374 | new_dev->stop = vlan_dev_stop; |
375 | new_dev->set_multicast_list = vlan_dev_set_multicast_list; | 375 | new_dev->set_multicast_list = vlan_dev_set_multicast_list; |
376 | new_dev->change_rx_flags = vlan_change_rx_flags; | ||
376 | new_dev->destructor = free_netdev; | 377 | new_dev->destructor = free_netdev; |
377 | new_dev->do_ioctl = vlan_dev_ioctl; | 378 | new_dev->do_ioctl = vlan_dev_ioctl; |
378 | 379 | ||
379 | memset(new_dev->broadcast, 0, sizeof(ETH_ALEN)); | 380 | memset(new_dev->broadcast, 0, ETH_ALEN); |
380 | } | 381 | } |
381 | 382 | ||
382 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) | 383 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) |
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 62ce1c519aab..7df5b2935579 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -69,6 +69,7 @@ int vlan_dev_set_vlan_flag(const struct net_device *dev, | |||
69 | u32 flag, short flag_val); | 69 | u32 flag, short flag_val); |
70 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); | 70 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); |
71 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result); | 71 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result); |
72 | void vlan_change_rx_flags(struct net_device *dev, int change); | ||
72 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); | 73 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); |
73 | 74 | ||
74 | int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id); | 75 | int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id); |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index d4a62d1b52b4..4d2aa4dd42ac 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -612,90 +612,6 @@ void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result) | |||
612 | *result = VLAN_DEV_INFO(dev)->vlan_id; | 612 | *result = VLAN_DEV_INFO(dev)->vlan_id; |
613 | } | 613 | } |
614 | 614 | ||
615 | static inline int vlan_dmi_equals(struct dev_mc_list *dmi1, | ||
616 | struct dev_mc_list *dmi2) | ||
617 | { | ||
618 | return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) && | ||
619 | (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0)); | ||
620 | } | ||
621 | |||
622 | /** dmi is a single entry into a dev_mc_list, a single node. mc_list is | ||
623 | * an entire list, and we'll iterate through it. | ||
624 | */ | ||
625 | static int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) | ||
626 | { | ||
627 | struct dev_mc_list *idmi; | ||
628 | |||
629 | for (idmi = mc_list; idmi != NULL; ) { | ||
630 | if (vlan_dmi_equals(dmi, idmi)) { | ||
631 | if (dmi->dmi_users > idmi->dmi_users) | ||
632 | return 1; | ||
633 | else | ||
634 | return 0; | ||
635 | } else { | ||
636 | idmi = idmi->next; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | return 1; | ||
641 | } | ||
642 | |||
643 | static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list) | ||
644 | { | ||
645 | struct dev_mc_list *dmi = mc_list; | ||
646 | struct dev_mc_list *next; | ||
647 | |||
648 | while(dmi) { | ||
649 | next = dmi->next; | ||
650 | kfree(dmi); | ||
651 | dmi = next; | ||
652 | } | ||
653 | } | ||
654 | |||
655 | static void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info) | ||
656 | { | ||
657 | struct dev_mc_list *dmi, *new_dmi; | ||
658 | |||
659 | vlan_destroy_mc_list(vlan_info->old_mc_list); | ||
660 | vlan_info->old_mc_list = NULL; | ||
661 | |||
662 | for (dmi = mc_list; dmi != NULL; dmi = dmi->next) { | ||
663 | new_dmi = kmalloc(sizeof(*new_dmi), GFP_ATOMIC); | ||
664 | if (new_dmi == NULL) { | ||
665 | printk(KERN_ERR "vlan: cannot allocate memory. " | ||
666 | "Multicast may not work properly from now.\n"); | ||
667 | return; | ||
668 | } | ||
669 | |||
670 | /* Copy whole structure, then make new 'next' pointer */ | ||
671 | *new_dmi = *dmi; | ||
672 | new_dmi->next = vlan_info->old_mc_list; | ||
673 | vlan_info->old_mc_list = new_dmi; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | static void vlan_flush_mc_list(struct net_device *dev) | ||
678 | { | ||
679 | struct dev_mc_list *dmi = dev->mc_list; | ||
680 | |||
681 | while (dmi) { | ||
682 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n", | ||
683 | dev->name, | ||
684 | dmi->dmi_addr[0], | ||
685 | dmi->dmi_addr[1], | ||
686 | dmi->dmi_addr[2], | ||
687 | dmi->dmi_addr[3], | ||
688 | dmi->dmi_addr[4], | ||
689 | dmi->dmi_addr[5]); | ||
690 | dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
691 | dmi = dev->mc_list; | ||
692 | } | ||
693 | |||
694 | /* dev->mc_list is NULL by the time we get here. */ | ||
695 | vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list); | ||
696 | VLAN_DEV_INFO(dev)->old_mc_list = NULL; | ||
697 | } | ||
698 | |||
699 | int vlan_dev_open(struct net_device *dev) | 615 | int vlan_dev_open(struct net_device *dev) |
700 | { | 616 | { |
701 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | 617 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); |
@@ -712,6 +628,11 @@ int vlan_dev_open(struct net_device *dev) | |||
712 | } | 628 | } |
713 | memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN); | 629 | memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN); |
714 | 630 | ||
631 | if (dev->flags & IFF_ALLMULTI) | ||
632 | dev_set_allmulti(real_dev, 1); | ||
633 | if (dev->flags & IFF_PROMISC) | ||
634 | dev_set_promiscuity(real_dev, 1); | ||
635 | |||
715 | return 0; | 636 | return 0; |
716 | } | 637 | } |
717 | 638 | ||
@@ -719,7 +640,11 @@ int vlan_dev_stop(struct net_device *dev) | |||
719 | { | 640 | { |
720 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; | 641 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
721 | 642 | ||
722 | vlan_flush_mc_list(dev); | 643 | dev_mc_unsync(real_dev, dev); |
644 | if (dev->flags & IFF_ALLMULTI) | ||
645 | dev_set_allmulti(real_dev, -1); | ||
646 | if (dev->flags & IFF_PROMISC) | ||
647 | dev_set_promiscuity(real_dev, -1); | ||
723 | 648 | ||
724 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 649 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
725 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); | 650 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); |
@@ -754,68 +679,18 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
754 | return err; | 679 | return err; |
755 | } | 680 | } |
756 | 681 | ||
757 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ | 682 | void vlan_change_rx_flags(struct net_device *dev, int change) |
758 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) | ||
759 | { | 683 | { |
760 | struct dev_mc_list *dmi; | 684 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
761 | struct net_device *real_dev; | ||
762 | int inc; | ||
763 | |||
764 | if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) { | ||
765 | /* Then it's a real vlan device, as far as we can tell.. */ | ||
766 | real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev; | ||
767 | |||
768 | /* compare the current promiscuity to the last promisc we had.. */ | ||
769 | inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity; | ||
770 | if (inc) { | ||
771 | printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n", | ||
772 | vlan_dev->name, inc); | ||
773 | dev_set_promiscuity(real_dev, inc); /* found in dev.c */ | ||
774 | VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity; | ||
775 | } | ||
776 | |||
777 | inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti; | ||
778 | if (inc) { | ||
779 | printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n", | ||
780 | vlan_dev->name, inc); | ||
781 | dev_set_allmulti(real_dev, inc); /* dev.c */ | ||
782 | VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti; | ||
783 | } | ||
784 | |||
785 | /* looking for addresses to add to master's list */ | ||
786 | for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) { | ||
787 | if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) { | ||
788 | dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
789 | printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", | ||
790 | vlan_dev->name, | ||
791 | dmi->dmi_addr[0], | ||
792 | dmi->dmi_addr[1], | ||
793 | dmi->dmi_addr[2], | ||
794 | dmi->dmi_addr[3], | ||
795 | dmi->dmi_addr[4], | ||
796 | dmi->dmi_addr[5]); | ||
797 | } | ||
798 | } | ||
799 | 685 | ||
800 | /* looking for addresses to delete from master's list */ | 686 | if (change & IFF_ALLMULTI) |
801 | for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) { | 687 | dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1); |
802 | if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) { | 688 | if (change & IFF_PROMISC) |
803 | /* if we think we should add it to the new list, then we should really | 689 | dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); |
804 | * delete it from the real list on the underlying device. | 690 | } |
805 | */ | ||
806 | dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
807 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", | ||
808 | vlan_dev->name, | ||
809 | dmi->dmi_addr[0], | ||
810 | dmi->dmi_addr[1], | ||
811 | dmi->dmi_addr[2], | ||
812 | dmi->dmi_addr[3], | ||
813 | dmi->dmi_addr[4], | ||
814 | dmi->dmi_addr[5]); | ||
815 | } | ||
816 | } | ||
817 | 691 | ||
818 | /* save multicast list */ | 692 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ |
819 | vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev)); | 693 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) |
820 | } | 694 | { |
695 | dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev); | ||
821 | } | 696 | } |