* [PATCH net-next 1/2] skb: skb_vlan_push gets VLAN_HLEN as an argument
2024-07-11 7:08 [PATCH net-next 0/2] tc: adjust network header after second vlan push Boris Sukholitko
@ 2024-07-11 7:08 ` Boris Sukholitko
2024-07-11 7:08 ` [PATCH net-next 2/2] tc vlan: adjust network header in tcf_vlan_act Boris Sukholitko
2024-07-15 15:59 ` [PATCH net-next 0/2] tc: adjust network header after second vlan push Jakub Kicinski
2 siblings, 0 replies; 4+ messages in thread
From: Boris Sukholitko @ 2024-07-11 7:08 UTC (permalink / raw)
To: netdev, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Pravin B Shelar, Jamal Hadi Salim, Cong Wang, Jiri Pirko,
Willem de Bruijn, Simon Horman, Florian Westphal, Mina Almasry,
Abhishek Chauhan, David Howells, Alexander Lobakin,
Pavel Begunkov, Lorenzo Bianconi, Thomas Weißschuh
Cc: Ilya Lifshits
[-- Attachment #1: Type: text/plain, Size: 3665 bytes --]
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(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9c29bdd5596d..e13f44fe33df 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -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);
diff --git a/net/core/filter.c b/net/core/filter.c
index d767880c276d..bb14574422b5 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -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);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 83f8cd8aa2d1..9c69c9bff55c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -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);
}
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 101f9a23792c..34909aca3526 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -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. */
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 22f4b1e8ade9..f60cf7062572 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -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;
--
2.42.0
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4221 bytes --]
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH net-next 2/2] tc vlan: adjust network header in tcf_vlan_act
2024-07-11 7:08 [PATCH net-next 0/2] tc: adjust network header after second vlan push Boris Sukholitko
2024-07-11 7:08 ` [PATCH net-next 1/2] skb: skb_vlan_push gets VLAN_HLEN as an argument Boris Sukholitko
@ 2024-07-11 7:08 ` Boris Sukholitko
2024-07-15 15:59 ` [PATCH net-next 0/2] tc: adjust network header after second vlan push Jakub Kicinski
2 siblings, 0 replies; 4+ messages in thread
From: Boris Sukholitko @ 2024-07-11 7:08 UTC (permalink / raw)
To: netdev, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Pravin B Shelar, Jamal Hadi Salim, Cong Wang, Jiri Pirko,
Willem de Bruijn, Simon Horman, Florian Westphal, Mina Almasry,
Abhishek Chauhan, David Howells, Alexander Lobakin,
Pavel Begunkov, Lorenzo Bianconi, Thomas Weißschuh
Cc: Ilya Lifshits
[-- Attachment #1: Type: text/plain, Size: 1522 bytes --]
When double-tagged VLAN packet enters Linux network stack the outer
vlan is stripped and copied to the skb. As a result, skb->data points
to the inner vlan.
When second vlan is pushed by tcf_vlan_act, skb->mac_len will be advanced
by skb_vlan_push. As a result, the final skb_pull_rcsum will have
network header pointing to the inner protocol header (e.g. IP) rather than
inner vlan as expected. This causes a problem with further TC processing
as __skb_flow_dissect expects the network header to point to the inner
vlan.
To fix this problem, we disable skb->mac_len advancement and reset
network header and mac_len at the end of tcf_vlan_act.
Signed-off-by: Boris Sukholitko <boris.sukholitko@broadcom.com>
---
net/sched/act_vlan.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index f60cf7062572..8de6f363885b 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -51,7 +51,7 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
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),
- VLAN_HLEN);
+ 0);
if (err)
goto drop;
break;
@@ -94,8 +94,11 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
}
out:
- if (skb_at_tc_ingress(skb))
+ if (skb_at_tc_ingress(skb)) {
skb_pull_rcsum(skb, skb->mac_len);
+ skb_reset_network_header(skb);
+ skb_reset_mac_len(skb);
+ }
return action;
--
2.42.0
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4221 bytes --]
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH net-next 0/2] tc: adjust network header after second vlan push
2024-07-11 7:08 [PATCH net-next 0/2] tc: adjust network header after second vlan push Boris Sukholitko
2024-07-11 7:08 ` [PATCH net-next 1/2] skb: skb_vlan_push gets VLAN_HLEN as an argument Boris Sukholitko
2024-07-11 7:08 ` [PATCH net-next 2/2] tc vlan: adjust network header in tcf_vlan_act Boris Sukholitko
@ 2024-07-15 15:59 ` Jakub Kicinski
2 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2024-07-15 15:59 UTC (permalink / raw)
To: Boris Sukholitko
Cc: netdev, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
David S . Miller, Eric Dumazet, Paolo Abeni, Pravin B Shelar,
Jamal Hadi Salim, Cong Wang, Jiri Pirko, Willem de Bruijn,
Simon Horman, Florian Westphal, Mina Almasry, Abhishek Chauhan,
David Howells, Alexander Lobakin, Pavel Begunkov,
Lorenzo Bianconi, Thomas Weißschuh, Ilya Lifshits
On Thu, 11 Jul 2024 10:08:26 +0300 Boris Sukholitko wrote:
> skb network header of the single-tagged vlan packet continues to point the
> vlan payload (e.g. IP) after second vlan tag is pushed by tc act_vlan. This
> causes problem at the dissector which expects double-tagged packet network
> header to point to the inner vlan.
>
> The fix is to adjust network header in tcf_act_vlan.c but requires minor
> changes to the generic skb_vlan_push function.
This requires more careful analysis than I can afford right now since
the merge window has started, sorry :( Please repost once net-next
reopens: https://netdev.bots.linux.dev/net-next.html
--
pw-bot: defer
^ permalink raw reply [flat|nested] 4+ messages in thread