History

bridge: Fix inabillity to retrieve vlan tags when tx offload is disabled

Bridge vlan code (br_vlan_get_tag()) assumes that all frames have vlan_tci if they are tagged, but if vlan tx offload is manually disabled on bridge device and frames are sent from vlan device on the bridge device, the tags are embedded in skb->data and they break this assumption. Extract embedded vlan tags and move them to vlan_tci at ingress.

Toshiaki Makita committed 12 years ago

Commit 12464bb1 parent a39ee442 files · +15 −3Browse files

Unified · Split

2 files
  1. net/bridge/br_device.c +3 −3
  2. net/bridge/br_vlan.c +12 −0
net/bridge/br_device.c+3−3
@@ -49,14 +49,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) · 48 unmodified lines
4949 brstats->tx_bytes += skb->len;
5050 u64_stats_update_end(&brstats->syncp);
5151
52− if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
53− goto out;
54−
5552 BR_INPUT_SKB_CB(skb)->brdev = dev;
5653
5754 skb_reset_mac_header(skb);
5855 skb_pull(skb, ETH_HLEN);
5956
57+ if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
58+ goto out;
59+
6060 if (is_broadcast_ether_addr(dest))
6161 br_flood_deliver(br, skb, false);
6262 else if (is_multicast_ether_addr(dest)) {
net/bridge/br_vlan.c+12−0
@@ -174,6 +174,18 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, · 173 unmodified lines
174174 if (!v)
175175 return false;
176176
177+ /* If vlan tx offload is disabled on bridge device and frame was
178+ * sent from vlan device on the bridge device, it does not have
179+ * HW accelerated vlan tag.
180+ */
181+ if (unlikely(!vlan_tx_tag_present(skb) &&
182+ (skb->protocol == htons(ETH_P_8021Q) ||
183+ skb->protocol == htons(ETH_P_8021AD)))) {
184+ skb = vlan_untag(skb);
185+ if (unlikely(!skb))
186+ return false;
187+ }
188+
177189 err = br_vlan_get_tag(skb, vid);
178190 if (!*vid) {
179191 u16 pvid = br_get_pvid(v);