diff options
author | Eric Dumazet <edumazet@google.com> | 2013-10-03 18:42:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-09 00:01:25 -0400 |
commit | efe4208f47f907b86f528788da711e8ab9dea44d (patch) | |
tree | 8246b487be087877ba26d166f629d8c53d553ec1 /net/ipv6/udp.c | |
parent | 05dbc7b59481ca891bbcfe6799a562d48159fbf7 (diff) |
ipv6: make lookups simpler and faster
TCP listener refactoring, part 4 :
To speed up inet lookups, we moved IPv4 addresses from inet to struct
sock_common
Now is time to do the same for IPv6, because it permits us to have fast
lookups for all kind of sockets, including upcoming SYN_RECV.
Getting IPv6 addresses in TCP lookups currently requires two extra cache
lines, plus a dereference (and memory stall).
inet6_sk(sk) does the dereference of inet_sk(__sk)->pinet6
This patch is way bigger than its IPv4 counter part, because for IPv4,
we could add aliases (inet_daddr, inet_rcv_saddr), while on IPv6,
it's not doable easily.
inet6_sk(sk)->daddr becomes sk->sk_v6_daddr
inet6_sk(sk)->rcv_saddr becomes sk->sk_v6_rcv_saddr
And timewait socket also have tw->tw_v6_daddr & tw->tw_v6_rcv_saddr
at the same offset.
We get rid of INET6_TW_MATCH() as INET6_MATCH() is now the generic
macro.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r-- | net/ipv6/udp.c | 48 |
1 files changed, 22 insertions, 26 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 37532478e3ba..b496de19a341 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -55,11 +55,10 @@ | |||
55 | 55 | ||
56 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | 56 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) |
57 | { | 57 | { |
58 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; | ||
59 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 58 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
60 | int sk_ipv6only = ipv6_only_sock(sk); | 59 | int sk_ipv6only = ipv6_only_sock(sk); |
61 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | 60 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
62 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); | 61 | int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); |
63 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | 62 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; |
64 | 63 | ||
65 | /* if both are mapped, treat as IPv4 */ | 64 | /* if both are mapped, treat as IPv4 */ |
@@ -77,7 +76,7 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
77 | return 1; | 76 | return 1; |
78 | 77 | ||
79 | if (sk2_rcv_saddr6 && | 78 | if (sk2_rcv_saddr6 && |
80 | ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6)) | 79 | ipv6_addr_equal(&sk->sk_v6_rcv_saddr, sk2_rcv_saddr6)) |
81 | return 1; | 80 | return 1; |
82 | 81 | ||
83 | return 0; | 82 | return 0; |
@@ -105,7 +104,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
105 | unsigned int hash2_nulladdr = | 104 | unsigned int hash2_nulladdr = |
106 | udp6_portaddr_hash(sock_net(sk), &in6addr_any, snum); | 105 | udp6_portaddr_hash(sock_net(sk), &in6addr_any, snum); |
107 | unsigned int hash2_partial = | 106 | unsigned int hash2_partial = |
108 | udp6_portaddr_hash(sock_net(sk), &inet6_sk(sk)->rcv_saddr, 0); | 107 | udp6_portaddr_hash(sock_net(sk), &sk->sk_v6_rcv_saddr, 0); |
109 | 108 | ||
110 | /* precompute partial secondary hash */ | 109 | /* precompute partial secondary hash */ |
111 | udp_sk(sk)->udp_portaddr_hash = hash2_partial; | 110 | udp_sk(sk)->udp_portaddr_hash = hash2_partial; |
@@ -115,7 +114,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
115 | static void udp_v6_rehash(struct sock *sk) | 114 | static void udp_v6_rehash(struct sock *sk) |
116 | { | 115 | { |
117 | u16 new_hash = udp6_portaddr_hash(sock_net(sk), | 116 | u16 new_hash = udp6_portaddr_hash(sock_net(sk), |
118 | &inet6_sk(sk)->rcv_saddr, | 117 | &sk->sk_v6_rcv_saddr, |
119 | inet_sk(sk)->inet_num); | 118 | inet_sk(sk)->inet_num); |
120 | 119 | ||
121 | udp_lib_rehash(sk, new_hash); | 120 | udp_lib_rehash(sk, new_hash); |
@@ -131,7 +130,6 @@ static inline int compute_score(struct sock *sk, struct net *net, | |||
131 | 130 | ||
132 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && | 131 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && |
133 | sk->sk_family == PF_INET6) { | 132 | sk->sk_family == PF_INET6) { |
134 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
135 | struct inet_sock *inet = inet_sk(sk); | 133 | struct inet_sock *inet = inet_sk(sk); |
136 | 134 | ||
137 | score = 0; | 135 | score = 0; |
@@ -140,13 +138,13 @@ static inline int compute_score(struct sock *sk, struct net *net, | |||
140 | return -1; | 138 | return -1; |
141 | score++; | 139 | score++; |
142 | } | 140 | } |
143 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 141 | if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { |
144 | if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) | 142 | if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr)) |
145 | return -1; | 143 | return -1; |
146 | score++; | 144 | score++; |
147 | } | 145 | } |
148 | if (!ipv6_addr_any(&np->daddr)) { | 146 | if (!ipv6_addr_any(&sk->sk_v6_daddr)) { |
149 | if (!ipv6_addr_equal(&np->daddr, saddr)) | 147 | if (!ipv6_addr_equal(&sk->sk_v6_daddr, saddr)) |
150 | return -1; | 148 | return -1; |
151 | score++; | 149 | score++; |
152 | } | 150 | } |
@@ -169,10 +167,9 @@ static inline int compute_score2(struct sock *sk, struct net *net, | |||
169 | 167 | ||
170 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && | 168 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && |
171 | sk->sk_family == PF_INET6) { | 169 | sk->sk_family == PF_INET6) { |
172 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
173 | struct inet_sock *inet = inet_sk(sk); | 170 | struct inet_sock *inet = inet_sk(sk); |
174 | 171 | ||
175 | if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) | 172 | if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr)) |
176 | return -1; | 173 | return -1; |
177 | score = 0; | 174 | score = 0; |
178 | if (inet->inet_dport) { | 175 | if (inet->inet_dport) { |
@@ -180,8 +177,8 @@ static inline int compute_score2(struct sock *sk, struct net *net, | |||
180 | return -1; | 177 | return -1; |
181 | score++; | 178 | score++; |
182 | } | 179 | } |
183 | if (!ipv6_addr_any(&np->daddr)) { | 180 | if (!ipv6_addr_any(&sk->sk_v6_daddr)) { |
184 | if (!ipv6_addr_equal(&np->daddr, saddr)) | 181 | if (!ipv6_addr_equal(&sk->sk_v6_daddr, saddr)) |
185 | return -1; | 182 | return -1; |
186 | score++; | 183 | score++; |
187 | } | 184 | } |
@@ -549,7 +546,7 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
549 | { | 546 | { |
550 | int rc; | 547 | int rc; |
551 | 548 | ||
552 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) { | 549 | if (!ipv6_addr_any(&sk->sk_v6_daddr)) { |
553 | sock_rps_save_rxhash(sk, skb); | 550 | sock_rps_save_rxhash(sk, skb); |
554 | sk_mark_napi_id(sk, skb); | 551 | sk_mark_napi_id(sk, skb); |
555 | } | 552 | } |
@@ -690,20 +687,19 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | |||
690 | 687 | ||
691 | if (udp_sk(s)->udp_port_hash == num && | 688 | if (udp_sk(s)->udp_port_hash == num && |
692 | s->sk_family == PF_INET6) { | 689 | s->sk_family == PF_INET6) { |
693 | struct ipv6_pinfo *np = inet6_sk(s); | ||
694 | if (inet->inet_dport) { | 690 | if (inet->inet_dport) { |
695 | if (inet->inet_dport != rmt_port) | 691 | if (inet->inet_dport != rmt_port) |
696 | continue; | 692 | continue; |
697 | } | 693 | } |
698 | if (!ipv6_addr_any(&np->daddr) && | 694 | if (!ipv6_addr_any(&sk->sk_v6_daddr) && |
699 | !ipv6_addr_equal(&np->daddr, rmt_addr)) | 695 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) |
700 | continue; | 696 | continue; |
701 | 697 | ||
702 | if (s->sk_bound_dev_if && s->sk_bound_dev_if != dif) | 698 | if (s->sk_bound_dev_if && s->sk_bound_dev_if != dif) |
703 | continue; | 699 | continue; |
704 | 700 | ||
705 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 701 | if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { |
706 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 702 | if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) |
707 | continue; | 703 | continue; |
708 | } | 704 | } |
709 | if (!inet6_mc_check(s, loc_addr, rmt_addr)) | 705 | if (!inet6_mc_check(s, loc_addr, rmt_addr)) |
@@ -1063,7 +1059,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1063 | } else if (!up->pending) { | 1059 | } else if (!up->pending) { |
1064 | if (sk->sk_state != TCP_ESTABLISHED) | 1060 | if (sk->sk_state != TCP_ESTABLISHED) |
1065 | return -EDESTADDRREQ; | 1061 | return -EDESTADDRREQ; |
1066 | daddr = &np->daddr; | 1062 | daddr = &sk->sk_v6_daddr; |
1067 | } else | 1063 | } else |
1068 | daddr = NULL; | 1064 | daddr = NULL; |
1069 | 1065 | ||
@@ -1133,8 +1129,8 @@ do_udp_sendmsg: | |||
1133 | * sk->sk_dst_cache. | 1129 | * sk->sk_dst_cache. |
1134 | */ | 1130 | */ |
1135 | if (sk->sk_state == TCP_ESTABLISHED && | 1131 | if (sk->sk_state == TCP_ESTABLISHED && |
1136 | ipv6_addr_equal(daddr, &np->daddr)) | 1132 | ipv6_addr_equal(daddr, &sk->sk_v6_daddr)) |
1137 | daddr = &np->daddr; | 1133 | daddr = &sk->sk_v6_daddr; |
1138 | 1134 | ||
1139 | if (addr_len >= sizeof(struct sockaddr_in6) && | 1135 | if (addr_len >= sizeof(struct sockaddr_in6) && |
1140 | sin6->sin6_scope_id && | 1136 | sin6->sin6_scope_id && |
@@ -1145,7 +1141,7 @@ do_udp_sendmsg: | |||
1145 | return -EDESTADDRREQ; | 1141 | return -EDESTADDRREQ; |
1146 | 1142 | ||
1147 | fl6.fl6_dport = inet->inet_dport; | 1143 | fl6.fl6_dport = inet->inet_dport; |
1148 | daddr = &np->daddr; | 1144 | daddr = &sk->sk_v6_daddr; |
1149 | fl6.flowlabel = np->flow_label; | 1145 | fl6.flowlabel = np->flow_label; |
1150 | connected = 1; | 1146 | connected = 1; |
1151 | } | 1147 | } |
@@ -1261,8 +1257,8 @@ do_append_data: | |||
1261 | if (dst) { | 1257 | if (dst) { |
1262 | if (connected) { | 1258 | if (connected) { |
1263 | ip6_dst_store(sk, dst, | 1259 | ip6_dst_store(sk, dst, |
1264 | ipv6_addr_equal(&fl6.daddr, &np->daddr) ? | 1260 | ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ? |
1265 | &np->daddr : NULL, | 1261 | &sk->sk_v6_daddr : NULL, |
1266 | #ifdef CONFIG_IPV6_SUBTREES | 1262 | #ifdef CONFIG_IPV6_SUBTREES |
1267 | ipv6_addr_equal(&fl6.saddr, &np->saddr) ? | 1263 | ipv6_addr_equal(&fl6.saddr, &np->saddr) ? |
1268 | &np->saddr : | 1264 | &np->saddr : |