diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2015-03-13 01:05:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-13 01:57:07 -0400 |
commit | 849e8a0ca8d5d286510ab30b5f67b91aa6965ef6 (patch) | |
tree | 995b044bc4e622efb842799e03e90185a203173c /net | |
parent | 3e5da62d0bcbfa86332f66cca0e3983e70557fac (diff) |
tcp_metrics: Add a field tcpm_net and verify it matches on lookup
In preparation for using one tcp metrics hash table for all network
namespaces add a field tcpm_net to struct tcp_metrics_block, and
verify that field on all hash table lookups.
Make the field tcpm_net of type possible_net_t so it takes no space
when network namespaces are disabled.
Further add a function tm_net to read that field so we can be
efficient when network namespaces are disabled and concise
the rest of the time.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_metrics.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index fbb42f44501e..461c3d2e1ca4 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -40,6 +40,7 @@ struct tcp_fastopen_metrics { | |||
40 | 40 | ||
41 | struct tcp_metrics_block { | 41 | struct tcp_metrics_block { |
42 | struct tcp_metrics_block __rcu *tcpm_next; | 42 | struct tcp_metrics_block __rcu *tcpm_next; |
43 | possible_net_t tcpm_net; | ||
43 | struct inetpeer_addr tcpm_saddr; | 44 | struct inetpeer_addr tcpm_saddr; |
44 | struct inetpeer_addr tcpm_daddr; | 45 | struct inetpeer_addr tcpm_daddr; |
45 | unsigned long tcpm_stamp; | 46 | unsigned long tcpm_stamp; |
@@ -52,6 +53,11 @@ struct tcp_metrics_block { | |||
52 | struct rcu_head rcu_head; | 53 | struct rcu_head rcu_head; |
53 | }; | 54 | }; |
54 | 55 | ||
56 | static inline struct net *tm_net(struct tcp_metrics_block *tm) | ||
57 | { | ||
58 | return read_pnet(&tm->tcpm_net); | ||
59 | } | ||
60 | |||
55 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, | 61 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, |
56 | enum tcp_metric_index idx) | 62 | enum tcp_metric_index idx) |
57 | { | 63 | { |
@@ -183,6 +189,7 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | |||
183 | if (!tm) | 189 | if (!tm) |
184 | goto out_unlock; | 190 | goto out_unlock; |
185 | } | 191 | } |
192 | write_pnet(&tm->tcpm_net, net); | ||
186 | tm->tcpm_saddr = *saddr; | 193 | tm->tcpm_saddr = *saddr; |
187 | tm->tcpm_daddr = *daddr; | 194 | tm->tcpm_daddr = *daddr; |
188 | 195 | ||
@@ -217,7 +224,8 @@ static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *s | |||
217 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 224 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
218 | tm = rcu_dereference(tm->tcpm_next)) { | 225 | tm = rcu_dereference(tm->tcpm_next)) { |
219 | if (addr_same(&tm->tcpm_saddr, saddr) && | 226 | if (addr_same(&tm->tcpm_saddr, saddr) && |
220 | addr_same(&tm->tcpm_daddr, daddr)) | 227 | addr_same(&tm->tcpm_daddr, daddr) && |
228 | net_eq(tm_net(tm), net)) | ||
221 | break; | 229 | break; |
222 | depth++; | 230 | depth++; |
223 | } | 231 | } |
@@ -258,7 +266,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req, | |||
258 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 266 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
259 | tm = rcu_dereference(tm->tcpm_next)) { | 267 | tm = rcu_dereference(tm->tcpm_next)) { |
260 | if (addr_same(&tm->tcpm_saddr, &saddr) && | 268 | if (addr_same(&tm->tcpm_saddr, &saddr) && |
261 | addr_same(&tm->tcpm_daddr, &daddr)) | 269 | addr_same(&tm->tcpm_daddr, &daddr) && |
270 | net_eq(tm_net(tm), net)) | ||
262 | break; | 271 | break; |
263 | } | 272 | } |
264 | tcpm_check_stamp(tm, dst); | 273 | tcpm_check_stamp(tm, dst); |
@@ -306,7 +315,8 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock | |||
306 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 315 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
307 | tm = rcu_dereference(tm->tcpm_next)) { | 316 | tm = rcu_dereference(tm->tcpm_next)) { |
308 | if (addr_same(&tm->tcpm_saddr, &saddr) && | 317 | if (addr_same(&tm->tcpm_saddr, &saddr) && |
309 | addr_same(&tm->tcpm_daddr, &daddr)) | 318 | addr_same(&tm->tcpm_daddr, &daddr) && |
319 | net_eq(tm_net(tm), net)) | ||
310 | break; | 320 | break; |
311 | } | 321 | } |
312 | return tm; | 322 | return tm; |
@@ -912,6 +922,8 @@ static int tcp_metrics_nl_dump(struct sk_buff *skb, | |||
912 | rcu_read_lock(); | 922 | rcu_read_lock(); |
913 | for (col = 0, tm = rcu_dereference(hb->chain); tm; | 923 | for (col = 0, tm = rcu_dereference(hb->chain); tm; |
914 | tm = rcu_dereference(tm->tcpm_next), col++) { | 924 | tm = rcu_dereference(tm->tcpm_next), col++) { |
925 | if (!net_eq(tm_net(tm), net)) | ||
926 | continue; | ||
915 | if (col < s_col) | 927 | if (col < s_col) |
916 | continue; | 928 | continue; |
917 | if (tcp_metrics_dump_info(skb, cb, tm) < 0) { | 929 | if (tcp_metrics_dump_info(skb, cb, tm) < 0) { |
@@ -1004,7 +1016,8 @@ static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1004 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; | 1016 | for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm; |
1005 | tm = rcu_dereference(tm->tcpm_next)) { | 1017 | tm = rcu_dereference(tm->tcpm_next)) { |
1006 | if (addr_same(&tm->tcpm_daddr, &daddr) && | 1018 | if (addr_same(&tm->tcpm_daddr, &daddr) && |
1007 | (!src || addr_same(&tm->tcpm_saddr, &saddr))) { | 1019 | (!src || addr_same(&tm->tcpm_saddr, &saddr)) && |
1020 | net_eq(tm_net(tm), net)) { | ||
1008 | ret = tcp_metrics_fill_info(msg, tm); | 1021 | ret = tcp_metrics_fill_info(msg, tm); |
1009 | break; | 1022 | break; |
1010 | } | 1023 | } |
@@ -1081,7 +1094,8 @@ static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1081 | spin_lock_bh(&tcp_metrics_lock); | 1094 | spin_lock_bh(&tcp_metrics_lock); |
1082 | for (tm = deref_locked_genl(*pp); tm; tm = deref_locked_genl(*pp)) { | 1095 | for (tm = deref_locked_genl(*pp); tm; tm = deref_locked_genl(*pp)) { |
1083 | if (addr_same(&tm->tcpm_daddr, &daddr) && | 1096 | if (addr_same(&tm->tcpm_daddr, &daddr) && |
1084 | (!src || addr_same(&tm->tcpm_saddr, &saddr))) { | 1097 | (!src || addr_same(&tm->tcpm_saddr, &saddr)) && |
1098 | net_eq(tm_net(tm), net)) { | ||
1085 | *pp = tm->tcpm_next; | 1099 | *pp = tm->tcpm_next; |
1086 | kfree_rcu(tm, rcu_head); | 1100 | kfree_rcu(tm, rcu_head); |
1087 | found = true; | 1101 | found = true; |