diff options
author | Patrick McHardy <kaber@trash.net> | 2007-07-14 21:53:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-07-14 21:53:28 -0400 |
commit | 56addd6eeeb4e11f5a0af7093ca078e0f29140e0 (patch) | |
tree | 814e84aa686d9fec602f977901634ebf576d039d /net | |
parent | 6c78dcbd47a68a7d25d2bee7a6c74b9136cb5fde (diff) |
[VLAN]: Use multicast list synchronization helpers
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan_dev.c | 131 |
1 files changed, 2 insertions, 129 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index dec7e62b2e10..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); |
@@ -724,8 +640,7 @@ int vlan_dev_stop(struct net_device *dev) | |||
724 | { | 640 | { |
725 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; | 641 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
726 | 642 | ||
727 | vlan_flush_mc_list(dev); | 643 | dev_mc_unsync(real_dev, dev); |
728 | |||
729 | if (dev->flags & IFF_ALLMULTI) | 644 | if (dev->flags & IFF_ALLMULTI) |
730 | dev_set_allmulti(real_dev, -1); | 645 | dev_set_allmulti(real_dev, -1); |
731 | if (dev->flags & IFF_PROMISC) | 646 | if (dev->flags & IFF_PROMISC) |
@@ -777,47 +692,5 @@ void vlan_change_rx_flags(struct net_device *dev, int change) | |||
777 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ | 692 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ |
778 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) | 693 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) |
779 | { | 694 | { |
780 | struct dev_mc_list *dmi; | 695 | dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev); |
781 | struct net_device *real_dev; | ||
782 | |||
783 | if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) { | ||
784 | /* Then it's a real vlan device, as far as we can tell.. */ | ||
785 | real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev; | ||
786 | |||
787 | /* looking for addresses to add to master's list */ | ||
788 | for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) { | ||
789 | if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) { | ||
790 | dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
791 | printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", | ||
792 | vlan_dev->name, | ||
793 | dmi->dmi_addr[0], | ||
794 | dmi->dmi_addr[1], | ||
795 | dmi->dmi_addr[2], | ||
796 | dmi->dmi_addr[3], | ||
797 | dmi->dmi_addr[4], | ||
798 | dmi->dmi_addr[5]); | ||
799 | } | ||
800 | } | ||
801 | |||
802 | /* looking for addresses to delete from master's list */ | ||
803 | for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) { | ||
804 | if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) { | ||
805 | /* if we think we should add it to the new list, then we should really | ||
806 | * delete it from the real list on the underlying device. | ||
807 | */ | ||
808 | dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
809 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", | ||
810 | vlan_dev->name, | ||
811 | dmi->dmi_addr[0], | ||
812 | dmi->dmi_addr[1], | ||
813 | dmi->dmi_addr[2], | ||
814 | dmi->dmi_addr[3], | ||
815 | dmi->dmi_addr[4], | ||
816 | dmi->dmi_addr[5]); | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* save multicast list */ | ||
821 | vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev)); | ||
822 | } | ||
823 | } | 696 | } |