]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfrm: remove type and offload_type map from xfrm_state_afinfo
authorFlorian Westphal <fw@strlen.de>
Fri, 3 May 2019 15:46:19 +0000 (17:46 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Thu, 6 Jun 2019 06:34:50 +0000 (08:34 +0200)
Only a handful of xfrm_types exist, no need to have 512 pointers for them.

Reduces size of afinfo struct from 4k to 120 bytes on 64bit platforms.

Also, the unregister function doesn't need to return an error, no single
caller does anything useful with it.

Just place a WARN_ON() where needed instead.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
12 files changed:
include/net/xfrm.h
net/ipv4/ah4.c
net/ipv4/esp4.c
net/ipv4/esp4_offload.c
net/ipv4/ipcomp.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/esp6_offload.c
net/ipv6/ipcomp6.c
net/ipv6/mip6.c
net/xfrm/xfrm_state.c

index 812994ad49ac1539be496961d63e444474ef6c85..56b31676e330d4f7ac48d3d24bdf7e2409fe369a 100644 (file)
@@ -348,8 +348,16 @@ int __xfrm_state_delete(struct xfrm_state *x);
 struct xfrm_state_afinfo {
        u8                              family;
        u8                              proto;
-       const struct xfrm_type          *type_map[IPPROTO_MAX];
-       const struct xfrm_type_offload  *type_offload_map[IPPROTO_MAX];
+
+       const struct xfrm_type_offload *type_offload_esp;
+
+       const struct xfrm_type          *type_esp;
+       const struct xfrm_type          *type_ipip;
+       const struct xfrm_type          *type_ipip6;
+       const struct xfrm_type          *type_comp;
+       const struct xfrm_type          *type_ah;
+       const struct xfrm_type          *type_routing;
+       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);
@@ -401,7 +409,7 @@ struct xfrm_type {
 };
 
 int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
-int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
+void xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
 
 struct xfrm_type_offload {
        char            *description;
@@ -413,7 +421,7 @@ 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);
+void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
 
 static inline int xfrm_af2proto(unsigned int family)
 {
index 9c3afd550612a8322649357749ca9cd474a31ac2..974179b3b31449e4687045f347973888bbadfbcf 100644 (file)
@@ -590,8 +590,7 @@ static void __exit ah4_fini(void)
 {
        if (xfrm4_protocol_deregister(&ah4_protocol, IPPROTO_AH) < 0)
                pr_info("%s: can't remove protocol\n", __func__);
-       if (xfrm_unregister_type(&ah_type, AF_INET) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
+       xfrm_unregister_type(&ah_type, AF_INET);
 }
 
 module_init(ah4_init);
index b9ae955760844b7bbac862ff0d2cdaccbb48fc2b..c06562aded118cba652adb0f425ff99a1f01691d 100644 (file)
@@ -1066,8 +1066,7 @@ static void __exit esp4_fini(void)
 {
        if (xfrm4_protocol_deregister(&esp4_protocol, IPPROTO_ESP) < 0)
                pr_info("%s: can't remove protocol\n", __func__);
-       if (xfrm_unregister_type(&esp_type, AF_INET) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
+       xfrm_unregister_type(&esp_type, AF_INET);
 }
 
 module_init(esp4_init);
index 8edcfa66d1e5ed0f224ba271d6898f1837fc5c76..6e5288aef71e4bf03462d4255403f6f53edc3df8 100644 (file)
@@ -315,9 +315,7 @@ static int __init esp4_offload_init(void)
 
 static void __exit esp4_offload_exit(void)
 {
-       if (xfrm_unregister_type_offload(&esp_type_offload, AF_INET) < 0)
-               pr_info("%s: can't remove xfrm type offload\n", __func__);
-
+       xfrm_unregister_type_offload(&esp_type_offload, AF_INET);
        inet_del_offload(&esp4_offload, IPPROTO_ESP);
 }
 
index 9119d012ba46e2f4c6feceb3256a0902f55792cb..ee03f0a55152bdc66366315f0787bf9390e90c11 100644 (file)
@@ -190,8 +190,7 @@ static void __exit ipcomp4_fini(void)
 {
        if (xfrm4_protocol_deregister(&ipcomp4_protocol, IPPROTO_COMP) < 0)
                pr_info("%s: can't remove protocol\n", __func__);
-       if (xfrm_unregister_type(&ipcomp_type, AF_INET) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
+       xfrm_unregister_type(&ipcomp_type, AF_INET);
 }
 
 module_init(ipcomp4_init);
index 5d00e54cd3190e829e73479ad0126eca8979a24e..dc19aff7c2e0055711597d7dd423fd107cd21ef7 100644 (file)
@@ -108,8 +108,7 @@ static void __exit ipip_fini(void)
        if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
                pr_info("%s: can't remove xfrm handler for AF_INET\n",
                        __func__);
-       if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
+       xfrm_unregister_type(&ipip_type, AF_INET);
 }
 
 module_init(ipip_init);
index 68b9e92e469eda8d0c641f5bf2066b333bf53c1a..25e1172fd1c3c260c44f52caded07198729ff533 100644 (file)
@@ -793,9 +793,7 @@ static void __exit ah6_fini(void)
        if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0)
                pr_info("%s: can't remove protocol\n", __func__);
 
-       if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
-
+       xfrm_unregister_type(&ah6_type, AF_INET6);
 }
 
 module_init(ah6_init);
index ae6a739c5f52873d0535998323a04d0f7b3c26c8..b6c6b3e08836ebbdae111c2113d283a79750eba4 100644 (file)
@@ -951,8 +951,7 @@ static void __exit esp6_fini(void)
 {
        if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0)
                pr_info("%s: can't remove protocol\n", __func__);
-       if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
+       xfrm_unregister_type(&esp6_type, AF_INET6);
 }
 
 module_init(esp6_init);
index d453cf417b03df29a919ca40360d2a9269c159ca..f2c8f7103332f0853b5acea88318b475a80bd437 100644 (file)
@@ -339,9 +339,7 @@ static int __init esp6_offload_init(void)
 
 static void __exit esp6_offload_exit(void)
 {
-       if (xfrm_unregister_type_offload(&esp6_type_offload, AF_INET6) < 0)
-               pr_info("%s: can't remove xfrm type offload\n", __func__);
-
+       xfrm_unregister_type_offload(&esp6_type_offload, AF_INET6);
        inet6_del_offload(&esp6_offload, IPPROTO_ESP);
 }
 
index 51fd33294c7c1891cf9195cd850ac9854e8b1213..3752bd3e92ce9b2f636e0cc8f5a6e2f541683054 100644 (file)
@@ -206,8 +206,7 @@ static void __exit ipcomp6_fini(void)
 {
        if (xfrm6_protocol_deregister(&ipcomp6_protocol, IPPROTO_COMP) < 0)
                pr_info("%s: can't remove protocol\n", __func__);
-       if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0)
-               pr_info("%s: can't remove xfrm type\n", __func__);
+       xfrm_unregister_type(&ipcomp6_type, AF_INET6);
 }
 
 module_init(ipcomp6_init);
index 91801432878c3ffabe583f070fbf957ba4980eee..878fcec149494976a515a901c4d7acad0386f59c 100644 (file)
@@ -499,10 +499,8 @@ static void __exit mip6_fini(void)
 {
        if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
                pr_info("%s: can't remove rawv6 mh filter\n", __func__);
-       if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
-               pr_info("%s: can't remove xfrm type(rthdr)\n", __func__);
-       if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
-               pr_info("%s: can't remove xfrm type(destopt)\n", __func__);
+       xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
+       xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
 }
 
 module_init(mip6_init);
index 3f0950db060a7bfeb4572bb08ddcc2c84047bb93..fd51737f9f17f015c13a2a74d343129eb4a83b5e 100644 (file)
@@ -177,63 +177,132 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
 static bool km_is_alive(const struct km_event *c);
 void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
 
-static DEFINE_SPINLOCK(xfrm_type_lock);
 int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
 {
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
-       const struct xfrm_type **typemap;
        int err = 0;
 
-       if (unlikely(afinfo == NULL))
+       if (!afinfo)
                return -EAFNOSUPPORT;
-       typemap = afinfo->type_map;
-       spin_lock_bh(&xfrm_type_lock);
 
-       if (likely(typemap[type->proto] == NULL))
-               typemap[type->proto] = type;
-       else
-               err = -EEXIST;
-       spin_unlock_bh(&xfrm_type_lock);
+#define X(afi, T, name) do {                   \
+               WARN_ON((afi)->type_ ## name);  \
+               (afi)->type_ ## name = (T);     \
+       } while (0)
+
+       switch (type->proto) {
+       case IPPROTO_COMP:
+               X(afinfo, type, comp);
+               break;
+       case IPPROTO_AH:
+               X(afinfo, type, ah);
+               break;
+       case IPPROTO_ESP:
+               X(afinfo, type, esp);
+               break;
+       case IPPROTO_IPIP:
+               X(afinfo, type, ipip);
+               break;
+       case IPPROTO_DSTOPTS:
+               X(afinfo, type, dstopts);
+               break;
+       case IPPROTO_ROUTING:
+               X(afinfo, type, routing);
+               break;
+       case IPPROTO_IPV6:
+               X(afinfo, type, ipip6);
+               break;
+       default:
+               WARN_ON(1);
+               err = -EPROTONOSUPPORT;
+               break;
+       }
+#undef X
        rcu_read_unlock();
        return err;
 }
 EXPORT_SYMBOL(xfrm_register_type);
 
-int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
+void xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
 {
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
-       const struct xfrm_type **typemap;
-       int err = 0;
 
        if (unlikely(afinfo == NULL))
-               return -EAFNOSUPPORT;
-       typemap = afinfo->type_map;
-       spin_lock_bh(&xfrm_type_lock);
+               return;
 
-       if (unlikely(typemap[type->proto] != type))
-               err = -ENOENT;
-       else
-               typemap[type->proto] = NULL;
-       spin_unlock_bh(&xfrm_type_lock);
+#define X(afi, T, name) do {                           \
+               WARN_ON((afi)->type_ ## name != (T));   \
+               (afi)->type_ ## name = NULL;            \
+       } while (0)
+
+       switch (type->proto) {
+       case IPPROTO_COMP:
+               X(afinfo, type, comp);
+               break;
+       case IPPROTO_AH:
+               X(afinfo, type, ah);
+               break;
+       case IPPROTO_ESP:
+               X(afinfo, type, esp);
+               break;
+       case IPPROTO_IPIP:
+               X(afinfo, type, ipip);
+               break;
+       case IPPROTO_DSTOPTS:
+               X(afinfo, type, dstopts);
+               break;
+       case IPPROTO_ROUTING:
+               X(afinfo, type, routing);
+               break;
+       case IPPROTO_IPV6:
+               X(afinfo, type, ipip6);
+               break;
+       default:
+               WARN_ON(1);
+               break;
+       }
+#undef X
        rcu_read_unlock();
-       return err;
 }
 EXPORT_SYMBOL(xfrm_unregister_type);
 
 static const struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
 {
+       const struct xfrm_type *type = NULL;
        struct xfrm_state_afinfo *afinfo;
-       const struct xfrm_type **typemap;
-       const struct xfrm_type *type;
        int modload_attempted = 0;
 
 retry:
        afinfo = xfrm_state_get_afinfo(family);
        if (unlikely(afinfo == NULL))
                return NULL;
-       typemap = afinfo->type_map;
 
-       type = READ_ONCE(typemap[proto]);
+       switch (proto) {
+       case IPPROTO_COMP:
+               type = afinfo->type_comp;
+               break;
+       case IPPROTO_AH:
+               type = afinfo->type_ah;
+               break;
+       case IPPROTO_ESP:
+               type = afinfo->type_esp;
+               break;
+       case IPPROTO_IPIP:
+               type = afinfo->type_ipip;
+               break;
+       case IPPROTO_DSTOPTS:
+               type = afinfo->type_dstopts;
+               break;
+       case IPPROTO_ROUTING:
+               type = afinfo->type_routing;
+               break;
+       case IPPROTO_IPV6:
+               type = afinfo->type_ipip6;
+               break;
+       default:
+               break;
+       }
+
        if (unlikely(type && !try_module_get(type->owner)))
                type = NULL;
 
@@ -253,65 +322,71 @@ static void xfrm_put_type(const struct xfrm_type *type)
        module_put(type->owner);
 }
 
-static DEFINE_SPINLOCK(xfrm_type_offload_lock);
 int xfrm_register_type_offload(const struct xfrm_type_offload *type,
                               unsigned short family)
 {
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
-       const struct xfrm_type_offload **typemap;
        int err = 0;
 
        if (unlikely(afinfo == NULL))
                return -EAFNOSUPPORT;
-       typemap = afinfo->type_offload_map;
-       spin_lock_bh(&xfrm_type_offload_lock);
 
-       if (likely(typemap[type->proto] == NULL))
-               typemap[type->proto] = type;
-       else
-               err = -EEXIST;
-       spin_unlock_bh(&xfrm_type_offload_lock);
+       switch (type->proto) {
+       case IPPROTO_ESP:
+               WARN_ON(afinfo->type_offload_esp);
+               afinfo->type_offload_esp = type;
+               break;
+       default:
+               WARN_ON(1);
+               err = -EPROTONOSUPPORT;
+               break;
+       }
+
        rcu_read_unlock();
        return err;
 }
 EXPORT_SYMBOL(xfrm_register_type_offload);
 
-int xfrm_unregister_type_offload(const struct xfrm_type_offload *type,
-                                unsigned short family)
+void xfrm_unregister_type_offload(const struct xfrm_type_offload *type,
+                                 unsigned short family)
 {
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
-       const struct xfrm_type_offload **typemap;
-       int err = 0;
 
        if (unlikely(afinfo == NULL))
-               return -EAFNOSUPPORT;
-       typemap = afinfo->type_offload_map;
-       spin_lock_bh(&xfrm_type_offload_lock);
+               return;
 
-       if (unlikely(typemap[type->proto] != type))
-               err = -ENOENT;
-       else
-               typemap[type->proto] = NULL;
-       spin_unlock_bh(&xfrm_type_offload_lock);
+       switch (type->proto) {
+       case IPPROTO_ESP:
+               WARN_ON(afinfo->type_offload_esp != type);
+               afinfo->type_offload_esp = NULL;
+               break;
+       default:
+               WARN_ON(1);
+               break;
+       }
        rcu_read_unlock();
-       return err;
 }
 EXPORT_SYMBOL(xfrm_unregister_type_offload);
 
 static const struct xfrm_type_offload *
 xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
 {
+       const struct xfrm_type_offload *type = NULL;
        struct xfrm_state_afinfo *afinfo;
-       const struct xfrm_type_offload **typemap;
-       const struct xfrm_type_offload *type;
 
 retry:
        afinfo = xfrm_state_get_afinfo(family);
        if (unlikely(afinfo == NULL))
                return NULL;
-       typemap = afinfo->type_offload_map;
 
-       type = typemap[proto];
+       switch (proto) {
+       case IPPROTO_ESP:
+               type = afinfo->type_offload_esp;
+               break;
+       default:
+               break;
+       }
+
        if ((type && !try_module_get(type->owner)))
                type = NULL;