aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2022-07-14 10:15:15 +0200
committerPaolo Abeni <pabeni@redhat.com>2022-07-14 10:15:16 +0200
commitcc91b09b9ef8f8a9f29b4fdff5f65ab5700872e2 (patch)
treec3b86b9d6bd0b2f456965e79343806a0af6ceab5
parentMerge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue (diff)
parentseg6: bpf: fix skb checksum in bpf_push_seg6_encap() (diff)
downloadlinux-dev-cc91b09b9ef8f8a9f29b4fdff5f65ab5700872e2.tar.xz
linux-dev-cc91b09b9ef8f8a9f29b4fdff5f65ab5700872e2.zip
Merge branch 'seg6-fix-skb-checksum-for-srh-encapsulation-insertion'
Andrea Mayer says: ==================== seg6: fix skb checksum for SRH encapsulation/insertion The Linux kernel supports Segment Routing Header (SRH) encapsulation/insertion operations by providing the capability to: i) encapsulate a packet in an outer IPv6 header with a specified SRH; ii) insert a specified SRH directly after the IPv6 header of the packet. Note that the insertion operation is also referred to as 'injection'. The two operations are respectively supported by seg6_do_srh_encap() and seg6_do_srh_inline(), which operate on the skb associated to the packet as needed (e.g. adding the necessary headers and initializing them, while taking care to recalculate the skb checksum). seg6_do_srh_encap() and seg6_do_srh_inline() do not initialize the payload length of the IPv6 header, which is carried out by the caller functions. However, this approach causes the corruption of the skb checksum which needs to be updated only after initialization of headers is completed (thanks to Paolo Abeni for detecting this issue). The patchset fixes the skb checksum corruption by moving the IPv6 header payload length initialization from the callers of seg6_do_srh_encap() and seg6_do_srh_inline() directly into these functions. This patchset is organized as follows: - patch 1/3, seg6: fix skb checksum evaluation in SRH encapsulation/insertion; (* SRH encapsulation/insertion available since v4.10) - patch 2/3, seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors; (* SRv6 End.B6 and End.B6.Encaps behaviors available since v4.14) - patch 3/3, seg6: bpf: fix skb checksum in bpf_push_seg6_encap(); (* bpf IPv6 Segment Routing helpers available since v4.18) ==================== Link: https://lore.kernel.org/r/20220712175837.16267-1-andrea.mayer@uniroma2.it Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--net/core/filter.c1
-rw-r--r--net/ipv6/seg6_iptunnel.c5
-rw-r--r--net/ipv6/seg6_local.c2
3 files changed, 4 insertions, 4 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 5d16d66727fc..2a6a0b0ce43e 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -6158,7 +6158,6 @@ static int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len
if (err)
return err;
- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
return seg6_lookup_nexthop(skb, NULL, 0);
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index d64855010948..e756ba705fd9 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -189,6 +189,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
}
#endif
+ hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+
skb_postpush_rcsum(skb, hdr, tot_len);
return 0;
@@ -241,6 +243,8 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
}
#endif
+ hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+
skb_postpush_rcsum(skb, hdr, sizeof(struct ipv6hdr) + hdrlen);
return 0;
@@ -302,7 +306,6 @@ static int seg6_do_srh(struct sk_buff *skb)
break;
}
- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
nf_reset_ct(skb);
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 98a34287439c..2cd4a8d3b30a 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -826,7 +826,6 @@ static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
if (err)
goto drop;
- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
seg6_lookup_nexthop(skb, NULL, 0);
@@ -858,7 +857,6 @@ static int input_action_end_b6_encap(struct sk_buff *skb,
if (err)
goto drop;
- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
seg6_lookup_nexthop(skb, NULL, 0);