The skb->mac_len is used for the skb_push before inserting the vlan tag to
the packet payload. After that the skb is pulled only ETH_HLEN and the
network header is being reset to get the correct packet mac header. This
avoids sending packets with incorrect mac header when vlan tags are pushed
with tc-vlan and the bridge tpid does not match the inserted vlan tpid. The
vlan tag is inserted at the right place of the header.

Signed-off-by: Zahari Doychev <zahari.doyc...@linux.com>
---
 net/bridge/br_vlan.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 4a2f31157ef5..f857487245c6 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -460,13 +460,14 @@ static bool __allowed_ingress(const struct net_bridge *br,
                /* Tagged frame */
                if (skb->vlan_proto != br->vlan_proto) {
                        /* Protocol-mismatch, empty out vlan_tci for new tag */
-                       skb_push(skb, ETH_HLEN);
+                       skb_push(skb, skb->mac_len);
                        skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
                                                        skb_vlan_tag_get(skb));
                        if (unlikely(!skb))
                                return false;
 
                        skb_pull(skb, ETH_HLEN);
+                       skb_reset_network_header(skb);
                        skb_reset_mac_len(skb);
                        *vid = 0;
                        tagged = false;
-- 
2.20.1

Reply via email to