aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_device.c1
-rw-r--r--net/bridge/br_private.h6
-rw-r--r--net/bridge/br_vlan.c56
3 files changed, 51 insertions, 12 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 82a410a5ef7e..1b797c42ef5f 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -388,4 +388,5 @@ void br_dev_setup(struct net_device *dev)
388 br_netfilter_rtable_init(br); 388 br_netfilter_rtable_init(br);
389 br_stp_timer_init(br); 389 br_stp_timer_init(br);
390 br_multicast_init(br); 390 br_multicast_init(br);
391 br_vlan_init(br);
391} 392}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8346e9504cdb..13e570e8b0fc 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -294,6 +294,7 @@ struct net_bridge
294 u32 auto_cnt; 294 u32 auto_cnt;
295#ifdef CONFIG_BRIDGE_VLAN_FILTERING 295#ifdef CONFIG_BRIDGE_VLAN_FILTERING
296 u8 vlan_enabled; 296 u8 vlan_enabled;
297 __be16 vlan_proto;
297 struct net_port_vlans __rcu *vlan_info; 298 struct net_port_vlans __rcu *vlan_info;
298#endif 299#endif
299}; 300};
@@ -594,6 +595,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid);
594void br_vlan_flush(struct net_bridge *br); 595void br_vlan_flush(struct net_bridge *br);
595bool br_vlan_find(struct net_bridge *br, u16 vid); 596bool br_vlan_find(struct net_bridge *br, u16 vid);
596int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); 597int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
598void br_vlan_init(struct net_bridge *br);
597int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); 599int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
598int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); 600int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
599void nbp_vlan_flush(struct net_bridge_port *port); 601void nbp_vlan_flush(struct net_bridge_port *port);
@@ -689,6 +691,10 @@ static inline bool br_vlan_find(struct net_bridge *br, u16 vid)
689 return false; 691 return false;
690} 692}
691 693
694static inline void br_vlan_init(struct net_bridge *br)
695{
696}
697
692static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 698static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
693{ 699{
694 return -EOPNOTSUPP; 700 return -EOPNOTSUPP;
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index fcc95390f862..63bd98137a42 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -60,7 +60,7 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
60 * that ever changes this code will allow tagged 60 * that ever changes this code will allow tagged
61 * traffic to enter the bridge. 61 * traffic to enter the bridge.
62 */ 62 */
63 err = vlan_vid_add(dev, htons(ETH_P_8021Q), vid); 63 err = vlan_vid_add(dev, br->vlan_proto, vid);
64 if (err) 64 if (err)
65 return err; 65 return err;
66 } 66 }
@@ -80,7 +80,7 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
80 80
81out_filt: 81out_filt:
82 if (p) 82 if (p)
83 vlan_vid_del(dev, htons(ETH_P_8021Q), vid); 83 vlan_vid_del(dev, br->vlan_proto, vid);
84 return err; 84 return err;
85} 85}
86 86
@@ -92,8 +92,10 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
92 __vlan_delete_pvid(v, vid); 92 __vlan_delete_pvid(v, vid);
93 clear_bit(vid, v->untagged_bitmap); 93 clear_bit(vid, v->untagged_bitmap);
94 94
95 if (v->port_idx) 95 if (v->port_idx) {
96 vlan_vid_del(v->parent.port->dev, htons(ETH_P_8021Q), vid); 96 struct net_bridge_port *p = v->parent.port;
97 vlan_vid_del(p->dev, p->br->vlan_proto, vid);
98 }
97 99
98 clear_bit(vid, v->vlan_bitmap); 100 clear_bit(vid, v->vlan_bitmap);
99 v->num_vlans--; 101 v->num_vlans--;
@@ -158,7 +160,8 @@ out:
158bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, 160bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
159 struct sk_buff *skb, u16 *vid) 161 struct sk_buff *skb, u16 *vid)
160{ 162{
161 int err; 163 bool tagged;
164 __be16 proto;
162 165
163 /* If VLAN filtering is disabled on the bridge, all packets are 166 /* If VLAN filtering is disabled on the bridge, all packets are
164 * permitted. 167 * permitted.
@@ -172,19 +175,41 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
172 if (!v) 175 if (!v)
173 goto drop; 176 goto drop;
174 177
178 proto = br->vlan_proto;
179
175 /* If vlan tx offload is disabled on bridge device and frame was 180 /* If vlan tx offload is disabled on bridge device and frame was
176 * sent from vlan device on the bridge device, it does not have 181 * sent from vlan device on the bridge device, it does not have
177 * HW accelerated vlan tag. 182 * HW accelerated vlan tag.
178 */ 183 */
179 if (unlikely(!vlan_tx_tag_present(skb) && 184 if (unlikely(!vlan_tx_tag_present(skb) &&
180 (skb->protocol == htons(ETH_P_8021Q) || 185 skb->protocol == proto)) {
181 skb->protocol == htons(ETH_P_8021AD)))) {
182 skb = vlan_untag(skb); 186 skb = vlan_untag(skb);
183 if (unlikely(!skb)) 187 if (unlikely(!skb))
184 return false; 188 return false;
185 } 189 }
186 190
187 err = br_vlan_get_tag(skb, vid); 191 if (!br_vlan_get_tag(skb, vid)) {
192 /* Tagged frame */
193 if (skb->vlan_proto != proto) {
194 /* Protocol-mismatch, empty out vlan_tci for new tag */
195 skb_push(skb, ETH_HLEN);
196 skb = __vlan_put_tag(skb, skb->vlan_proto,
197 vlan_tx_tag_get(skb));
198 if (unlikely(!skb))
199 return false;
200
201 skb_pull(skb, ETH_HLEN);
202 skb_reset_mac_len(skb);
203 *vid = 0;
204 tagged = false;
205 } else {
206 tagged = true;
207 }
208 } else {
209 /* Untagged frame */
210 tagged = false;
211 }
212
188 if (!*vid) { 213 if (!*vid) {
189 u16 pvid = br_get_pvid(v); 214 u16 pvid = br_get_pvid(v);
190 215
@@ -199,9 +224,9 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
199 * ingress frame is considered to belong to this vlan. 224 * ingress frame is considered to belong to this vlan.
200 */ 225 */
201 *vid = pvid; 226 *vid = pvid;
202 if (likely(err)) 227 if (likely(!tagged))
203 /* Untagged Frame. */ 228 /* Untagged Frame. */
204 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); 229 __vlan_hwaccel_put_tag(skb, proto, pvid);
205 else 230 else
206 /* Priority-tagged Frame. 231 /* Priority-tagged Frame.
207 * At this point, We know that skb->vlan_tci had 232 * At this point, We know that skb->vlan_tci had
@@ -254,7 +279,9 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
254 if (!v) 279 if (!v)
255 return false; 280 return false;
256 281
257 br_vlan_get_tag(skb, vid); 282 if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto)
283 *vid = 0;
284
258 if (!*vid) { 285 if (!*vid) {
259 *vid = br_get_pvid(v); 286 *vid = br_get_pvid(v);
260 if (*vid == VLAN_N_VID) 287 if (*vid == VLAN_N_VID)
@@ -367,6 +394,11 @@ unlock:
367 return 0; 394 return 0;
368} 395}
369 396
397void br_vlan_init(struct net_bridge *br)
398{
399 br->vlan_proto = htons(ETH_P_8021Q);
400}
401
370/* Must be protected by RTNL. 402/* Must be protected by RTNL.
371 * Must be called with vid in range from 1 to 4094 inclusive. 403 * Must be called with vid in range from 1 to 4094 inclusive.
372 */ 404 */
@@ -433,7 +465,7 @@ void nbp_vlan_flush(struct net_bridge_port *port)
433 return; 465 return;
434 466
435 for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) 467 for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID)
436 vlan_vid_del(port->dev, htons(ETH_P_8021Q), vid); 468 vlan_vid_del(port->dev, port->br->vlan_proto, vid);
437 469
438 __vlan_flush(pv); 470 __vlan_flush(pv);
439} 471}