aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r--net/8021q/vlan_dev.c217
1 files changed, 72 insertions, 145 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ec46084f44b4..d4a62d1b52b4 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -73,7 +73,7 @@ int vlan_dev_rebuild_header(struct sk_buff *skb)
73 73
74static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) 74static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
75{ 75{
76 if (VLAN_DEV_INFO(skb->dev)->flags & 1) { 76 if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
77 if (skb_shared(skb) || skb_cloned(skb)) { 77 if (skb_shared(skb) || skb_cloned(skb)) {
78 struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); 78 struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
79 kfree_skb(skb); 79 kfree_skb(skb);
@@ -350,7 +350,8 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
350 * header shuffling in the hard_start_xmit. Users can turn off this 350 * header shuffling in the hard_start_xmit. Users can turn off this
351 * REORDER behaviour with the vconfig tool. 351 * REORDER behaviour with the vconfig tool.
352 */ 352 */
353 build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0); 353 if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR))
354 build_vlan_header = 1;
354 355
355 if (build_vlan_header) { 356 if (build_vlan_header) {
356 vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); 357 vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
@@ -534,172 +535,81 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
534 return 0; 535 return 0;
535} 536}
536 537
537int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) 538void vlan_dev_set_ingress_priority(const struct net_device *dev,
539 u32 skb_prio, short vlan_prio)
538{ 540{
539 struct net_device *dev = dev_get_by_name(dev_name); 541 struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
540 542
541 if (dev) { 543 if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio)
542 if (dev->priv_flags & IFF_802_1Q_VLAN) { 544 vlan->nr_ingress_mappings--;
543 /* see if a priority mapping exists.. */ 545 else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio)
544 VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio; 546 vlan->nr_ingress_mappings++;
545 dev_put(dev);
546 return 0;
547 }
548 547
549 dev_put(dev); 548 vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
550 }
551 return -EINVAL;
552} 549}
553 550
554int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) 551int vlan_dev_set_egress_priority(const struct net_device *dev,
552 u32 skb_prio, short vlan_prio)
555{ 553{
556 struct net_device *dev = dev_get_by_name(dev_name); 554 struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
557 struct vlan_priority_tci_mapping *mp = NULL; 555 struct vlan_priority_tci_mapping *mp = NULL;
558 struct vlan_priority_tci_mapping *np; 556 struct vlan_priority_tci_mapping *np;
557 u32 vlan_qos = (vlan_prio << 13) & 0xE000;
559 558
560 if (dev) { 559 /* See if a priority mapping exists.. */
561 if (dev->priv_flags & IFF_802_1Q_VLAN) { 560 mp = vlan->egress_priority_map[skb_prio & 0xF];
562 /* See if a priority mapping exists.. */ 561 while (mp) {
563 mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; 562 if (mp->priority == skb_prio) {
564 while (mp) { 563 if (mp->vlan_qos && !vlan_qos)
565 if (mp->priority == skb_prio) { 564 vlan->nr_egress_mappings--;
566 mp->vlan_qos = ((vlan_prio << 13) & 0xE000); 565 else if (!mp->vlan_qos && vlan_qos)
567 dev_put(dev); 566 vlan->nr_egress_mappings++;
568 return 0; 567 mp->vlan_qos = vlan_qos;
569 } 568 return 0;
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 }
588 dev_put(dev);
589 }
590 return -EINVAL;
591}
592
593/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
594int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
595{
596 struct net_device *dev = dev_get_by_name(dev_name);
597
598 if (dev) {
599 if (dev->priv_flags & IFF_802_1Q_VLAN) {
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 {
616 printk(KERN_ERR
617 "%s: %s is not a vlan device, priv_flags: %hX.\n",
618 __FUNCTION__, dev->name, dev->priv_flags);
619 dev_put(dev);
620 } 569 }
621 } else { 570 mp = mp->next;
622 printk(KERN_ERR "%s: Could not find device: %s\n",
623 __FUNCTION__, dev_name);
624 } 571 }
625 572
626 return -EINVAL; 573 /* Create a new mapping then. */
574 mp = vlan->egress_priority_map[skb_prio & 0xF];
575 np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
576 if (!np)
577 return -ENOBUFS;
578
579 np->next = mp;
580 np->priority = skb_prio;
581 np->vlan_qos = vlan_qos;
582 vlan->egress_priority_map[skb_prio & 0xF] = np;
583 if (vlan_qos)
584 vlan->nr_egress_mappings++;
585 return 0;
627} 586}
628 587
629 588/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
630int vlan_dev_get_realdev_name(const char *dev_name, char* result) 589int vlan_dev_set_vlan_flag(const struct net_device *dev,
590 u32 flag, short flag_val)
631{ 591{
632 struct net_device *dev = dev_get_by_name(dev_name); 592 /* verify flag is supported */
633 int rv = 0; 593 if (flag == VLAN_FLAG_REORDER_HDR) {
634 if (dev) { 594 if (flag_val) {
635 if (dev->priv_flags & IFF_802_1Q_VLAN) { 595 VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR;
636 strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
637 rv = 0;
638 } else { 596 } else {
639 rv = -EINVAL; 597 VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
640 } 598 }
641 dev_put(dev); 599 return 0;
642 } else {
643 rv = -ENODEV;
644 } 600 }
645 return rv; 601 printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag);
602 return -EINVAL;
646} 603}
647 604
648int vlan_dev_get_vid(const char *dev_name, unsigned short* result) 605void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
649{ 606{
650 struct net_device *dev = dev_get_by_name(dev_name); 607 strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
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} 608}
665 609
666 610void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
667int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
668{ 611{
669 struct sockaddr *addr = (struct sockaddr *)(addr_struct_p); 612 *result = VLAN_DEV_INFO(dev)->vlan_id;
670 int i;
671
672 if (netif_running(dev))
673 return -EBUSY;
674
675 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
676
677 printk("%s: Setting MAC address to ", dev->name);
678 for (i = 0; i < 6; i++)
679 printk(" %2.2x", dev->dev_addr[i]);
680 printk(".\n");
681
682 if (memcmp(VLAN_DEV_INFO(dev)->real_dev->dev_addr,
683 dev->dev_addr,
684 dev->addr_len) != 0) {
685 if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_PROMISC)) {
686 int flgs = VLAN_DEV_INFO(dev)->real_dev->flags;
687
688 /* Increment our in-use promiscuity counter */
689 dev_set_promiscuity(VLAN_DEV_INFO(dev)->real_dev, 1);
690
691 /* Make PROMISC visible to the user. */
692 flgs |= IFF_PROMISC;
693 printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n",
694 dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
695 dev_change_flags(VLAN_DEV_INFO(dev)->real_dev, flgs);
696 }
697 } else {
698 printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n",
699 dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
700 }
701
702 return 0;
703} 613}
704 614
705static inline int vlan_dmi_equals(struct dev_mc_list *dmi1, 615static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
@@ -788,15 +698,32 @@ static void vlan_flush_mc_list(struct net_device *dev)
788 698
789int vlan_dev_open(struct net_device *dev) 699int vlan_dev_open(struct net_device *dev)
790{ 700{
791 if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_UP)) 701 struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
702 struct net_device *real_dev = vlan->real_dev;
703 int err;
704
705 if (!(real_dev->flags & IFF_UP))
792 return -ENETDOWN; 706 return -ENETDOWN;
793 707
708 if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) {
709 err = dev_unicast_add(real_dev, dev->dev_addr, ETH_ALEN);
710 if (err < 0)
711 return err;
712 }
713 memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN);
714
794 return 0; 715 return 0;
795} 716}
796 717
797int vlan_dev_stop(struct net_device *dev) 718int vlan_dev_stop(struct net_device *dev)
798{ 719{
720 struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
721
799 vlan_flush_mc_list(dev); 722 vlan_flush_mc_list(dev);
723
724 if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
725 dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len);
726
800 return 0; 727 return 0;
801} 728}
802 729