@@ -4046,7 +4046,7 @@ int skb_ensure_writable(struct sk_buff *skb, unsigned int write_len);
int skb_ensure_writable_head_tail(struct sk_buff *skb, struct net_device *dev);
int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci);
int skb_vlan_pop(struct sk_buff *skb);
-int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
+int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci, u16 hlen);
int skb_eth_pop(struct sk_buff *skb);
int skb_eth_push(struct sk_buff *skb, const unsigned char *dst,
const unsigned char *src);
@@ -3187,7 +3187,7 @@ BPF_CALL_3(bpf_skb_vlan_push, struct sk_buff *, skb, __be16, vlan_proto,
vlan_proto = htons(ETH_P_8021Q);
bpf_push_mac_rcsum(skb);
- ret = skb_vlan_push(skb, vlan_proto, vlan_tci);
+ ret = skb_vlan_push(skb, vlan_proto, vlan_tci, VLAN_HLEN);
bpf_pull_mac_rcsum(skb);
bpf_compute_data_pointers(skb);
@@ -6223,7 +6223,7 @@ EXPORT_SYMBOL(skb_vlan_pop);
/* Push a vlan tag either into hwaccel or into payload (if hwaccel tag present).
* Expects skb->data at mac header.
*/
-int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
+int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci, u16 hlen)
{
if (skb_vlan_tag_present(skb)) {
int offset = skb->data - skb_mac_header(skb);
@@ -6241,7 +6241,7 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
return err;
skb->protocol = skb->vlan_proto;
- skb->mac_len += VLAN_HLEN;
+ skb->mac_len += hlen;
skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
}
@@ -244,7 +244,8 @@ static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
key->eth.vlan.tpid = vlan->vlan_tpid;
}
return skb_vlan_push(skb, vlan->vlan_tpid,
- ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
+ ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK,
+ VLAN_HLEN);
}
/* 'src' is already properly masked. */
@@ -50,7 +50,8 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
break;
case TCA_VLAN_ACT_PUSH:
err = skb_vlan_push(skb, p->tcfv_push_proto, p->tcfv_push_vid |
- (p->tcfv_push_prio << VLAN_PRIO_SHIFT));
+ (p->tcfv_push_prio << VLAN_PRIO_SHIFT),
+ VLAN_HLEN);
if (err)
goto drop;
break;
In case of vlan tagged packet, skb_vlan_push flushes current vlan header into skb packet buffer. It also advances skb->mac_len by VLAN_HLEN amount. Some of the callers of skb_vlan_push (e.g. net/sched/act_vlan.c) may want to reset skb network header by themselves. To allow this we pass VLAN_HLEN as an argument to skb_vlan_push. Signed-off-by: Boris Sukholitko <boris.sukholitko@broadcom.com> --- include/linux/skbuff.h | 2 +- net/core/filter.c | 2 +- net/core/skbuff.c | 4 ++-- net/openvswitch/actions.c | 3 ++- net/sched/act_vlan.c | 3 ++- 5 files changed, 8 insertions(+), 6 deletions(-)