aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/br_device.c8
-rw-r--r--net/bridge/br_if.c3
-rw-r--r--net/bridge/br_private.h14
-rw-r--r--net/bridge/br_vlan.c118
4 files changed, 136 insertions, 7 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 659cac15c0df..ffd379db5938 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -88,12 +88,17 @@ out:
88static int br_dev_init(struct net_device *dev) 88static int br_dev_init(struct net_device *dev)
89{ 89{
90 struct net_bridge *br = netdev_priv(dev); 90 struct net_bridge *br = netdev_priv(dev);
91 int err;
91 92
92 br->stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 93 br->stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
93 if (!br->stats) 94 if (!br->stats)
94 return -ENOMEM; 95 return -ENOMEM;
95 96
96 return 0; 97 err = br_vlan_init(br);
98 if (err)
99 free_percpu(br->stats);
100
101 return err;
97} 102}
98 103
99static int br_dev_open(struct net_device *dev) 104static int br_dev_open(struct net_device *dev)
@@ -389,5 +394,4 @@ void br_dev_setup(struct net_device *dev)
389 br_netfilter_rtable_init(br); 394 br_netfilter_rtable_init(br);
390 br_stp_timer_init(br); 395 br_stp_timer_init(br);
391 br_multicast_init(br); 396 br_multicast_init(br);
392 br_vlan_init(br);
393} 397}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 7b7289ca2992..ed307db7a12b 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -500,6 +500,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
500 if (br_fdb_insert(br, p, dev->dev_addr, 0)) 500 if (br_fdb_insert(br, p, dev->dev_addr, 0))
501 netdev_err(dev, "failed insert local address bridge forwarding table\n"); 501 netdev_err(dev, "failed insert local address bridge forwarding table\n");
502 502
503 if (nbp_vlan_init(p))
504 netdev_err(dev, "failed to initialize vlan filtering on this port\n");
505
503 spin_lock_bh(&br->lock); 506 spin_lock_bh(&br->lock);
504 changed_addr = br_stp_recalculate_bridge_id(br); 507 changed_addr = br_stp_recalculate_bridge_id(br);
505 508
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index f671561b3053..d8cbaa694227 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -605,12 +605,13 @@ bool br_vlan_find(struct net_bridge *br, u16 vid);
605void br_recalculate_fwd_mask(struct net_bridge *br); 605void br_recalculate_fwd_mask(struct net_bridge *br);
606int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); 606int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
607int br_vlan_set_proto(struct net_bridge *br, unsigned long val); 607int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
608void br_vlan_init(struct net_bridge *br); 608int br_vlan_init(struct net_bridge *br);
609int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val); 609int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
610int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); 610int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
611int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); 611int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
612void nbp_vlan_flush(struct net_bridge_port *port); 612void nbp_vlan_flush(struct net_bridge_port *port);
613bool nbp_vlan_find(struct net_bridge_port *port, u16 vid); 613bool nbp_vlan_find(struct net_bridge_port *port, u16 vid);
614int nbp_vlan_init(struct net_bridge_port *port);
614 615
615static inline struct net_port_vlans *br_get_vlan_info( 616static inline struct net_port_vlans *br_get_vlan_info(
616 const struct net_bridge *br) 617 const struct net_bridge *br)
@@ -643,6 +644,9 @@ static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid)
643 644
644static inline u16 br_get_pvid(const struct net_port_vlans *v) 645static inline u16 br_get_pvid(const struct net_port_vlans *v)
645{ 646{
647 if (!v)
648 return 0;
649
646 smp_rmb(); 650 smp_rmb();
647 return v->pvid; 651 return v->pvid;
648} 652}
@@ -703,8 +707,9 @@ static inline void br_recalculate_fwd_mask(struct net_bridge *br)
703{ 707{
704} 708}
705 709
706static inline void br_vlan_init(struct net_bridge *br) 710static inline int br_vlan_init(struct net_bridge *br)
707{ 711{
712 return 0;
708} 713}
709 714
710static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 715static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
@@ -737,6 +742,11 @@ static inline bool nbp_vlan_find(struct net_bridge_port *port, u16 vid)
737 return false; 742 return false;
738} 743}
739 744
745static inline int nbp_vlan_init(struct net_bridge_port *port)
746{
747 return 0;
748}
749
740static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag) 750static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag)
741{ 751{
742 return 0; 752 return 0;
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index e11c9932e706..150048fb99b0 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -499,12 +499,110 @@ err_filt:
499 goto unlock; 499 goto unlock;
500} 500}
501 501
502static bool vlan_default_pvid(struct net_port_vlans *pv, u16 vid)
503{
504 return pv && vid == pv->pvid && test_bit(vid, pv->untagged_bitmap);
505}
506
507static void br_vlan_disable_default_pvid(struct net_bridge *br)
508{
509 struct net_bridge_port *p;
510 u16 pvid = br->default_pvid;
511
512 /* Disable default_pvid on all ports where it is still
513 * configured.
514 */
515 if (vlan_default_pvid(br_get_vlan_info(br), pvid))
516 br_vlan_delete(br, pvid);
517
518 list_for_each_entry(p, &br->port_list, list) {
519 if (vlan_default_pvid(nbp_get_vlan_info(p), pvid))
520 nbp_vlan_delete(p, pvid);
521 }
522
523 br->default_pvid = 0;
524}
525
526static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
527{
528 struct net_bridge_port *p;
529 u16 old_pvid;
530 int err = 0;
531 unsigned long *changed;
532
533 changed = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long),
534 GFP_KERNEL);
535 if (!changed)
536 return -ENOMEM;
537
538 old_pvid = br->default_pvid;
539
540 /* Update default_pvid config only if we do not conflict with
541 * user configuration.
542 */
543 if ((!old_pvid || vlan_default_pvid(br_get_vlan_info(br), old_pvid)) &&
544 !br_vlan_find(br, pvid)) {
545 err = br_vlan_add(br, pvid,
546 BRIDGE_VLAN_INFO_PVID |
547 BRIDGE_VLAN_INFO_UNTAGGED);
548 if (err)
549 goto out;
550 br_vlan_delete(br, old_pvid);
551 set_bit(0, changed);
552 }
553
554 list_for_each_entry(p, &br->port_list, list) {
555 /* Update default_pvid config only if we do not conflict with
556 * user configuration.
557 */
558 if ((old_pvid &&
559 !vlan_default_pvid(nbp_get_vlan_info(p), old_pvid)) ||
560 nbp_vlan_find(p, pvid))
561 continue;
562
563 err = nbp_vlan_add(p, pvid,
564 BRIDGE_VLAN_INFO_PVID |
565 BRIDGE_VLAN_INFO_UNTAGGED);
566 if (err)
567 goto err_port;
568 nbp_vlan_delete(p, old_pvid);
569 set_bit(p->port_no, changed);
570 }
571
572 br->default_pvid = pvid;
573
574out:
575 kfree(changed);
576 return err;
577
578err_port:
579 list_for_each_entry_continue_reverse(p, &br->port_list, list) {
580 if (!test_bit(p->port_no, changed))
581 continue;
582
583 if (old_pvid)
584 nbp_vlan_add(p, old_pvid,
585 BRIDGE_VLAN_INFO_PVID |
586 BRIDGE_VLAN_INFO_UNTAGGED);
587 nbp_vlan_delete(p, pvid);
588 }
589
590 if (test_bit(0, changed)) {
591 if (old_pvid)
592 br_vlan_add(br, old_pvid,
593 BRIDGE_VLAN_INFO_PVID |
594 BRIDGE_VLAN_INFO_UNTAGGED);
595 br_vlan_delete(br, pvid);
596 }
597 goto out;
598}
599
502int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) 600int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
503{ 601{
504 u16 pvid = val; 602 u16 pvid = val;
505 int err = 0; 603 int err = 0;
506 604
507 if (!val || val >= VLAN_VID_MASK) 605 if (val >= VLAN_VID_MASK)
508 return -EINVAL; 606 return -EINVAL;
509 607
510 if (!rtnl_trylock()) 608 if (!rtnl_trylock())
@@ -520,17 +618,22 @@ int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
520 goto unlock; 618 goto unlock;
521 } 619 }
522 620
523 br->default_pvid = pvid; 621 if (!pvid)
622 br_vlan_disable_default_pvid(br);
623 else
624 err = __br_vlan_set_default_pvid(br, pvid);
524 625
525unlock: 626unlock:
526 rtnl_unlock(); 627 rtnl_unlock();
527 return err; 628 return err;
528} 629}
529 630
530void br_vlan_init(struct net_bridge *br) 631int br_vlan_init(struct net_bridge *br)
531{ 632{
532 br->vlan_proto = htons(ETH_P_8021Q); 633 br->vlan_proto = htons(ETH_P_8021Q);
533 br->default_pvid = 1; 634 br->default_pvid = 1;
635 return br_vlan_add(br, 1,
636 BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED);
534} 637}
535 638
536/* Must be protected by RTNL. 639/* Must be protected by RTNL.
@@ -622,3 +725,12 @@ out:
622 rcu_read_unlock(); 725 rcu_read_unlock();
623 return found; 726 return found;
624} 727}
728
729int nbp_vlan_init(struct net_bridge_port *p)
730{
731 return p->br->default_pvid ?
732 nbp_vlan_add(p, p->br->default_pvid,
733 BRIDGE_VLAN_INFO_PVID |
734 BRIDGE_VLAN_INFO_UNTAGGED) :
735 0;
736}