Skip to content

Commit

Permalink
xfrm: remove output_finish indirection from xfrm_state_afinfo
Browse files Browse the repository at this point in the history
There are only two implementaions, one for ipv4 and one for ipv6.

Both are almost identical, they clear skb->cb[], set the TRANSFORMED flag
in IP(6)CB and then call the common xfrm_output() function.

By placing the IPCB handling into the common function, we avoid the need
for the output_finish indirection as the output functions can simply
use xfrm_output().

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
  • Loading branch information
Florian Westphal authored and Steffen Klassert committed May 6, 2020
1 parent f3075f4 commit 2ab6096
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 57 deletions.
1 change: 0 additions & 1 deletion include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ struct xfrm_state_afinfo {
const struct xfrm_type *type_dstopts;

int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*output_finish)(struct sock *sk, struct sk_buff *skb);
int (*transport_finish)(struct sk_buff *skb,
int async);
void (*local_error)(struct sk_buff *skb, u32 mtu);
Expand Down
23 changes: 1 addition & 22 deletions net/ipv4/xfrm4_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,9 @@
#include <net/xfrm.h>
#include <net/icmp.h>

int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
{
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));

#ifdef CONFIG_NETFILTER
IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
#endif

return xfrm_output(sk, skb);
}

static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct xfrm_state *x = skb_dst(skb)->xfrm;
const struct xfrm_state_afinfo *afinfo;
int ret = -EAFNOSUPPORT;

#ifdef CONFIG_NETFILTER
if (!x) {
Expand All @@ -38,15 +25,7 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
}
#endif

rcu_read_lock();
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
if (likely(afinfo))
ret = afinfo->output_finish(sk, skb);
else
kfree_skb(skb);
rcu_read_unlock();

return ret;
return xfrm_output(sk, skb);
}

int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
Expand Down
1 change: 0 additions & 1 deletion net/ipv4/xfrm4_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
.family = AF_INET,
.proto = IPPROTO_IPIP,
.output = xfrm4_output,
.output_finish = xfrm4_output_finish,
.transport_finish = xfrm4_transport_finish,
.local_error = xfrm4_local_error,
};
Expand Down
34 changes: 2 additions & 32 deletions net/ipv6/xfrm6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,39 +47,9 @@ void xfrm6_local_error(struct sk_buff *skb, u32 mtu)
ipv6_local_error(sk, EMSGSIZE, &fl6, mtu);
}

int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
{
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));

#ifdef CONFIG_NETFILTER
IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
#endif

return xfrm_output(sk, skb);
}

static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk,
struct sk_buff *skb)
{
const struct xfrm_state_afinfo *afinfo;
int ret = -EAFNOSUPPORT;

rcu_read_lock();
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
if (likely(afinfo))
ret = afinfo->output_finish(sk, skb);
else
kfree_skb(skb);
rcu_read_unlock();

return ret;
}

static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct xfrm_state *x = skb_dst(skb)->xfrm;

return __xfrm6_output_state_finish(x, sk, skb);
return xfrm_output(sk, skb);
}

static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
Expand Down Expand Up @@ -121,7 +91,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
__xfrm6_output_finish);

skip_frag:
return __xfrm6_output_state_finish(x, sk, skb);
return xfrm_output(sk, skb);
}

int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
Expand Down
1 change: 0 additions & 1 deletion net/ipv6/xfrm6_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
.family = AF_INET6,
.proto = IPPROTO_IPV6,
.output = xfrm6_output,
.output_finish = xfrm6_output_finish,
.transport_finish = xfrm6_transport_finish,
.local_error = xfrm6_local_error,
};
Expand Down
16 changes: 16 additions & 0 deletions net/xfrm/xfrm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,22 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
struct xfrm_state *x = skb_dst(skb)->xfrm;
int err;

switch (x->outer_mode.family) {
case AF_INET:
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
#ifdef CONFIG_NETFILTER
IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
#endif
break;
case AF_INET6:
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));

#ifdef CONFIG_NETFILTER
IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
#endif
break;
}

secpath_reset(skb);

if (xfrm_dev_offload_ok(skb, x)) {
Expand Down

0 comments on commit 2ab6096

Please sign in to comment.