mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 10:43:43 +00:00
xfrm: store xfrm_mode directly, not its address
This structure is now only 4 bytes, so its more efficient to cache a copy rather than its address. No significant size difference in allmodconfig vmlinux. With non-modular kernel that has all XFRM options enabled, this series reduces vmlinux image size by ~11kb. All xfrm_mode indirections are gone and all modes are built-in. before (ipsec-next master): text data bss dec filename 21071494 7233140 11104324 39408958 vmlinux.master after this series: 21066448 7226772 11104324 39397544 vmlinux.patched With allmodconfig kernel, the size increase is only 362 bytes, even all the xfrm config options removed in this series are modular. before: text data bss dec filename 15731286 6936912 4046908 26715106 vmlinux.master after this series: 15731492 6937068 4046908 26715468 vmlinux Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
parent
4c145dce26
commit
c9500d7b7d
@ -132,6 +132,17 @@ struct xfrm_state_offload {
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
struct xfrm_mode {
|
||||
u8 encap;
|
||||
u8 family;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/* Flags for xfrm_mode. */
|
||||
enum {
|
||||
XFRM_MODE_FLAG_TUNNEL = 1,
|
||||
};
|
||||
|
||||
/* Full description of state of transformer. */
|
||||
struct xfrm_state {
|
||||
possible_net_t xs_net;
|
||||
@ -234,9 +245,9 @@ struct xfrm_state {
|
||||
/* Reference to data common to all the instances of this
|
||||
* transformer. */
|
||||
const struct xfrm_type *type;
|
||||
const struct xfrm_mode *inner_mode;
|
||||
const struct xfrm_mode *inner_mode_iaf;
|
||||
const struct xfrm_mode *outer_mode;
|
||||
struct xfrm_mode inner_mode;
|
||||
struct xfrm_mode inner_mode_iaf;
|
||||
struct xfrm_mode outer_mode;
|
||||
|
||||
const struct xfrm_type_offload *type_offload;
|
||||
|
||||
@ -421,17 +432,6 @@ struct xfrm_type_offload {
|
||||
int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
|
||||
int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
|
||||
|
||||
struct xfrm_mode {
|
||||
u8 encap;
|
||||
u8 family;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/* Flags for xfrm_mode. */
|
||||
enum {
|
||||
XFRM_MODE_FLAG_TUNNEL = 1,
|
||||
};
|
||||
|
||||
static inline int xfrm_af2proto(unsigned int family)
|
||||
{
|
||||
switch(family) {
|
||||
@ -448,9 +448,9 @@ static inline const struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, i
|
||||
{
|
||||
if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
|
||||
(ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
|
||||
return x->inner_mode;
|
||||
return &x->inner_mode;
|
||||
else
|
||||
return x->inner_mode_iaf;
|
||||
return &x->inner_mode_iaf;
|
||||
}
|
||||
|
||||
struct xfrm_tmpl {
|
||||
@ -1990,7 +1990,7 @@ static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
|
||||
tunnel = true;
|
||||
break;
|
||||
}
|
||||
if (tunnel && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL))
|
||||
if (tunnel && !(x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
@ -135,7 +135,7 @@ static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
|
||||
struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
switch (x->outer_mode->encap) {
|
||||
switch (x->outer_mode.encap) {
|
||||
case XFRM_MODE_TUNNEL:
|
||||
return xfrm4_tunnel_gso_segment(x, skb, features);
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
|
@ -126,7 +126,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
|
||||
|
||||
x = xfrm_input_state(skb);
|
||||
|
||||
inner_mode = x->inner_mode;
|
||||
inner_mode = &x->inner_mode;
|
||||
|
||||
if (x->sel.family == AF_UNSPEC) {
|
||||
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
|
||||
|
@ -83,7 +83,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);
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
|
||||
if (likely(afinfo))
|
||||
ret = afinfo->output_finish(sk, skb);
|
||||
else
|
||||
|
@ -162,7 +162,7 @@ static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
|
||||
struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
switch (x->outer_mode->encap) {
|
||||
switch (x->outer_mode.encap) {
|
||||
case XFRM_MODE_TUNNEL:
|
||||
return xfrm6_tunnel_gso_segment(x, skb, features);
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
|
@ -361,7 +361,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
|
||||
|
||||
x = xfrm_input_state(skb);
|
||||
|
||||
inner_mode = x->inner_mode;
|
||||
inner_mode = &x->inner_mode;
|
||||
|
||||
if (x->sel.family == AF_UNSPEC) {
|
||||
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
|
||||
|
@ -129,7 +129,7 @@ static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk,
|
||||
int ret = -EAFNOSUPPORT;
|
||||
|
||||
rcu_read_lock();
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
|
||||
if (likely(afinfo))
|
||||
ret = afinfo->output_finish(sk, skb);
|
||||
else
|
||||
|
@ -53,20 +53,20 @@ static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
|
||||
/* Adjust pointers into the packet when IPsec is done at layer2 */
|
||||
static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
switch (x->outer_mode->encap) {
|
||||
switch (x->outer_mode.encap) {
|
||||
case XFRM_MODE_TUNNEL:
|
||||
if (x->outer_mode->family == AF_INET)
|
||||
if (x->outer_mode.family == AF_INET)
|
||||
return __xfrm_mode_tunnel_prep(x, skb,
|
||||
sizeof(struct iphdr));
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
return __xfrm_mode_tunnel_prep(x, skb,
|
||||
sizeof(struct ipv6hdr));
|
||||
break;
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
if (x->outer_mode->family == AF_INET)
|
||||
if (x->outer_mode.family == AF_INET)
|
||||
return __xfrm_transport_prep(x, skb,
|
||||
sizeof(struct iphdr));
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
return __xfrm_transport_prep(x, skb,
|
||||
sizeof(struct ipv6hdr));
|
||||
break;
|
||||
|
@ -351,12 +351,12 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
|
||||
|
||||
static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode = x->inner_mode;
|
||||
const struct xfrm_mode *inner_mode = &x->inner_mode;
|
||||
const struct xfrm_state_afinfo *afinfo;
|
||||
int err = -EAFNOSUPPORT;
|
||||
|
||||
rcu_read_lock();
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode->family);
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
|
||||
if (likely(afinfo))
|
||||
err = afinfo->extract_input(x, skb);
|
||||
|
||||
@ -482,7 +482,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
family = x->outer_mode->family;
|
||||
family = x->outer_mode.family;
|
||||
|
||||
/* An encap_type of -1 indicates async resumption. */
|
||||
if (encap_type == -1) {
|
||||
@ -666,7 +666,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
|
||||
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
|
||||
|
||||
inner_mode = x->inner_mode;
|
||||
inner_mode = &x->inner_mode;
|
||||
|
||||
if (x->sel.family == AF_UNSPEC) {
|
||||
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
|
||||
@ -681,7 +681,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
|
||||
if (x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL) {
|
||||
decaps = 1;
|
||||
break;
|
||||
}
|
||||
@ -691,7 +691,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
* transport mode so the outer address is identical.
|
||||
*/
|
||||
daddr = &x->id.daddr;
|
||||
family = x->outer_mode->family;
|
||||
family = x->outer_mode.family;
|
||||
|
||||
err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
|
||||
if (err < 0) {
|
||||
@ -721,7 +721,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
|
||||
err = -EAFNOSUPPORT;
|
||||
rcu_read_lock();
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode->family);
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode.family);
|
||||
if (likely(afinfo))
|
||||
err = afinfo->transport_finish(skb, xfrm_gro || async);
|
||||
rcu_read_unlock();
|
||||
|
@ -273,7 +273,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
|
||||
xnet = !net_eq(xi->net, dev_net(skb->dev));
|
||||
|
||||
if (xnet) {
|
||||
inner_mode = x->inner_mode;
|
||||
inner_mode = &x->inner_mode;
|
||||
|
||||
if (x->sel.family == AF_UNSPEC) {
|
||||
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
|
||||
|
@ -334,7 +334,7 @@ static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
switch (x->outer_mode->encap) {
|
||||
switch (x->outer_mode.encap) {
|
||||
case XFRM_MODE_BEET:
|
||||
return xfrm4_beet_encap_add(x, skb);
|
||||
case XFRM_MODE_TUNNEL:
|
||||
@ -357,7 +357,7 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
skb->ignore_df = 1;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
switch (x->outer_mode->encap) {
|
||||
switch (x->outer_mode.encap) {
|
||||
case XFRM_MODE_BEET:
|
||||
return xfrm6_beet_encap_add(x, skb);
|
||||
case XFRM_MODE_TUNNEL:
|
||||
@ -373,22 +373,22 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
|
||||
static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
switch (x->outer_mode->encap) {
|
||||
switch (x->outer_mode.encap) {
|
||||
case XFRM_MODE_BEET:
|
||||
case XFRM_MODE_TUNNEL:
|
||||
if (x->outer_mode->family == AF_INET)
|
||||
if (x->outer_mode.family == AF_INET)
|
||||
return xfrm4_prepare_output(x, skb);
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
return xfrm6_prepare_output(x, skb);
|
||||
break;
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
if (x->outer_mode->family == AF_INET)
|
||||
if (x->outer_mode.family == AF_INET)
|
||||
return xfrm4_transport_output(x, skb);
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
return xfrm6_transport_output(x, skb);
|
||||
break;
|
||||
case XFRM_MODE_ROUTEOPTIMIZATION:
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
return xfrm6_ro_output(x, skb);
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
@ -489,7 +489,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
|
||||
}
|
||||
skb_dst_set(skb, dst);
|
||||
x = dst->xfrm;
|
||||
} while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
|
||||
} while (x && !(x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL));
|
||||
|
||||
return 0;
|
||||
|
||||
@ -626,7 +626,7 @@ static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
inner_mode = xfrm_ip2inner_mode(x,
|
||||
xfrm_af2proto(skb_dst(skb)->ops->family));
|
||||
else
|
||||
inner_mode = x->inner_mode;
|
||||
inner_mode = &x->inner_mode;
|
||||
|
||||
if (inner_mode == NULL)
|
||||
return -EAFNOSUPPORT;
|
||||
|
@ -2595,7 +2595,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
|
||||
goto put_states;
|
||||
}
|
||||
} else
|
||||
inner_mode = xfrm[i]->inner_mode;
|
||||
inner_mode = &xfrm[i]->inner_mode;
|
||||
|
||||
xdst->route = dst;
|
||||
dst_copy_metrics(dst1, dst);
|
||||
|
@ -551,8 +551,6 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
|
||||
x->lft.hard_packet_limit = XFRM_INF;
|
||||
x->replay_maxage = 0;
|
||||
x->replay_maxdiff = 0;
|
||||
x->inner_mode = NULL;
|
||||
x->inner_mode_iaf = NULL;
|
||||
spin_lock_init(&x->lock);
|
||||
}
|
||||
return x;
|
||||
@ -2204,8 +2202,9 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
||||
|
||||
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode;
|
||||
const struct xfrm_state_afinfo *afinfo;
|
||||
const struct xfrm_mode *inner_mode;
|
||||
const struct xfrm_mode *outer_mode;
|
||||
int family = x->props.family;
|
||||
int err;
|
||||
|
||||
@ -2234,7 +2233,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
||||
family != x->sel.family)
|
||||
goto error;
|
||||
|
||||
x->inner_mode = inner_mode;
|
||||
x->inner_mode = *inner_mode;
|
||||
} else {
|
||||
const struct xfrm_mode *inner_mode_iaf;
|
||||
int iafamily = AF_INET;
|
||||
@ -2246,7 +2245,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
||||
if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL))
|
||||
goto error;
|
||||
|
||||
x->inner_mode = inner_mode;
|
||||
x->inner_mode = *inner_mode;
|
||||
|
||||
if (x->props.family == AF_INET)
|
||||
iafamily = AF_INET6;
|
||||
@ -2254,7 +2253,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
||||
inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily);
|
||||
if (inner_mode_iaf) {
|
||||
if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)
|
||||
x->inner_mode_iaf = inner_mode_iaf;
|
||||
x->inner_mode_iaf = *inner_mode_iaf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2268,12 +2267,13 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
x->outer_mode = xfrm_get_mode(x->props.mode, family);
|
||||
if (x->outer_mode == NULL) {
|
||||
outer_mode = xfrm_get_mode(x->props.mode, family);
|
||||
if (!outer_mode) {
|
||||
err = -EPROTONOSUPPORT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
x->outer_mode = *outer_mode;
|
||||
if (init_replay) {
|
||||
err = xfrm_init_replay(x);
|
||||
if (err)
|
||||
|
Loading…
Reference in New Issue
Block a user