aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-03-13 01:05:52 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-13 01:57:07 -0400
commit849e8a0ca8d5d286510ab30b5f67b91aa6965ef6 (patch)
tree995b044bc4e622efb842799e03e90185a203173c /net
parent3e5da62d0bcbfa86332f66cca0e3983e70557fac (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.c24
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
41struct tcp_metrics_block { 41struct 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
56static inline struct net *tm_net(struct tcp_metrics_block *tm)
57{
58 return read_pnet(&tm->tcpm_net);
59}
60
55static bool tcp_metric_locked(struct tcp_metrics_block *tm, 61static 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;