* [PATCH net-next 0/4] CHECKSUM_COMPLETE in IPSec
@ 2017-06-22 12:31 ilant
2017-06-22 12:31 ` [PATCH net-next 1/4] esp4: Support RX checksum with crypto offload ilant
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: ilant @ 2017-06-22 12:31 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Ilan Tayari
From: Ilan Tayari <ilant@mellanox.com>
This patchset adds support for RX checksum offload in IPSec.
When crypto is performed in the host, the checksum needs to
be recalculated over all the payload.
However, when crypto is performed in the NIC, the NIC may
provide useful CHECKSUM_COMPLETE value, which then only needs
to be updated to account for decapsulation.
Note: This patchset is on top of the recent two IPv6 xfrm
patches which were submitted to 'net'.
Ilan Tayari (2):
esp4: Support RX checksum with crypto offload
esp6: Support RX checksum with crypto offload
Yossi Kuperman (2):
xfrm6: Fix CHECKSUM_COMPLETE after IPv6 header push
esp6: Fix RX checksum after header pull
net/ipv4/esp4.c | 13 +++++++++++--
net/ipv4/esp4_offload.c | 4 +++-
net/ipv6/esp6.c | 15 +++++++++++++--
net/ipv6/esp6_offload.c | 4 +++-
net/ipv6/xfrm6_input.c | 4 +++-
5 files changed, 33 insertions(+), 7 deletions(-)
--
2.11.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net-next 1/4] esp4: Support RX checksum with crypto offload
2017-06-22 12:31 [PATCH net-next 0/4] CHECKSUM_COMPLETE in IPSec ilant
@ 2017-06-22 12:31 ` ilant
2017-06-22 12:31 ` [PATCH net-next 2/4] esp6: " ilant
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: ilant @ 2017-06-22 12:31 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Ilan Tayari, Ariel Levkovich
From: Ilan Tayari <ilant@mellanox.com>
Keep the device's reported ip_summed indication in case crypto
was offloaded by the device. Subtract the csum values of the
stripped parts (esp header+iv, esp trailer+auth_data) to keep
value correct.
Note: CHECKSUM_COMPLETE should be indicated only if skb->csum
has the post-decryption offload csum value.
Signed-off-by: Ariel Levkovich <lariel@mellanox.com>
Signed-off-by: Ilan Tayari <ilant@mellanox.com>
---
net/ipv4/esp4.c | 13 +++++++++++--
net/ipv4/esp4_offload.c | 4 +++-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 1f18b4650253..2eab0992b127 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -510,7 +510,8 @@ int esp_input_done2(struct sk_buff *skb, int err)
int elen = skb->len - hlen;
int ihl;
u8 nexthdr[2];
- int padlen;
+ int padlen, trimlen;
+ __wsum csumdiff;
if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
kfree(ESP_SKB_CB(skb)->tmp);
@@ -568,7 +569,15 @@ int esp_input_done2(struct sk_buff *skb, int err)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
- pskb_trim(skb, skb->len - alen - padlen - 2);
+ trimlen = alen + padlen + 2;
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
+ skb->csum = csum_block_sub(skb->csum, csumdiff,
+ skb->len - trimlen);
+ skb_postpull_rcsum(skb, skb->data, hlen);
+ }
+
+ pskb_trim(skb, skb->len - trimlen);
__skb_pull(skb, hlen);
if (x->props.mode == XFRM_MODE_TUNNEL)
skb_reset_transport_header(skb);
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index e0666016a764..05831dea00f4 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -182,11 +182,13 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
{
struct crypto_aead *aead = x->data;
+ struct xfrm_offload *xo = xfrm_offload(skb);
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
return -EINVAL;
- skb->ip_summed = CHECKSUM_NONE;
+ if (!(xo->flags & CRYPTO_DONE))
+ skb->ip_summed = CHECKSUM_NONE;
return esp_input_done2(skb, 0);
}
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net-next 2/4] esp6: Support RX checksum with crypto offload
2017-06-22 12:31 [PATCH net-next 0/4] CHECKSUM_COMPLETE in IPSec ilant
2017-06-22 12:31 ` [PATCH net-next 1/4] esp4: Support RX checksum with crypto offload ilant
@ 2017-06-22 12:31 ` ilant
2017-06-22 12:31 ` [PATCH net-next 3/4] xfrm6: Fix CHECKSUM_COMPLETE after IPv6 header push ilant
2017-06-22 12:31 ` [PATCH net-next 4/4] esp6: Fix RX checksum after header pull ilant
3 siblings, 0 replies; 5+ messages in thread
From: ilant @ 2017-06-22 12:31 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Ilan Tayari, Ariel Levkovich
From: Ilan Tayari <ilant@mellanox.com>
Keep the device's reported ip_summed indication in case crypto
was offloaded by the device. Subtract the csum values of the
stripped parts (esp header+iv, esp trailer+auth_data) to keep
value correct.
Note: CHECKSUM_COMPLETE should be indicated only if skb->csum
has the post-decryption offload csum value.
Signed-off-by: Ariel Levkovich <lariel@mellanox.com>
Signed-off-by: Ilan Tayari <ilant@mellanox.com>
---
net/ipv6/esp6.c | 13 +++++++++++--
net/ipv6/esp6_offload.c | 4 +++-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index d8b40ff4b2e6..f872bb16cc9d 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -475,7 +475,8 @@ int esp6_input_done2(struct sk_buff *skb, int err)
int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
int elen = skb->len - hlen;
int hdr_len = skb_network_header_len(skb);
- int padlen;
+ int padlen, trimlen;
+ __wsum csumdiff;
u8 nexthdr[2];
if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
@@ -497,7 +498,15 @@ int esp6_input_done2(struct sk_buff *skb, int err)
/* ... check padding bits here. Silly. :-) */
- pskb_trim(skb, skb->len - alen - padlen - 2);
+ trimlen = alen + padlen + 2;
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
+ skb->csum = csum_block_sub(skb->csum, csumdiff,
+ skb->len - trimlen);
+ skb_postpull_rcsum(skb, skb->data, hlen);
+ }
+
+ pskb_trim(skb, skb->len - trimlen);
__skb_pull(skb, hlen);
if (x->props.mode == XFRM_MODE_TUNNEL)
skb_reset_transport_header(skb);
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index f02f131f6435..eec3add177fe 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -209,11 +209,13 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
{
struct crypto_aead *aead = x->data;
+ struct xfrm_offload *xo = xfrm_offload(skb);
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
return -EINVAL;
- skb->ip_summed = CHECKSUM_NONE;
+ if (!(xo->flags & CRYPTO_DONE))
+ skb->ip_summed = CHECKSUM_NONE;
return esp6_input_done2(skb, 0);
}
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net-next 3/4] xfrm6: Fix CHECKSUM_COMPLETE after IPv6 header push
2017-06-22 12:31 [PATCH net-next 0/4] CHECKSUM_COMPLETE in IPSec ilant
2017-06-22 12:31 ` [PATCH net-next 1/4] esp4: Support RX checksum with crypto offload ilant
2017-06-22 12:31 ` [PATCH net-next 2/4] esp6: " ilant
@ 2017-06-22 12:31 ` ilant
2017-06-22 12:31 ` [PATCH net-next 4/4] esp6: Fix RX checksum after header pull ilant
3 siblings, 0 replies; 5+ messages in thread
From: ilant @ 2017-06-22 12:31 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Yossi Kuperman
From: Yossi Kuperman <yossiku@mellanox.com>
xfrm6_transport_finish rebuilds the IPv6 header based on the
original one and pushes it back without fixing skb->csum.
Therefore, CHECKSUM_COMPLETE is no longer valid and the packet
gets dropped.
Fix skb->csum by calling skb_postpush_rcsum.
Note: A valid IPv4 header has checksum 0, unlike IPv6. Thus,
the change is not needed in the sibling xfrm4_transport_finish
function.
Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
---
net/ipv6/xfrm6_input.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 3ef5d913e7a3..f95943a13abc 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -34,6 +34,7 @@ EXPORT_SYMBOL(xfrm6_rcv_spi);
int xfrm6_transport_finish(struct sk_buff *skb, int async)
{
struct xfrm_offload *xo = xfrm_offload(skb);
+ int nhlen = skb->data - skb_network_header(skb);
skb_network_header(skb)[IP6CB(skb)->nhoff] =
XFRM_MODE_SKB_CB(skb)->protocol;
@@ -43,8 +44,9 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
return 1;
#endif
- __skb_push(skb, skb->data - skb_network_header(skb));
+ __skb_push(skb, nhlen);
ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+ skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
if (xo && (xo->flags & XFRM_GRO)) {
skb_mac_header_rebuild(skb);
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net-next 4/4] esp6: Fix RX checksum after header pull
2017-06-22 12:31 [PATCH net-next 0/4] CHECKSUM_COMPLETE in IPSec ilant
` (2 preceding siblings ...)
2017-06-22 12:31 ` [PATCH net-next 3/4] xfrm6: Fix CHECKSUM_COMPLETE after IPv6 header push ilant
@ 2017-06-22 12:31 ` ilant
3 siblings, 0 replies; 5+ messages in thread
From: ilant @ 2017-06-22 12:31 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Yossi Kuperman
From: Yossi Kuperman <yossiku@mellanox.com>
Both ip6_input_finish (non-GRO) and esp6_gro_receive (GRO) strip
the IPv6 header without adjusting skb->csum accordingly. As a
result CHECKSUM_COMPLETE breaks and "hw csum failure" is written
to the kernel log by netdev_rx_csum_fault (dev.c).
Fix skb->csum by substracting the checksum value of the pulled IPv6
header using a call to skb_postpull_rcsum.
This affects both transport and tunnel modes.
Note that the fix occurs far from the place that the header was
pulled. This is based on existing code, see:
ipv6_srh_rcv() in exthdrs.c and rawv6_rcv() in raw.c
Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
---
net/ipv6/esp6.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index f872bb16cc9d..3fed3947acf9 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -500,6 +500,8 @@ int esp6_input_done2(struct sk_buff *skb, int err)
trimlen = alen + padlen + 2;
if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ skb_postpull_rcsum(skb, skb_network_header(skb),
+ skb_network_header_len(skb));
csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
skb->csum = csum_block_sub(skb->csum, csumdiff,
skb->len - trimlen);
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-06-22 12:32 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-22 12:31 [PATCH net-next 0/4] CHECKSUM_COMPLETE in IPSec ilant
2017-06-22 12:31 ` [PATCH net-next 1/4] esp4: Support RX checksum with crypto offload ilant
2017-06-22 12:31 ` [PATCH net-next 2/4] esp6: " ilant
2017-06-22 12:31 ` [PATCH net-next 3/4] xfrm6: Fix CHECKSUM_COMPLETE after IPv6 header push ilant
2017-06-22 12:31 ` [PATCH net-next 4/4] esp6: Fix RX checksum after header pull ilant
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).