xfrm: store xfrm_mode directly, not its address
authorFlorian Westphal <fw@strlen.de>
Fri, 29 Mar 2019 20:16:32 +0000 (21:16 +0100)
committerSteffen Klassert <steffen.klassert@secunet.com>
Mon, 8 Apr 2019 07:15:28 +0000 (09:15 +0200)
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>
13 files changed:
include/net/xfrm.h
net/ipv4/esp4_offload.c
net/ipv4/ip_vti.c
net/ipv4/xfrm4_output.c
net/ipv6/esp6_offload.c
net/ipv6/ip6_vti.c
net/ipv6/xfrm6_output.c
net/xfrm/xfrm_device.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_interface.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c

index 4ca79cdc34601e93b7805d7640f9fa283c594b7c..77eb578a03844174ef7b5a261abdec54939482be 100644 (file)
@@ -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;
index 74d59e0177a729a2a9cda07ba4775bdaf4806288..b61a8ff558f97c92a760a57da8f4508f72d3a90c 100644 (file)
@@ -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:
index 91926c9a3bc9a6fb808a61b2dfa26041f28c74d1..cc5d9c0a8a1007434b5d4e84f3a8d9713fef9c03 100644 (file)
@@ -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);
index 7c3df14daef3488ce52cb8458d6a7074170e98c7..9bb8905088c75619ebde66739dd43896a90528fd 100644 (file)
@@ -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
index c793a2ace77d936e5dccb4dbe4f94910940516f0..bff83279d76fd3b6f7675f12bcaf3a427e52c249 100644 (file)
@@ -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:
index 71ec5e60cf8f98305eca05853c0d758dc8088af1..218a0dedc8f48e72f3b9df03033875d3c873c6e2 100644 (file)
@@ -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);
index 455fbf3b91cf1baa5fd114ea3bcc5b4100d10435..8ad5e54eb8ca201061d48aaa75938231658b3cc4 100644 (file)
@@ -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
index a20f376fe71f69cdddba9aa2c847dcfebedb148f..b24cd86a02c3693ec6eb27f4fb03b5830bd420ce 100644 (file)
@@ -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;
index b5a31c8e20884d26e2f0963d6633864c883fd35e..314973aaa4143ef01832bbe39a15f672375df01a 100644 (file)
@@ -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 @@ resume:
 
                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 @@ resume:
                        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 @@ resume:
                 * 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 @@ resume:
 
                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();
index 4fc49dbf3edfbd563dbfa8ab652a472c12867b2b..b9f118530db6a3d17e914fd7979b26b0004ac9e2 100644 (file)
@@ -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);
index 3cb2a328a8abfa3edbbb39f7a1c85548a472aa2f..a55510f9ff35a711af26e416c6168370fac04ac6 100644 (file)
@@ -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 @@ resume:
                }
                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;
index 1a5fd2296556fd539c127c03cfc8260dacd4d0f6..16e70fc547b13670a6a1767169bc063ae1921711 100644 (file)
@@ -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);
index ace26f6dc79071bcdb254706f8264df5305f2578..d3d87c409f44c28b8d77f00971130fef05d8e4ef 100644 (file)
@@ -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)