aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/8021q/vlan_core.c1
-rw-r--r--net/bridge/br_device.c3
-rw-r--r--net/bridge/br_forward.c8
-rw-r--r--net/bridge/br_input.c7
-rw-r--r--net/bridge/br_private.h34
-rw-r--r--net/bridge/br_vlan.c83
6 files changed, 126 insertions, 10 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 71b64fde8dc9..f3b6f515eba6 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -144,6 +144,7 @@ err_free:
144 kfree_skb(skb); 144 kfree_skb(skb);
145 return NULL; 145 return NULL;
146} 146}
147EXPORT_SYMBOL(vlan_untag);
147 148
148 149
149/* 150/*
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 091bedf266a0..9509139da49c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -30,6 +30,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
30 struct net_bridge_fdb_entry *dst; 30 struct net_bridge_fdb_entry *dst;
31 struct net_bridge_mdb_entry *mdst; 31 struct net_bridge_mdb_entry *mdst;
32 struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); 32 struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
33 u16 vid = 0;
33 34
34 rcu_read_lock(); 35 rcu_read_lock();
35#ifdef CONFIG_BRIDGE_NETFILTER 36#ifdef CONFIG_BRIDGE_NETFILTER
@@ -45,7 +46,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
45 brstats->tx_bytes += skb->len; 46 brstats->tx_bytes += skb->len;
46 u64_stats_update_end(&brstats->syncp); 47 u64_stats_update_end(&brstats->syncp);
47 48
48 if (!br_allowed_ingress(br, br_get_vlan_info(br), skb)) 49 if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
49 goto out; 50 goto out;
50 51
51 BR_INPUT_SKB_CB(skb)->brdev = dev; 52 BR_INPUT_SKB_CB(skb)->brdev = dev;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 35b0671f135d..092b20e4ee4c 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -64,6 +64,10 @@ int br_forward_finish(struct sk_buff *skb)
64 64
65static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) 65static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
66{ 66{
67 skb = br_handle_vlan(to->br, nbp_get_vlan_info(to), skb);
68 if (!skb)
69 return;
70
67 skb->dev = to->dev; 71 skb->dev = to->dev;
68 72
69 if (unlikely(netpoll_tx_running(to->br->dev))) { 73 if (unlikely(netpoll_tx_running(to->br->dev))) {
@@ -89,6 +93,10 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
89 return; 93 return;
90 } 94 }
91 95
96 skb = br_handle_vlan(to->br, nbp_get_vlan_info(to), skb);
97 if (!skb)
98 return;
99
92 indev = skb->dev; 100 indev = skb->dev;
93 skb->dev = to->dev; 101 skb->dev = to->dev;
94 skb_forward_csum(skb); 102 skb_forward_csum(skb);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 787d7dad6b7e..a63f227ad963 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -45,6 +45,10 @@ static int br_pass_frame_up(struct sk_buff *skb)
45 return NET_RX_DROP; 45 return NET_RX_DROP;
46 } 46 }
47 47
48 skb = br_handle_vlan(br, br_get_vlan_info(br), skb);
49 if (!skb)
50 return NET_RX_DROP;
51
48 indev = skb->dev; 52 indev = skb->dev;
49 skb->dev = brdev; 53 skb->dev = brdev;
50 54
@@ -61,11 +65,12 @@ int br_handle_frame_finish(struct sk_buff *skb)
61 struct net_bridge_fdb_entry *dst; 65 struct net_bridge_fdb_entry *dst;
62 struct net_bridge_mdb_entry *mdst; 66 struct net_bridge_mdb_entry *mdst;
63 struct sk_buff *skb2; 67 struct sk_buff *skb2;
68 u16 vid = 0;
64 69
65 if (!p || p->state == BR_STATE_DISABLED) 70 if (!p || p->state == BR_STATE_DISABLED)
66 goto drop; 71 goto drop;
67 72
68 if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb)) 73 if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb, &vid))
69 goto drop; 74 goto drop;
70 75
71 /* insert into forwarding database after filtering to avoid spoofing */ 76 /* insert into forwarding database after filtering to avoid spoofing */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index ce2235255c2f..ea8e7efd9137 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -67,6 +67,7 @@ struct br_ip
67 67
68struct net_port_vlans { 68struct net_port_vlans {
69 u16 port_idx; 69 u16 port_idx;
70 u16 pvid;
70 union { 71 union {
71 struct net_bridge_port *port; 72 struct net_bridge_port *port;
72 struct net_bridge *br; 73 struct net_bridge *br;
@@ -554,10 +555,13 @@ static inline void br_mdb_uninit(void)
554/* br_vlan.c */ 555/* br_vlan.c */
555#ifdef CONFIG_BRIDGE_VLAN_FILTERING 556#ifdef CONFIG_BRIDGE_VLAN_FILTERING
556extern bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, 557extern bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
557 struct sk_buff *skb); 558 struct sk_buff *skb, u16 *vid);
558extern bool br_allowed_egress(struct net_bridge *br, 559extern bool br_allowed_egress(struct net_bridge *br,
559 const struct net_port_vlans *v, 560 const struct net_port_vlans *v,
560 const struct sk_buff *skb); 561 const struct sk_buff *skb);
562extern struct sk_buff *br_handle_vlan(struct net_bridge *br,
563 const struct net_port_vlans *v,
564 struct sk_buff *skb);
561extern int br_vlan_add(struct net_bridge *br, u16 vid); 565extern int br_vlan_add(struct net_bridge *br, u16 vid);
562extern int br_vlan_delete(struct net_bridge *br, u16 vid); 566extern int br_vlan_delete(struct net_bridge *br, u16 vid);
563extern void br_vlan_flush(struct net_bridge *br); 567extern void br_vlan_flush(struct net_bridge *br);
@@ -594,10 +598,23 @@ static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid)
594 598
595 return err; 599 return err;
596} 600}
601
602static inline u16 br_get_pvid(const struct net_port_vlans *v)
603{
604 /* Return just the VID if it is set, or VLAN_N_VID (invalid vid) if
605 * vid wasn't set
606 */
607 smp_rmb();
608 return (v->pvid & VLAN_TAG_PRESENT) ?
609 (v->pvid & ~VLAN_TAG_PRESENT) :
610 VLAN_N_VID;
611}
612
597#else 613#else
598static inline bool br_allowed_ingress(struct net_bridge *br, 614static inline bool br_allowed_ingress(struct net_bridge *br,
599 struct net_port_vlans *v, 615 struct net_port_vlans *v,
600 struct sk_buff *skb) 616 struct sk_buff *skb,
617 u16 *vid)
601{ 618{
602 return true; 619 return true;
603} 620}
@@ -609,6 +626,13 @@ static inline bool br_allowed_egress(struct net_bridge *br,
609 return true; 626 return true;
610} 627}
611 628
629static inline struct sk_buff *br_handle_vlan(struct net_bridge *br,
630 const struct net_port_vlans *v,
631 struct sk_buff *skb)
632{
633 return skb;
634}
635
612static inline int br_vlan_add(struct net_bridge *br, u16 vid) 636static inline int br_vlan_add(struct net_bridge *br, u16 vid)
613{ 637{
614 return -EOPNOTSUPP; 638 return -EOPNOTSUPP;
@@ -648,10 +672,14 @@ static inline struct net_port_vlans *nbp_get_vlan_info(
648 return NULL; 672 return NULL;
649} 673}
650 674
651static inline u16 br_vlan_get_tag(const struct sk_buff *skb) 675static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag)
652{ 676{
653 return 0; 677 return 0;
654} 678}
679static inline u16 br_get_pvid(const struct net_port_vlans *v)
680{
681 return VLAN_N_VID; /* Returns invalid vid */
682}
655#endif 683#endif
656 684
657/* br_netfilter.c */ 685/* br_netfilter.c */
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index f2bf5a197ea3..20057de56db0 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -66,12 +66,68 @@ static void __vlan_flush(struct net_port_vlans *v)
66 kfree_rcu(v, rcu); 66 kfree_rcu(v, rcu);
67} 67}
68 68
69/* Called under RCU */ 69/* Strip the tag from the packet. Will return skb with tci set 0. */
70bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, 70static struct sk_buff *br_vlan_untag(struct sk_buff *skb)
71 struct sk_buff *skb) 71{
72 if (skb->protocol != htons(ETH_P_8021Q)) {
73 skb->vlan_tci = 0;
74 return skb;
75 }
76
77 skb->vlan_tci = 0;
78 skb = vlan_untag(skb);
79 if (skb)
80 skb->vlan_tci = 0;
81
82 return skb;
83}
84
85struct sk_buff *br_handle_vlan(struct net_bridge *br,
86 const struct net_port_vlans *pv,
87 struct sk_buff *skb)
72{ 88{
73 u16 vid; 89 u16 vid;
74 90
91 if (!br->vlan_enabled)
92 goto out;
93
94 /* At this point, we know that the frame was filtered and contains
95 * a valid vlan id. If the vlan id matches the pvid of current port
96 * send untagged; otherwise, send taged.
97 */
98 br_vlan_get_tag(skb, &vid);
99 if (vid == br_get_pvid(pv))
100 skb = br_vlan_untag(skb);
101 else {
102 /* Egress policy says "send tagged". If output device
103 * is the bridge, we need to add the VLAN header
104 * ourselves since we'll be going through the RX path.
105 * Sending to ports puts the frame on the TX path and
106 * we let dev_hard_start_xmit() add the header.
107 */
108 if (skb->protocol != htons(ETH_P_8021Q) &&
109 pv->port_idx == 0) {
110 /* vlan_put_tag expects skb->data to point to
111 * mac header.
112 */
113 skb_push(skb, ETH_HLEN);
114 skb = __vlan_put_tag(skb, skb->vlan_tci);
115 if (!skb)
116 goto out;
117 /* put skb->data back to where it was */
118 skb_pull(skb, ETH_HLEN);
119 skb->vlan_tci = 0;
120 }
121 }
122
123out:
124 return skb;
125}
126
127/* Called under RCU */
128bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
129 struct sk_buff *skb, u16 *vid)
130{
75 /* If VLAN filtering is disabled on the bridge, all packets are 131 /* If VLAN filtering is disabled on the bridge, all packets are
76 * permitted. 132 * permitted.
77 */ 133 */
@@ -84,8 +140,25 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
84 if (!v) 140 if (!v)
85 return false; 141 return false;
86 142
87 br_vlan_get_tag(skb, &vid); 143 if (br_vlan_get_tag(skb, vid)) {
88 if (test_bit(vid, v->vlan_bitmap)) 144 u16 pvid = br_get_pvid(v);
145
146 /* Frame did not have a tag. See if pvid is set
147 * on this port. That tells us which vlan untagged
148 * traffic belongs to.
149 */
150 if (pvid == VLAN_N_VID)
151 return false;
152
153 /* PVID is set on this port. Any untagged ingress
154 * frame is considered to belong to this vlan.
155 */
156 __vlan_hwaccel_put_tag(skb, pvid);
157 return true;
158 }
159
160 /* Frame had a valid vlan tag. See if vlan is allowed */
161 if (test_bit(*vid, v->vlan_bitmap))
89 return true; 162 return true;
90 163
91 return false; 164 return false;