Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 733a5fac authored by Florian Westphal's avatar Florian Westphal Committed by Steffen Klassert
Browse files

xfrm: remove afinfo pointer from xfrm_mode



Adds an EXPORT_SYMBOL for afinfo_get_rcu, as it will now be called from
ipv6 in case of CONFIG_IPV6=m.

This change has virtually no effect on vmlinux size, but it reduces
afinfo size and allows followup patch to make xfrm modes const.

v2: mark if (afinfo) tests as likely (Sabrina)
    re-fetch afinfo according to inner_mode in xfrm_prepare_input().

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Reviewed-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 1de70830
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -423,7 +423,6 @@ int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned sh
int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);

struct xfrm_mode {
	struct xfrm_state_afinfo *afinfo;
	struct module *owner;
	u8 encap;
	u8 family;
+11 −1
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *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) {
@@ -80,7 +82,15 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
	}
#endif

	return x->outer_mode->afinfo->output_finish(sk, skb);
	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;
}

int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+19 −2
Original line number Diff line number Diff line
@@ -122,11 +122,28 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
	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 x->outer_mode->afinfo->output_finish(sk, skb);
	return __xfrm6_output_state_finish(x, sk, skb);
}

static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
@@ -168,7 +185,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
				    __xfrm6_output_finish);

skip_frag:
	return x->outer_mode->afinfo->output_finish(sk, skb);
	return __xfrm6_output_state_finish(x, sk, skb);
}

int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+28 −6
Original line number Diff line number Diff line
@@ -352,19 +352,35 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
{
	struct xfrm_mode *inner_mode = x->inner_mode;
	int err;
	const struct xfrm_state_afinfo *afinfo;
	int err = -EAFNOSUPPORT;

	err = x->outer_mode->afinfo->extract_input(x, skb);
	if (err)
	rcu_read_lock();
	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
	if (likely(afinfo))
		err = afinfo->extract_input(x, skb);

	if (err) {
		rcu_read_unlock();
		return err;
	}

	if (x->sel.family == AF_UNSPEC) {
		inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
		if (inner_mode == NULL)
		if (!inner_mode) {
			rcu_read_unlock();
			return -EAFNOSUPPORT;
		}
	}

	skb->protocol = inner_mode->afinfo->eth_proto;
	afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
	if (unlikely(!afinfo)) {
		rcu_read_unlock();
		return -EAFNOSUPPORT;
	}

	skb->protocol = afinfo->eth_proto;
	rcu_read_unlock();
	return xfrm_inner_mode_encap_remove(x, inner_mode, skb);
}

@@ -440,6 +456,7 @@ static int xfrm_inner_mode_input(struct xfrm_state *x,

int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
{
	const struct xfrm_state_afinfo *afinfo;
	struct net *net = dev_net(skb->dev);
	int err;
	__be32 seq;
@@ -705,7 +722,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
		if (xo)
			xfrm_gro = xo->flags & XFRM_GRO;

		err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);
		err = -EAFNOSUPPORT;
		rcu_read_lock();
		afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode->family);
		if (likely(afinfo))
			err = afinfo->transport_finish(skb, xfrm_gro || async);
		rcu_read_unlock();
		if (xfrm_gro) {
			sp = skb_sec_path(skb);
			if (sp)
+11 −1
Original line number Diff line number Diff line
@@ -623,7 +623,10 @@ EXPORT_SYMBOL_GPL(xfrm_output);

static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
{
	const struct xfrm_state_afinfo *afinfo;
	struct xfrm_mode *inner_mode;
	int err = -EAFNOSUPPORT;

	if (x->sel.family == AF_UNSPEC)
		inner_mode = xfrm_ip2inner_mode(x,
				xfrm_af2proto(skb_dst(skb)->ops->family));
@@ -632,7 +635,14 @@ static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)

	if (inner_mode == NULL)
		return -EAFNOSUPPORT;
	return inner_mode->afinfo->extract_output(x, skb);

	rcu_read_lock();
	afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
	if (likely(afinfo))
		err = afinfo->extract_output(x, skb);
	rcu_read_unlock();

	return err;
}

void xfrm_local_error(struct sk_buff *skb, int mtu)
Loading