diff options
author | Florian Westphal <fw@strlen.de> | 2019-05-03 11:46:17 -0400 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2019-06-06 02:34:50 -0400 |
commit | 3aaf3915a31aac83523d2de0191a480d3ad1e747 (patch) | |
tree | ecae3204bda9b89b3d6a38d3b05232af71114bc3 | |
parent | e46817472a1d7da32e8f265f9469a4e2fa39c60f (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.h | 18 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 98 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 132 |
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 |
1504 | int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, | 1502 | void xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, |
1505 | unsigned short family, struct net *net); | ||
1506 | int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, | ||
1507 | unsigned short family); | 1503 | unsigned short family); |
1504 | void xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, | ||
1505 | unsigned short family); | ||
1508 | #else | 1506 | #else |
1509 | static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, | 1507 | static 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 | ||
1515 | static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, | 1512 | static 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 */ | ||
25 | static 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 | */ | ||
58 | static 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 | |||
80 | static 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 | */ | ||
95 | static 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 | |||
113 | static 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 | |||
120 | int xfrm6_extract_header(struct sk_buff *skb) | 24 | int 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, | |||
1688 | EXPORT_SYMBOL(xfrm_find_acq); | 1688 | EXPORT_SYMBOL(xfrm_find_acq); |
1689 | 1689 | ||
1690 | #ifdef CONFIG_XFRM_SUB_POLICY | 1690 | #ifdef CONFIG_XFRM_SUB_POLICY |
1691 | int | 1691 | #if IS_ENABLED(CONFIG_IPV6) |
1692 | /* distribution counting sort function for xfrm_state and xfrm_tmpl */ | ||
1693 | static 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 | */ | ||
1725 | static 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 | */ | ||
1754 | static 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 | ||
1773 | static inline int __xfrm6_state_sort_cmp(const void *p) { return 5; } | ||
1774 | static inline int __xfrm6_tmpl_sort_cmp(const void *p) { return 4; } | ||
1775 | |||
1776 | static 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 | |||
1787 | void | ||
1692 | xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, | 1788 | xfrm_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 | } |
1711 | EXPORT_SYMBOL(xfrm_tmpl_sort); | ||
1712 | 1800 | ||
1713 | int | 1801 | void |
1714 | xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, | 1802 | xfrm_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 | } |
1735 | EXPORT_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 */ |