diff options
author | Christoph Paasch <christoph.paasch@uclouvain.be> | 2014-01-08 10:05:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-10 17:38:18 -0500 |
commit | a544302820db12660b15de185b9e67c781a6b74e (patch) | |
tree | 3eb9015f85c1adfc7bf43c40b197b7f12c8d38a4 /net/ipv4/tcp_metrics.c | |
parent | 324fd55a19827b7191cc6ab73865e30c0e6e6423 (diff) |
tcp: metrics: Add source-address to tcp-metrics
We add the source-address to the tcp-metrics, so that different metrics
will be used per source/destination-pair. We use the destination-hash to
store the metric inside the hash-table. That way, deleting and dumping
via "ip tcp_metrics" is easy.
Signed-off-by: Christoph Paasch <christoph.paasch@uclouvain.be>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_metrics.c')
-rw-r--r-- | net/ipv4/tcp_metrics.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index f9b5f519a4ea..de32aa41a846 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -31,6 +31,7 @@ struct tcp_fastopen_metrics { | |||
31 | 31 | ||
32 | struct tcp_metrics_block { | 32 | struct tcp_metrics_block { |
33 | struct tcp_metrics_block __rcu *tcpm_next; | 33 | struct tcp_metrics_block __rcu *tcpm_next; |
34 | struct inetpeer_addr tcpm_saddr; | ||
34 | struct inetpeer_addr tcpm_daddr; | 35 | struct inetpeer_addr tcpm_daddr; |
35 | unsigned long tcpm_stamp; | 36 | unsigned long tcpm_stamp; |
36 | u32 tcpm_ts; | 37 | u32 tcpm_ts; |
@@ -131,6 +132,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst, | |||
131 | } | 132 | } |
132 | 133 | ||
133 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | 134 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, |
135 | struct inetpeer_addr *saddr, | ||
134 | struct inetpeer_addr *daddr, | 136 | struct inetpeer_addr *daddr, |
135 | unsigned int hash, | 137 | unsigned int hash, |
136 | bool reclaim) | 138 | bool reclaim) |
@@ -155,6 +157,7 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | |||
155 | if (!tm) | 157 | if (!tm) |
156 | goto out_unlock; | 158 | goto out_unlock; |
157 | } | 159 | } |
160 | tm->tcpm_saddr = *saddr; | ||
158 | tm->tcpm_daddr = *daddr; | 161 | tm->tcpm_daddr = *daddr; |
159 | 162 | ||
160 | tcpm_suck_dst(tm, dst, true); | 163 | tcpm_suck_dst(tm, dst, true); |
@@ -189,7 +192,8 @@ static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, in | |||
189 | return NULL; | 192 | return NULL; |
190 | } | 193 | } |
191 | 194 | ||
192 | static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *daddr, | 195 | static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *saddr, |
196 | const struct inetpeer_addr *daddr, | ||
193 | struct net *net, unsigned int hash) | 197 | struct net *net, unsigned int hash) |
194 | { | 198 | { |
195 | struct tcp_metrics_block *tm; | 199 | struct tcp_metrics_block *tm; |
@@ -197,7 +201,8 @@ static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *d | |||
197 | 201 | ||
198 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 202 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
199 | tm = rcu_dereference(tm->tcpm_next)) { | 203 | tm = rcu_dereference(tm->tcpm_next)) { |
200 | if (addr_same(&tm->tcpm_daddr, daddr)) | 204 | if (addr_same(&tm->tcpm_saddr, saddr) && |
205 | addr_same(&tm->tcpm_daddr, daddr)) | ||
201 | break; | 206 | break; |
202 | depth++; | 207 | depth++; |
203 | } | 208 | } |
@@ -208,18 +213,21 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
208 | struct dst_entry *dst) | 213 | struct dst_entry *dst) |
209 | { | 214 | { |
210 | struct tcp_metrics_block *tm; | 215 | struct tcp_metrics_block *tm; |
211 | struct inetpeer_addr daddr; | 216 | struct inetpeer_addr saddr, daddr; |
212 | unsigned int hash; | 217 | unsigned int hash; |
213 | struct net *net; | 218 | struct net *net; |
214 | 219 | ||
220 | saddr.family = req->rsk_ops->family; | ||
215 | daddr.family = req->rsk_ops->family; | 221 | daddr.family = req->rsk_ops->family; |
216 | switch (daddr.family) { | 222 | switch (daddr.family) { |
217 | case AF_INET: | 223 | case AF_INET: |
224 | saddr.addr.a4 = inet_rsk(req)->ir_loc_addr; | ||
218 | daddr.addr.a4 = inet_rsk(req)->ir_rmt_addr; | 225 | daddr.addr.a4 = inet_rsk(req)->ir_rmt_addr; |
219 | hash = (__force unsigned int) daddr.addr.a4; | 226 | hash = (__force unsigned int) daddr.addr.a4; |
220 | break; | 227 | break; |
221 | #if IS_ENABLED(CONFIG_IPV6) | 228 | #if IS_ENABLED(CONFIG_IPV6) |
222 | case AF_INET6: | 229 | case AF_INET6: |
230 | *(struct in6_addr *)saddr.addr.a6 = inet_rsk(req)->ir_v6_loc_addr; | ||
223 | *(struct in6_addr *)daddr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr; | 231 | *(struct in6_addr *)daddr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr; |
224 | hash = ipv6_addr_hash(&inet_rsk(req)->ir_v6_rmt_addr); | 232 | hash = ipv6_addr_hash(&inet_rsk(req)->ir_v6_rmt_addr); |
225 | break; | 233 | break; |
@@ -233,7 +241,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
233 | 241 | ||
234 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 242 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
235 | tm = rcu_dereference(tm->tcpm_next)) { | 243 | tm = rcu_dereference(tm->tcpm_next)) { |
236 | if (addr_same(&tm->tcpm_daddr, &daddr)) | 244 | if (addr_same(&tm->tcpm_saddr, &saddr) && |
245 | addr_same(&tm->tcpm_daddr, &daddr)) | ||
237 | break; | 246 | break; |
238 | } | 247 | } |
239 | tcpm_check_stamp(tm, dst); | 248 | tcpm_check_stamp(tm, dst); |
@@ -243,18 +252,21 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
243 | static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw) | 252 | static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw) |
244 | { | 253 | { |
245 | struct tcp_metrics_block *tm; | 254 | struct tcp_metrics_block *tm; |
246 | struct inetpeer_addr daddr; | 255 | struct inetpeer_addr saddr, daddr; |
247 | unsigned int hash; | 256 | unsigned int hash; |
248 | struct net *net; | 257 | struct net *net; |
249 | 258 | ||
259 | saddr.family = tw->tw_family; | ||
250 | daddr.family = tw->tw_family; | 260 | daddr.family = tw->tw_family; |
251 | switch (daddr.family) { | 261 | switch (daddr.family) { |
252 | case AF_INET: | 262 | case AF_INET: |
263 | saddr.addr.a4 = tw->tw_rcv_saddr; | ||
253 | daddr.addr.a4 = tw->tw_daddr; | 264 | daddr.addr.a4 = tw->tw_daddr; |
254 | hash = (__force unsigned int) daddr.addr.a4; | 265 | hash = (__force unsigned int) daddr.addr.a4; |
255 | break; | 266 | break; |
256 | #if IS_ENABLED(CONFIG_IPV6) | 267 | #if IS_ENABLED(CONFIG_IPV6) |
257 | case AF_INET6: | 268 | case AF_INET6: |
269 | *(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr; | ||
258 | *(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr; | 270 | *(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr; |
259 | hash = ipv6_addr_hash(&tw->tw_v6_daddr); | 271 | hash = ipv6_addr_hash(&tw->tw_v6_daddr); |
260 | break; | 272 | break; |
@@ -268,7 +280,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock | |||
268 | 280 | ||
269 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 281 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
270 | tm = rcu_dereference(tm->tcpm_next)) { | 282 | tm = rcu_dereference(tm->tcpm_next)) { |
271 | if (addr_same(&tm->tcpm_daddr, &daddr)) | 283 | if (addr_same(&tm->tcpm_saddr, &saddr) && |
284 | addr_same(&tm->tcpm_daddr, &daddr)) | ||
272 | break; | 285 | break; |
273 | } | 286 | } |
274 | return tm; | 287 | return tm; |
@@ -279,19 +292,22 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, | |||
279 | bool create) | 292 | bool create) |
280 | { | 293 | { |
281 | struct tcp_metrics_block *tm; | 294 | struct tcp_metrics_block *tm; |
282 | struct inetpeer_addr daddr; | 295 | struct inetpeer_addr saddr, daddr; |
283 | unsigned int hash; | 296 | unsigned int hash; |
284 | struct net *net; | 297 | struct net *net; |
285 | bool reclaim; | 298 | bool reclaim; |
286 | 299 | ||
300 | saddr.family = sk->sk_family; | ||
287 | daddr.family = sk->sk_family; | 301 | daddr.family = sk->sk_family; |
288 | switch (daddr.family) { | 302 | switch (daddr.family) { |
289 | case AF_INET: | 303 | case AF_INET: |
304 | saddr.addr.a4 = inet_sk(sk)->inet_saddr; | ||
290 | daddr.addr.a4 = inet_sk(sk)->inet_daddr; | 305 | daddr.addr.a4 = inet_sk(sk)->inet_daddr; |
291 | hash = (__force unsigned int) daddr.addr.a4; | 306 | hash = (__force unsigned int) daddr.addr.a4; |
292 | break; | 307 | break; |
293 | #if IS_ENABLED(CONFIG_IPV6) | 308 | #if IS_ENABLED(CONFIG_IPV6) |
294 | case AF_INET6: | 309 | case AF_INET6: |
310 | *(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr; | ||
295 | *(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr; | 311 | *(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr; |
296 | hash = ipv6_addr_hash(&sk->sk_v6_daddr); | 312 | hash = ipv6_addr_hash(&sk->sk_v6_daddr); |
297 | break; | 313 | break; |
@@ -303,14 +319,14 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, | |||
303 | net = dev_net(dst->dev); | 319 | net = dev_net(dst->dev); |
304 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); | 320 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); |
305 | 321 | ||
306 | tm = __tcp_get_metrics(&daddr, net, hash); | 322 | tm = __tcp_get_metrics(&saddr, &daddr, net, hash); |
307 | reclaim = false; | 323 | reclaim = false; |
308 | if (tm == TCP_METRICS_RECLAIM_PTR) { | 324 | if (tm == TCP_METRICS_RECLAIM_PTR) { |
309 | reclaim = true; | 325 | reclaim = true; |
310 | tm = NULL; | 326 | tm = NULL; |
311 | } | 327 | } |
312 | if (!tm && create) | 328 | if (!tm && create) |
313 | tm = tcpm_new(dst, &daddr, hash, reclaim); | 329 | tm = tcpm_new(dst, &saddr, &daddr, hash, reclaim); |
314 | else | 330 | else |
315 | tcpm_check_stamp(tm, dst); | 331 | tcpm_check_stamp(tm, dst); |
316 | 332 | ||