summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-05-03 11:46:17 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2019-06-06 02:34:50 -0400
commit3aaf3915a31aac83523d2de0191a480d3ad1e747 (patch)
treeecae3204bda9b89b3d6a38d3b05232af71114bc3
parente46817472a1d7da32e8f265f9469a4e2fa39c60f (diff)
xfrm: remove state and template sort indirections from xfrm_state_afinfo
No module dependency, placing this in xfrm_state.c avoids need for an indirection. This also removes the state spinlock -- I don't see why we would need to hold it during sorting. This in turn allows to remove the 'net' argument passed to xfrm_tmpl_sort. Last, remove the EXPORT_SYMBOL, there are no modular callers. For the CONFIG_IPV6=m case, vmlinux size increase is about 300 byte. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
-rw-r--r--include/net/xfrm.h18
-rw-r--r--net/ipv6/xfrm6_state.c98
-rw-r--r--net/xfrm/xfrm_policy.c2
-rw-r--r--net/xfrm/xfrm_state.c132
4 files changed, 113 insertions, 137 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 61214f5c3205..4325cb708ed4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -353,8 +353,6 @@ struct xfrm_state_afinfo {
353 const struct xfrm_type *type_map[IPPROTO_MAX]; 353 const struct xfrm_type *type_map[IPPROTO_MAX];
354 const struct xfrm_type_offload *type_offload_map[IPPROTO_MAX]; 354 const struct xfrm_type_offload *type_offload_map[IPPROTO_MAX];
355 355
356 int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
357 int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
358 int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); 356 int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
359 int (*output_finish)(struct sock *sk, struct sk_buff *skb); 357 int (*output_finish)(struct sock *sk, struct sk_buff *skb);
360 int (*extract_input)(struct xfrm_state *x, 358 int (*extract_input)(struct xfrm_state *x,
@@ -1501,21 +1499,19 @@ struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1501 u8 proto, 1499 u8 proto,
1502 unsigned short family); 1500 unsigned short family);
1503#ifdef CONFIG_XFRM_SUB_POLICY 1501#ifdef CONFIG_XFRM_SUB_POLICY
1504int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, 1502void xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
1505 unsigned short family, struct net *net);
1506int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
1507 unsigned short family); 1503 unsigned short family);
1504void xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
1505 unsigned short family);
1508#else 1506#else
1509static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, 1507static inline void xfrm_tmpl_sort(struct xfrm_tmpl **d, struct xfrm_tmpl **s,
1510 int n, unsigned short family, struct net *net) 1508 int n, unsigned short family)
1511{ 1509{
1512 return -ENOSYS;
1513} 1510}
1514 1511
1515static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, 1512static inline void xfrm_state_sort(struct xfrm_state **d, struct xfrm_state **s,
1516 int n, unsigned short family) 1513 int n, unsigned short family)
1517{ 1514{
1518 return -ENOSYS;
1519} 1515}
1520#endif 1516#endif
1521 1517
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index aa5d2c52cc31..1782ebb22dd3 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -21,102 +21,6 @@
21#include <net/ipv6.h> 21#include <net/ipv6.h>
22#include <net/addrconf.h> 22#include <net/addrconf.h>
23 23
24/* distribution counting sort function for xfrm_state and xfrm_tmpl */
25static int
26__xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass)
27{
28 int count[XFRM_MAX_DEPTH] = { };
29 int class[XFRM_MAX_DEPTH];
30 int i;
31
32 for (i = 0; i < n; i++) {
33 int c;
34 class[i] = c = cmp(src[i]);
35 count[c]++;
36 }
37
38 for (i = 2; i < maxclass; i++)
39 count[i] += count[i - 1];
40
41 for (i = 0; i < n; i++) {
42 dst[count[class[i] - 1]++] = src[i];
43 src[i] = NULL;
44 }
45
46 return 0;
47}
48
49/*
50 * Rule for xfrm_state:
51 *
52 * rule 1: select IPsec transport except AH
53 * rule 2: select MIPv6 RO or inbound trigger
54 * rule 3: select IPsec transport AH
55 * rule 4: select IPsec tunnel
56 * rule 5: others
57 */
58static int __xfrm6_state_sort_cmp(void *p)
59{
60 struct xfrm_state *v = p;
61
62 switch (v->props.mode) {
63 case XFRM_MODE_TRANSPORT:
64 if (v->id.proto != IPPROTO_AH)
65 return 1;
66 else
67 return 3;
68#if IS_ENABLED(CONFIG_IPV6_MIP6)
69 case XFRM_MODE_ROUTEOPTIMIZATION:
70 case XFRM_MODE_IN_TRIGGER:
71 return 2;
72#endif
73 case XFRM_MODE_TUNNEL:
74 case XFRM_MODE_BEET:
75 return 4;
76 }
77 return 5;
78}
79
80static int
81__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
82{
83 return __xfrm6_sort((void **)dst, (void **)src, n,
84 __xfrm6_state_sort_cmp, 6);
85}
86
87/*
88 * Rule for xfrm_tmpl:
89 *
90 * rule 1: select IPsec transport
91 * rule 2: select MIPv6 RO or inbound trigger
92 * rule 3: select IPsec tunnel
93 * rule 4: others
94 */
95static int __xfrm6_tmpl_sort_cmp(void *p)
96{
97 struct xfrm_tmpl *v = p;
98 switch (v->mode) {
99 case XFRM_MODE_TRANSPORT:
100 return 1;
101#if IS_ENABLED(CONFIG_IPV6_MIP6)
102 case XFRM_MODE_ROUTEOPTIMIZATION:
103 case XFRM_MODE_IN_TRIGGER:
104 return 2;
105#endif
106 case XFRM_MODE_TUNNEL:
107 case XFRM_MODE_BEET:
108 return 3;
109 }
110 return 4;
111}
112
113static int
114__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
115{
116 return __xfrm6_sort((void **)dst, (void **)src, n,
117 __xfrm6_tmpl_sort_cmp, 5);
118}
119
120int xfrm6_extract_header(struct sk_buff *skb) 24int xfrm6_extract_header(struct sk_buff *skb)
121{ 25{
122 struct ipv6hdr *iph = ipv6_hdr(skb); 26 struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -138,8 +42,6 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
138 .proto = IPPROTO_IPV6, 42 .proto = IPPROTO_IPV6,
139 .eth_proto = htons(ETH_P_IPV6), 43 .eth_proto = htons(ETH_P_IPV6),
140 .owner = THIS_MODULE, 44 .owner = THIS_MODULE,
141 .tmpl_sort = __xfrm6_tmpl_sort,
142 .state_sort = __xfrm6_state_sort,
143 .output = xfrm6_output, 45 .output = xfrm6_output,
144 .output_finish = xfrm6_output_finish, 46 .output_finish = xfrm6_output_finish,
145 .extract_input = xfrm6_extract_input, 47 .extract_input = xfrm6_extract_input,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b1694d5d15d3..1070dfece76b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3628,7 +3628,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
3628 } 3628 }
3629 xfrm_nr = ti; 3629 xfrm_nr = ti;
3630 if (npols > 1) { 3630 if (npols > 1) {
3631 xfrm_tmpl_sort(stp, tpp, xfrm_nr, family, net); 3631 xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
3632 tpp = stp; 3632 tpp = stp;
3633 } 3633 }
3634 3634
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 5c13a8021d4c..3f0950db060a 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1688,51 +1688,129 @@ xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid,
1688EXPORT_SYMBOL(xfrm_find_acq); 1688EXPORT_SYMBOL(xfrm_find_acq);
1689 1689
1690#ifdef CONFIG_XFRM_SUB_POLICY 1690#ifdef CONFIG_XFRM_SUB_POLICY
1691int 1691#if IS_ENABLED(CONFIG_IPV6)
1692/* distribution counting sort function for xfrm_state and xfrm_tmpl */
1693static void
1694__xfrm6_sort(void **dst, void **src, int n,
1695 int (*cmp)(const void *p), int maxclass)
1696{
1697 int count[XFRM_MAX_DEPTH] = { };
1698 int class[XFRM_MAX_DEPTH];
1699 int i;
1700
1701 for (i = 0; i < n; i++) {
1702 int c = cmp(src[i]);
1703
1704 class[i] = c;
1705 count[c]++;
1706 }
1707
1708 for (i = 2; i < maxclass; i++)
1709 count[i] += count[i - 1];
1710
1711 for (i = 0; i < n; i++) {
1712 dst[count[class[i] - 1]++] = src[i];
1713 src[i] = NULL;
1714 }
1715}
1716
1717/* Rule for xfrm_state:
1718 *
1719 * rule 1: select IPsec transport except AH
1720 * rule 2: select MIPv6 RO or inbound trigger
1721 * rule 3: select IPsec transport AH
1722 * rule 4: select IPsec tunnel
1723 * rule 5: others
1724 */
1725static int __xfrm6_state_sort_cmp(const void *p)
1726{
1727 const struct xfrm_state *v = p;
1728
1729 switch (v->props.mode) {
1730 case XFRM_MODE_TRANSPORT:
1731 if (v->id.proto != IPPROTO_AH)
1732 return 1;
1733 else
1734 return 3;
1735#if IS_ENABLED(CONFIG_IPV6_MIP6)
1736 case XFRM_MODE_ROUTEOPTIMIZATION:
1737 case XFRM_MODE_IN_TRIGGER:
1738 return 2;
1739#endif
1740 case XFRM_MODE_TUNNEL:
1741 case XFRM_MODE_BEET:
1742 return 4;
1743 }
1744 return 5;
1745}
1746
1747/* Rule for xfrm_tmpl:
1748 *
1749 * rule 1: select IPsec transport
1750 * rule 2: select MIPv6 RO or inbound trigger
1751 * rule 3: select IPsec tunnel
1752 * rule 4: others
1753 */
1754static int __xfrm6_tmpl_sort_cmp(const void *p)
1755{
1756 const struct xfrm_tmpl *v = p;
1757
1758 switch (v->mode) {
1759 case XFRM_MODE_TRANSPORT:
1760 return 1;
1761#if IS_ENABLED(CONFIG_IPV6_MIP6)
1762 case XFRM_MODE_ROUTEOPTIMIZATION:
1763 case XFRM_MODE_IN_TRIGGER:
1764 return 2;
1765#endif
1766 case XFRM_MODE_TUNNEL:
1767 case XFRM_MODE_BEET:
1768 return 3;
1769 }
1770 return 4;
1771}
1772#else
1773static inline int __xfrm6_state_sort_cmp(const void *p) { return 5; }
1774static inline int __xfrm6_tmpl_sort_cmp(const void *p) { return 4; }
1775
1776static inline void
1777__xfrm6_sort(void **dst, void **src, int n,
1778 int (*cmp)(const void *p), int maxclass)
1779{
1780 int i;
1781
1782 for (i = 0; i < n; i++)
1783 dst[i] = src[i];
1784}
1785#endif /* CONFIG_IPV6 */
1786
1787void
1692xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, 1788xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
1693 unsigned short family, struct net *net) 1789 unsigned short family)
1694{ 1790{
1695 int i; 1791 int i;
1696 int err = 0;
1697 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
1698 if (!afinfo)
1699 return -EAFNOSUPPORT;
1700 1792
1701 spin_lock_bh(&net->xfrm.xfrm_state_lock); /*FIXME*/ 1793 if (family == AF_INET6)
1702 if (afinfo->tmpl_sort) 1794 __xfrm6_sort((void **)dst, (void **)src, n,
1703 err = afinfo->tmpl_sort(dst, src, n); 1795 __xfrm6_tmpl_sort_cmp, 5);
1704 else 1796 else
1705 for (i = 0; i < n; i++) 1797 for (i = 0; i < n; i++)
1706 dst[i] = src[i]; 1798 dst[i] = src[i];
1707 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1708 rcu_read_unlock();
1709 return err;
1710} 1799}
1711EXPORT_SYMBOL(xfrm_tmpl_sort);
1712 1800
1713int 1801void
1714xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, 1802xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
1715 unsigned short family) 1803 unsigned short family)
1716{ 1804{
1717 int i; 1805 int i;
1718 int err = 0;
1719 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
1720 struct net *net = xs_net(*src);
1721 1806
1722 if (!afinfo) 1807 if (family == AF_INET6)
1723 return -EAFNOSUPPORT; 1808 __xfrm6_sort((void **)dst, (void **)src, n,
1724 1809 __xfrm6_state_sort_cmp, 6);
1725 spin_lock_bh(&net->xfrm.xfrm_state_lock);
1726 if (afinfo->state_sort)
1727 err = afinfo->state_sort(dst, src, n);
1728 else 1810 else
1729 for (i = 0; i < n; i++) 1811 for (i = 0; i < n; i++)
1730 dst[i] = src[i]; 1812 dst[i] = src[i];
1731 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1732 rcu_read_unlock();
1733 return err;
1734} 1813}
1735EXPORT_SYMBOL(xfrm_state_sort);
1736#endif 1814#endif
1737 1815
1738/* Silly enough, but I'm lazy to build resolution list */ 1816/* Silly enough, but I'm lazy to build resolution list */