Skip to content

Commit

Permalink
bridge: Fix inabillity to retrieve vlan tags when tx offload is disabled
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Acked-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Toshiaki Makita authored and David S. Miller committed Mar 28, 2014
1 parent a39ee44 commit 12464bb
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
6 changes: 3 additions & 3 deletions net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
brstats->tx_bytes += skb->len;
u64_stats_update_end(&brstats->syncp);

if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
goto out;

BR_INPUT_SKB_CB(skb)->brdev = dev;

skb_reset_mac_header(skb);
skb_pull(skb, ETH_HLEN);

if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
goto out;

if (is_broadcast_ether_addr(dest))
br_flood_deliver(br, skb, false);
else if (is_multicast_ether_addr(dest)) {
Expand Down
12 changes: 12 additions & 0 deletions net/bridge/br_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
if (!v)
return false;

/* If vlan tx offload is disabled on bridge device and frame was
* sent from vlan device on the bridge device, it does not have
* HW accelerated vlan tag.
*/
if (unlikely(!vlan_tx_tag_present(skb) &&
(skb->protocol == htons(ETH_P_8021Q) ||
skb->protocol == htons(ETH_P_8021AD)))) {
skb = vlan_untag(skb);
if (unlikely(!skb))
return false;
}

err = br_vlan_get_tag(skb, vid);
if (!*vid) {
u16 pvid = br_get_pvid(v);
Expand Down

0 comments on commit 12464bb

Please sign in to comment.