aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2017-04-14 10:07:49 +0200
committerSteffen Klassert <steffen.klassert@secunet.com>2017-04-14 10:07:49 +0200
commitbcd1f8a45e7d5804e4f7bd78a91348cfce3cb74a (patch)
tree16bbfdf78347e85972881ae8de3c32c7a775fff2
parentxfrm: Add encapsulation header offsets while SKB is not encrypted (diff)
downloadlinux-dev-bcd1f8a45e7d5804e4f7bd78a91348cfce3cb74a.tar.xz
linux-dev-bcd1f8a45e7d5804e4f7bd78a91348cfce3cb74a.zip
xfrm: Prepare the GRO codepath for hardware offloading.
On IPsec hardware offloading, we already get a secpath with valid state attached when the packet enters the GRO handlers. So check for hardware offload and skip the state lookup in this case. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
-rw-r--r--net/ipv4/esp4_offload.c42
-rw-r--r--net/ipv6/esp6_offload.c42
-rw-r--r--net/xfrm/xfrm_input.c50
3 files changed, 71 insertions, 63 deletions
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 1e39564cb8b4..f3e33c26dc33 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -43,27 +43,31 @@ static struct sk_buff **esp4_gro_receive(struct sk_buff **head,
if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
goto out;
- err = secpath_set(skb);
- if (err)
- goto out;
-
- if (skb->sp->len == XFRM_MAX_DEPTH)
- goto out;
-
- x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
- (xfrm_address_t *)&ip_hdr(skb)->daddr,
- spi, IPPROTO_ESP, AF_INET);
- if (!x)
- goto out;
-
- skb->sp->xvec[skb->sp->len++] = x;
- skb->sp->olen++;
-
xo = xfrm_offload(skb);
- if (!xo) {
- xfrm_state_put(x);
- goto out;
+ if (!xo || !(xo->flags & CRYPTO_DONE)) {
+ err = secpath_set(skb);
+ if (err)
+ goto out;
+
+ if (skb->sp->len == XFRM_MAX_DEPTH)
+ goto out;
+
+ x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
+ (xfrm_address_t *)&ip_hdr(skb)->daddr,
+ spi, IPPROTO_ESP, AF_INET);
+ if (!x)
+ goto out;
+
+ skb->sp->xvec[skb->sp->len++] = x;
+ skb->sp->olen++;
+
+ xo = xfrm_offload(skb);
+ if (!xo) {
+ xfrm_state_put(x);
+ goto out;
+ }
}
+
xo->flags |= XFRM_GRO;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 06e972135ab0..1cceeee7cc33 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -45,27 +45,31 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
goto out;
- err = secpath_set(skb);
- if (err)
- goto out;
-
- if (skb->sp->len == XFRM_MAX_DEPTH)
- goto out;
-
- x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
- (xfrm_address_t *)&ipv6_hdr(skb)->daddr,
- spi, IPPROTO_ESP, AF_INET6);
- if (!x)
- goto out;
-
- skb->sp->xvec[skb->sp->len++] = x;
- skb->sp->olen++;
-
xo = xfrm_offload(skb);
- if (!xo) {
- xfrm_state_put(x);
- goto out;
+ if (!xo || !(xo->flags & CRYPTO_DONE)) {
+ err = secpath_set(skb);
+ if (err)
+ goto out;
+
+ if (skb->sp->len == XFRM_MAX_DEPTH)
+ goto out;
+
+ x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
+ (xfrm_address_t *)&ipv6_hdr(skb)->daddr,
+ spi, IPPROTO_ESP, AF_INET6);
+ if (!x)
+ goto out;
+
+ skb->sp->xvec[skb->sp->len++] = x;
+ skb->sp->olen++;
+
+ xo = xfrm_offload(skb);
+ if (!xo) {
+ xfrm_state_put(x);
+ goto out;
+ }
}
+
xo->flags |= XFRM_GRO;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 362d655eac27..21c6cc965402 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -223,38 +223,38 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
seq = XFRM_SKB_CB(skb)->seq.input.low;
goto resume;
}
+
/* encap_type < -1 indicates a GRO call. */
encap_type = 0;
seq = XFRM_SPI_SKB_CB(skb)->seq;
- goto lock;
- }
-
- if (xo && (xo->flags & CRYPTO_DONE)) {
- crypto_done = true;
- x = xfrm_input_state(skb);
- family = XFRM_SPI_SKB_CB(skb)->family;
- if (!(xo->status & CRYPTO_SUCCESS)) {
- if (xo->status &
- (CRYPTO_TRANSPORT_AH_AUTH_FAILED |
- CRYPTO_TRANSPORT_ESP_AUTH_FAILED |
- CRYPTO_TUNNEL_AH_AUTH_FAILED |
- CRYPTO_TUNNEL_ESP_AUTH_FAILED)) {
-
- xfrm_audit_state_icvfail(x, skb,
- x->type->proto);
- x->stats.integrity_failed++;
- XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR);
+ if (xo && (xo->flags & CRYPTO_DONE)) {
+ crypto_done = true;
+ x = xfrm_input_state(skb);
+ family = XFRM_SPI_SKB_CB(skb)->family;
+
+ if (!(xo->status & CRYPTO_SUCCESS)) {
+ if (xo->status &
+ (CRYPTO_TRANSPORT_AH_AUTH_FAILED |
+ CRYPTO_TRANSPORT_ESP_AUTH_FAILED |
+ CRYPTO_TUNNEL_AH_AUTH_FAILED |
+ CRYPTO_TUNNEL_ESP_AUTH_FAILED)) {
+
+ xfrm_audit_state_icvfail(x, skb,
+ x->type->proto);
+ x->stats.integrity_failed++;
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR);
+ goto drop;
+ }
+
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
goto drop;
}
- XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
- goto drop;
- }
-
- if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
- XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
- goto drop;
+ if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
+ goto drop;
+ }
}
goto lock;