Commit bcd1f8a4 authored by Steffen Klassert's avatar Steffen Klassert

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: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent f1bd7d65
...@@ -43,27 +43,31 @@ static struct sk_buff **esp4_gro_receive(struct sk_buff **head, ...@@ -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) if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
goto out; 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); xo = xfrm_offload(skb);
if (!xo) { if (!xo || !(xo->flags & CRYPTO_DONE)) {
xfrm_state_put(x); err = secpath_set(skb);
goto out; 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; xo->flags |= XFRM_GRO;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
......
...@@ -45,27 +45,31 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head, ...@@ -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) if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
goto out; 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); xo = xfrm_offload(skb);
if (!xo) { if (!xo || !(xo->flags & CRYPTO_DONE)) {
xfrm_state_put(x); err = secpath_set(skb);
goto out; 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; xo->flags |= XFRM_GRO;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
......
...@@ -223,38 +223,38 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -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; seq = XFRM_SKB_CB(skb)->seq.input.low;
goto resume; goto resume;
} }
/* encap_type < -1 indicates a GRO call. */ /* encap_type < -1 indicates a GRO call. */
encap_type = 0; encap_type = 0;
seq = XFRM_SPI_SKB_CB(skb)->seq; 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 && (xo->flags & CRYPTO_DONE)) {
if (xo->status & crypto_done = true;
(CRYPTO_TRANSPORT_AH_AUTH_FAILED | x = xfrm_input_state(skb);
CRYPTO_TRANSPORT_ESP_AUTH_FAILED | family = XFRM_SPI_SKB_CB(skb)->family;
CRYPTO_TUNNEL_AH_AUTH_FAILED |
CRYPTO_TUNNEL_ESP_AUTH_FAILED)) { if (!(xo->status & CRYPTO_SUCCESS)) {
if (xo->status &
xfrm_audit_state_icvfail(x, skb, (CRYPTO_TRANSPORT_AH_AUTH_FAILED |
x->type->proto); CRYPTO_TRANSPORT_ESP_AUTH_FAILED |
x->stats.integrity_failed++; CRYPTO_TUNNEL_AH_AUTH_FAILED |
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR); 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; goto drop;
} }
XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
goto drop; 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; goto lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment