Skip to content

Commit 8580e21

Browse files
Toshiaki Makitadavem330
authored andcommitted
bridge: Prepare for 802.1ad vlan filtering support
This enables a bridge to have vlan protocol informantion and allows vlan tag manipulation (retrieve, insert and remove tags) according to the vlan protocol. Signed-off-by: Toshiaki Makita <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1c5abb6 commit 8580e21

File tree

3 files changed

+51
-12
lines changed

3 files changed

+51
-12
lines changed

net/bridge/br_device.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,4 +388,5 @@ void br_dev_setup(struct net_device *dev)
388388
br_netfilter_rtable_init(br);
389389
br_stp_timer_init(br);
390390
br_multicast_init(br);
391+
br_vlan_init(br);
391392
}

net/bridge/br_private.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ struct net_bridge
294294
u32 auto_cnt;
295295
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
296296
u8 vlan_enabled;
297+
__be16 vlan_proto;
297298
struct net_port_vlans __rcu *vlan_info;
298299
#endif
299300
};
@@ -594,6 +595,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid);
594595
void br_vlan_flush(struct net_bridge *br);
595596
bool br_vlan_find(struct net_bridge *br, u16 vid);
596597
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
598+
void br_vlan_init(struct net_bridge *br);
597599
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
598600
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
599601
void nbp_vlan_flush(struct net_bridge_port *port);
@@ -689,6 +691,10 @@ static inline bool br_vlan_find(struct net_bridge *br, u16 vid)
689691
return false;
690692
}
691693

694+
static inline void br_vlan_init(struct net_bridge *br)
695+
{
696+
}
697+
692698
static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
693699
{
694700
return -EOPNOTSUPP;

net/bridge/br_vlan.c

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
6060
* that ever changes this code will allow tagged
6161
* traffic to enter the bridge.
6262
*/
63-
err = vlan_vid_add(dev, htons(ETH_P_8021Q), vid);
63+
err = vlan_vid_add(dev, br->vlan_proto, vid);
6464
if (err)
6565
return err;
6666
}
@@ -80,7 +80,7 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
8080

8181
out_filt:
8282
if (p)
83-
vlan_vid_del(dev, htons(ETH_P_8021Q), vid);
83+
vlan_vid_del(dev, br->vlan_proto, vid);
8484
return err;
8585
}
8686

@@ -92,8 +92,10 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
9292
__vlan_delete_pvid(v, vid);
9393
clear_bit(vid, v->untagged_bitmap);
9494

95-
if (v->port_idx)
96-
vlan_vid_del(v->parent.port->dev, htons(ETH_P_8021Q), vid);
95+
if (v->port_idx) {
96+
struct net_bridge_port *p = v->parent.port;
97+
vlan_vid_del(p->dev, p->br->vlan_proto, vid);
98+
}
9799

98100
clear_bit(vid, v->vlan_bitmap);
99101
v->num_vlans--;
@@ -158,7 +160,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
158160
bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
159161
struct sk_buff *skb, u16 *vid)
160162
{
161-
int err;
163+
bool tagged;
164+
__be16 proto;
162165

163166
/* If VLAN filtering is disabled on the bridge, all packets are
164167
* permitted.
@@ -172,19 +175,41 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
172175
if (!v)
173176
goto drop;
174177

178+
proto = br->vlan_proto;
179+
175180
/* If vlan tx offload is disabled on bridge device and frame was
176181
* sent from vlan device on the bridge device, it does not have
177182
* HW accelerated vlan tag.
178183
*/
179184
if (unlikely(!vlan_tx_tag_present(skb) &&
180-
(skb->protocol == htons(ETH_P_8021Q) ||
181-
skb->protocol == htons(ETH_P_8021AD)))) {
185+
skb->protocol == proto)) {
182186
skb = vlan_untag(skb);
183187
if (unlikely(!skb))
184188
return false;
185189
}
186190

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+
188213
if (!*vid) {
189214
u16 pvid = br_get_pvid(v);
190215

@@ -199,9 +224,9 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
199224
* ingress frame is considered to belong to this vlan.
200225
*/
201226
*vid = pvid;
202-
if (likely(err))
227+
if (likely(!tagged))
203228
/* Untagged Frame. */
204-
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid);
229+
__vlan_hwaccel_put_tag(skb, proto, pvid);
205230
else
206231
/* Priority-tagged Frame.
207232
* 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)
254279
if (!v)
255280
return false;
256281

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+
258285
if (!*vid) {
259286
*vid = br_get_pvid(v);
260287
if (*vid == VLAN_N_VID)
@@ -367,6 +394,11 @@ int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
367394
return 0;
368395
}
369396

397+
void br_vlan_init(struct net_bridge *br)
398+
{
399+
br->vlan_proto = htons(ETH_P_8021Q);
400+
}
401+
370402
/* Must be protected by RTNL.
371403
* Must be called with vid in range from 1 to 4094 inclusive.
372404
*/
@@ -433,7 +465,7 @@ void nbp_vlan_flush(struct net_bridge_port *port)
433465
return;
434466

435467
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);
437469

438470
__vlan_flush(pv);
439471
}

0 commit comments

Comments
 (0)