aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_vlan.c')
-rw-r--r--net/bridge/br_vlan.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 2b2774fe0703..3ba57fcdcd13 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -27,9 +27,13 @@ static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags)
27{ 27{
28 if (flags & BRIDGE_VLAN_INFO_PVID) 28 if (flags & BRIDGE_VLAN_INFO_PVID)
29 __vlan_add_pvid(v, vid); 29 __vlan_add_pvid(v, vid);
30 else
31 __vlan_delete_pvid(v, vid);
30 32
31 if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 33 if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
32 set_bit(vid, v->untagged_bitmap); 34 set_bit(vid, v->untagged_bitmap);
35 else
36 clear_bit(vid, v->untagged_bitmap);
33} 37}
34 38
35static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) 39static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
@@ -55,10 +59,8 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
55 59
56 if (p) { 60 if (p) {
57 /* Add VLAN to the device filter if it is supported. 61 /* Add VLAN to the device filter if it is supported.
58 * Stricly speaking, this is not necessary now, since 62 * This ensures tagged traffic enters the bridge when
59 * devices are made promiscuous by the bridge, but if 63 * promiscuous mode is disabled by br_manage_promisc().
60 * that ever changes this code will allow tagged
61 * traffic to enter the bridge.
62 */ 64 */
63 err = vlan_vid_add(dev, br->vlan_proto, vid); 65 err = vlan_vid_add(dev, br->vlan_proto, vid);
64 if (err) 66 if (err)
@@ -127,7 +129,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
127{ 129{
128 u16 vid; 130 u16 vid;
129 131
130 if (!br->vlan_enabled) 132 /* If this packet was not filtered at input, let it pass */
133 if (!BR_INPUT_SKB_CB(skb)->vlan_filtered)
131 goto out; 134 goto out;
132 135
133 /* Vlan filter table must be configured at this point. The 136 /* Vlan filter table must be configured at this point. The
@@ -166,8 +169,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
166 /* If VLAN filtering is disabled on the bridge, all packets are 169 /* If VLAN filtering is disabled on the bridge, all packets are
167 * permitted. 170 * permitted.
168 */ 171 */
169 if (!br->vlan_enabled) 172 if (!br->vlan_enabled) {
173 BR_INPUT_SKB_CB(skb)->vlan_filtered = false;
170 return true; 174 return true;
175 }
171 176
172 /* If there are no vlan in the permitted list, all packets are 177 /* If there are no vlan in the permitted list, all packets are
173 * rejected. 178 * rejected.
@@ -175,6 +180,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
175 if (!v) 180 if (!v)
176 goto drop; 181 goto drop;
177 182
183 BR_INPUT_SKB_CB(skb)->vlan_filtered = true;
178 proto = br->vlan_proto; 184 proto = br->vlan_proto;
179 185
180 /* If vlan tx offload is disabled on bridge device and frame was 186 /* If vlan tx offload is disabled on bridge device and frame was
@@ -183,7 +189,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
183 */ 189 */
184 if (unlikely(!vlan_tx_tag_present(skb) && 190 if (unlikely(!vlan_tx_tag_present(skb) &&
185 skb->protocol == proto)) { 191 skb->protocol == proto)) {
186 skb = vlan_untag(skb); 192 skb = skb_vlan_untag(skb);
187 if (unlikely(!skb)) 193 if (unlikely(!skb))
188 return false; 194 return false;
189 } 195 }
@@ -253,7 +259,8 @@ bool br_allowed_egress(struct net_bridge *br,
253{ 259{
254 u16 vid; 260 u16 vid;
255 261
256 if (!br->vlan_enabled) 262 /* If this packet was not filtered at input, let it pass */
263 if (!BR_INPUT_SKB_CB(skb)->vlan_filtered)
257 return true; 264 return true;
258 265
259 if (!v) 266 if (!v)
@@ -272,6 +279,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
272 struct net_bridge *br = p->br; 279 struct net_bridge *br = p->br;
273 struct net_port_vlans *v; 280 struct net_port_vlans *v;
274 281
282 /* If filtering was disabled at input, let it pass. */
275 if (!br->vlan_enabled) 283 if (!br->vlan_enabled)
276 return true; 284 return true;
277 285