aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Schillstrom <hans.schillstrom@ericsson.com>2011-01-03 08:44:43 -0500
committerSimon Horman <horms@verge.net.au>2011-01-12 20:30:26 -0500
commitfc723250c9cb046cc19833a2b1c4309bbf59ac36 (patch)
treefa8cd33ad9e020549dd8c6389f311d25e495ca7d
parent61b1ab4583e275af216c8454b9256de680499b19 (diff)
IPVS: netns to services part 1
Services hash tables got netns ptr a hash arg, While Real Servers (rs) has been moved to ipvs struct. Two new inline functions added to get net ptr from skb. Since ip_vs is called from different contexts there is two places to dig for the net ptr skb->dev or skb->sk this is handled in skb_net() and skb_sknet() Global functions, ip_vs_service_get() ip_vs_lookup_real_service() etc have got struct net *net as first param. If possible get net ptr skb etc, - if not &init_net is used at this early stage of patching. ip_vs_ctl.c procfs not ready for netns yet. *v3 Comments by Julian - __ip_vs_service_find and __ip_vs_svc_fwm_find are fast path, net_eq(svc->net, net) so the check is at the end now. - net = skb_net(skb) in ip_vs_out moved after check for skb_dst. Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--include/net/ip_vs.h64
-rw-r--r--include/net/netns/ip_vs.h8
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c232
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c2
9 files changed, 214 insertions, 115 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index c1c2ece3ed9..d551e0d8fd9 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -37,6 +37,59 @@ static inline struct netns_ipvs *net_ipvs(struct net* net)
37{ 37{
38 return net->ipvs; 38 return net->ipvs;
39} 39}
40/*
41 * Get net ptr from skb in traffic cases
42 * use skb_sknet when call is from userland (ioctl or netlink)
43 */
44static inline struct net *skb_net(struct sk_buff *skb)
45{
46#ifdef CONFIG_NET_NS
47#ifdef CONFIG_IP_VS_DEBUG
48 /*
49 * This is used for debug only.
50 * Start with the most likely hit
51 * End with BUG
52 */
53 if (likely(skb->dev && skb->dev->nd_net))
54 return dev_net(skb->dev);
55 if (skb_dst(skb)->dev)
56 return dev_net(skb_dst(skb)->dev);
57 WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",
58 __func__, __LINE__);
59 if (likely(skb->sk && skb->sk->sk_net))
60 return sock_net(skb->sk);
61 pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
62 __func__, __LINE__);
63 BUG();
64#else
65 return dev_net(skb->dev ? : skb_dst(skb)->dev);
66#endif
67#else
68 return &init_net;
69#endif
70}
71
72static inline struct net *skb_sknet(struct sk_buff *skb)
73{
74#ifdef CONFIG_NET_NS
75#ifdef CONFIG_IP_VS_DEBUG
76 /* Start with the most likely hit */
77 if (likely(skb->sk && skb->sk->sk_net))
78 return sock_net(skb->sk);
79 WARN(skb->dev, "Maybe skb_net should be used instead in %s() line:%d\n",
80 __func__, __LINE__);
81 if (likely(skb->dev && skb->dev->nd_net))
82 return dev_net(skb->dev);
83 pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
84 __func__, __LINE__);
85 BUG();
86#else
87 return sock_net(skb->sk);
88#endif
89#else
90 return &init_net;
91#endif
92}
40 93
41/* Connections' size value needed by ip_vs_ctl.c */ 94/* Connections' size value needed by ip_vs_ctl.c */
42extern int ip_vs_conn_tab_size; 95extern int ip_vs_conn_tab_size;
@@ -496,6 +549,7 @@ struct ip_vs_service {
496 unsigned flags; /* service status flags */ 549 unsigned flags; /* service status flags */
497 unsigned timeout; /* persistent timeout in ticks */ 550 unsigned timeout; /* persistent timeout in ticks */
498 __be32 netmask; /* grouping granularity */ 551 __be32 netmask; /* grouping granularity */
552 struct net *net;
499 553
500 struct list_head destinations; /* real server d-linked list */ 554 struct list_head destinations; /* real server d-linked list */
501 __u32 num_dests; /* number of servers */ 555 __u32 num_dests; /* number of servers */
@@ -896,7 +950,7 @@ extern int sysctl_ip_vs_sync_ver;
896 950
897extern void ip_vs_sync_switch_mode(int mode); 951extern void ip_vs_sync_switch_mode(int mode);
898extern struct ip_vs_service * 952extern struct ip_vs_service *
899ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, 953ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
900 const union nf_inet_addr *vaddr, __be16 vport); 954 const union nf_inet_addr *vaddr, __be16 vport);
901 955
902static inline void ip_vs_service_put(struct ip_vs_service *svc) 956static inline void ip_vs_service_put(struct ip_vs_service *svc)
@@ -905,7 +959,7 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc)
905} 959}
906 960
907extern struct ip_vs_dest * 961extern struct ip_vs_dest *
908ip_vs_lookup_real_service(int af, __u16 protocol, 962ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
909 const union nf_inet_addr *daddr, __be16 dport); 963 const union nf_inet_addr *daddr, __be16 dport);
910 964
911extern int ip_vs_use_count_inc(void); 965extern int ip_vs_use_count_inc(void);
@@ -913,9 +967,9 @@ extern void ip_vs_use_count_dec(void);
913extern int ip_vs_control_init(void); 967extern int ip_vs_control_init(void);
914extern void ip_vs_control_cleanup(void); 968extern void ip_vs_control_cleanup(void);
915extern struct ip_vs_dest * 969extern struct ip_vs_dest *
916ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, 970ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr,
917 const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol, 971 __be16 dport, const union nf_inet_addr *vaddr, __be16 vport,
918 __u32 fwmark); 972 __u16 protocol, __u32 fwmark);
919extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); 973extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
920 974
921 975
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h
index 12fe84087ce..5b87d22a39f 100644
--- a/include/net/netns/ip_vs.h
+++ b/include/net/netns/ip_vs.h
@@ -20,6 +20,14 @@ struct ctl_table_header;
20 20
21struct netns_ipvs { 21struct netns_ipvs {
22 int gen; /* Generation */ 22 int gen; /* Generation */
23 /*
24 * Hash table: for real service lookups
25 */
26 #define IP_VS_RTAB_BITS 4
27 #define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
28 #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1)
29
30 struct list_head rs_table[IP_VS_RTAB_SIZE];
23}; 31};
24 32
25#endif /* IP_VS_H_ */ 33#endif /* IP_VS_H_ */
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 7c1b502f8d8..7a0e79e3ad0 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -611,7 +611,7 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
611 struct ip_vs_dest *dest; 611 struct ip_vs_dest *dest;
612 612
613 if ((cp) && (!cp->dest)) { 613 if ((cp) && (!cp->dest)) {
614 dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport, 614 dest = ip_vs_find_dest(&init_net, cp->af, &cp->daddr, cp->dport,
615 &cp->vaddr, cp->vport, 615 &cp->vaddr, cp->vport,
616 cp->protocol, cp->fwmark); 616 cp->protocol, cp->fwmark);
617 ip_vs_bind_dest(cp, dest); 617 ip_vs_bind_dest(cp, dest);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 206f40c548d..d0616ea1eeb 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1031,6 +1031,7 @@ drop:
1031static unsigned int 1031static unsigned int
1032ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) 1032ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
1033{ 1033{
1034 struct net *net = NULL;
1034 struct ip_vs_iphdr iph; 1035 struct ip_vs_iphdr iph;
1035 struct ip_vs_protocol *pp; 1036 struct ip_vs_protocol *pp;
1036 struct ip_vs_conn *cp; 1037 struct ip_vs_conn *cp;
@@ -1054,6 +1055,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
1054 if (unlikely(!skb_dst(skb))) 1055 if (unlikely(!skb_dst(skb)))
1055 return NF_ACCEPT; 1056 return NF_ACCEPT;
1056 1057
1058 net = skb_net(skb);
1057 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); 1059 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
1058#ifdef CONFIG_IP_VS_IPV6 1060#ifdef CONFIG_IP_VS_IPV6
1059 if (af == AF_INET6) { 1061 if (af == AF_INET6) {
@@ -1119,7 +1121,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
1119 sizeof(_ports), _ports); 1121 sizeof(_ports), _ports);
1120 if (pptr == NULL) 1122 if (pptr == NULL)
1121 return NF_ACCEPT; /* Not for me */ 1123 return NF_ACCEPT; /* Not for me */
1122 if (ip_vs_lookup_real_service(af, iph.protocol, 1124 if (ip_vs_lookup_real_service(net, af, iph.protocol,
1123 &iph.saddr, 1125 &iph.saddr,
1124 pptr[0])) { 1126 pptr[0])) {
1125 /* 1127 /*
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index ceeef4352d3..2d7c96bd211 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -288,15 +288,6 @@ static struct list_head ip_vs_svc_table[IP_VS_SVC_TAB_SIZE];
288static struct list_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE]; 288static struct list_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE];
289 289
290/* 290/*
291 * Hash table: for real service lookups
292 */
293#define IP_VS_RTAB_BITS 4
294#define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
295#define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1)
296
297static struct list_head ip_vs_rtable[IP_VS_RTAB_SIZE];
298
299/*
300 * Trash for destinations 291 * Trash for destinations
301 */ 292 */
302static LIST_HEAD(ip_vs_dest_trash); 293static LIST_HEAD(ip_vs_dest_trash);
@@ -311,9 +302,9 @@ static atomic_t ip_vs_nullsvc_counter = ATOMIC_INIT(0);
311/* 302/*
312 * Returns hash value for virtual service 303 * Returns hash value for virtual service
313 */ 304 */
314static __inline__ unsigned 305static inline unsigned
315ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr, 306ip_vs_svc_hashkey(struct net *net, int af, unsigned proto,
316 __be16 port) 307 const union nf_inet_addr *addr, __be16 port)
317{ 308{
318 register unsigned porth = ntohs(port); 309 register unsigned porth = ntohs(port);
319 __be32 addr_fold = addr->ip; 310 __be32 addr_fold = addr->ip;
@@ -323,6 +314,7 @@ ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
323 addr_fold = addr->ip6[0]^addr->ip6[1]^ 314 addr_fold = addr->ip6[0]^addr->ip6[1]^
324 addr->ip6[2]^addr->ip6[3]; 315 addr->ip6[2]^addr->ip6[3];
325#endif 316#endif
317 addr_fold ^= ((size_t)net>>8);
326 318
327 return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth) 319 return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth)
328 & IP_VS_SVC_TAB_MASK; 320 & IP_VS_SVC_TAB_MASK;
@@ -331,13 +323,13 @@ ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
331/* 323/*
332 * Returns hash value of fwmark for virtual service lookup 324 * Returns hash value of fwmark for virtual service lookup
333 */ 325 */
334static __inline__ unsigned ip_vs_svc_fwm_hashkey(__u32 fwmark) 326static inline unsigned ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark)
335{ 327{
336 return fwmark & IP_VS_SVC_TAB_MASK; 328 return (((size_t)net>>8) ^ fwmark) & IP_VS_SVC_TAB_MASK;
337} 329}
338 330
339/* 331/*
340 * Hashes a service in the ip_vs_svc_table by <proto,addr,port> 332 * Hashes a service in the ip_vs_svc_table by <netns,proto,addr,port>
341 * or in the ip_vs_svc_fwm_table by fwmark. 333 * or in the ip_vs_svc_fwm_table by fwmark.
342 * Should be called with locked tables. 334 * Should be called with locked tables.
343 */ 335 */
@@ -353,16 +345,16 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
353 345
354 if (svc->fwmark == 0) { 346 if (svc->fwmark == 0) {
355 /* 347 /*
356 * Hash it by <protocol,addr,port> in ip_vs_svc_table 348 * Hash it by <netns,protocol,addr,port> in ip_vs_svc_table
357 */ 349 */
358 hash = ip_vs_svc_hashkey(svc->af, svc->protocol, &svc->addr, 350 hash = ip_vs_svc_hashkey(svc->net, svc->af, svc->protocol,
359 svc->port); 351 &svc->addr, svc->port);
360 list_add(&svc->s_list, &ip_vs_svc_table[hash]); 352 list_add(&svc->s_list, &ip_vs_svc_table[hash]);
361 } else { 353 } else {
362 /* 354 /*
363 * Hash it by fwmark in ip_vs_svc_fwm_table 355 * Hash it by fwmark in svc_fwm_table
364 */ 356 */
365 hash = ip_vs_svc_fwm_hashkey(svc->fwmark); 357 hash = ip_vs_svc_fwm_hashkey(svc->net, svc->fwmark);
366 list_add(&svc->f_list, &ip_vs_svc_fwm_table[hash]); 358 list_add(&svc->f_list, &ip_vs_svc_fwm_table[hash]);
367 } 359 }
368 360
@@ -374,7 +366,7 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
374 366
375 367
376/* 368/*
377 * Unhashes a service from ip_vs_svc_table/ip_vs_svc_fwm_table. 369 * Unhashes a service from svc_table / svc_fwm_table.
378 * Should be called with locked tables. 370 * Should be called with locked tables.
379 */ 371 */
380static int ip_vs_svc_unhash(struct ip_vs_service *svc) 372static int ip_vs_svc_unhash(struct ip_vs_service *svc)
@@ -386,10 +378,10 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
386 } 378 }
387 379
388 if (svc->fwmark == 0) { 380 if (svc->fwmark == 0) {
389 /* Remove it from the ip_vs_svc_table table */ 381 /* Remove it from the svc_table table */
390 list_del(&svc->s_list); 382 list_del(&svc->s_list);
391 } else { 383 } else {
392 /* Remove it from the ip_vs_svc_fwm_table table */ 384 /* Remove it from the svc_fwm_table table */
393 list_del(&svc->f_list); 385 list_del(&svc->f_list);
394 } 386 }
395 387
@@ -400,23 +392,24 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
400 392
401 393
402/* 394/*
403 * Get service by {proto,addr,port} in the service table. 395 * Get service by {netns, proto,addr,port} in the service table.
404 */ 396 */
405static inline struct ip_vs_service * 397static inline struct ip_vs_service *
406__ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr, 398__ip_vs_service_find(struct net *net, int af, __u16 protocol,
407 __be16 vport) 399 const union nf_inet_addr *vaddr, __be16 vport)
408{ 400{
409 unsigned hash; 401 unsigned hash;
410 struct ip_vs_service *svc; 402 struct ip_vs_service *svc;
411 403
412 /* Check for "full" addressed entries */ 404 /* Check for "full" addressed entries */
413 hash = ip_vs_svc_hashkey(af, protocol, vaddr, vport); 405 hash = ip_vs_svc_hashkey(net, af, protocol, vaddr, vport);
414 406
415 list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){ 407 list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){
416 if ((svc->af == af) 408 if ((svc->af == af)
417 && ip_vs_addr_equal(af, &svc->addr, vaddr) 409 && ip_vs_addr_equal(af, &svc->addr, vaddr)
418 && (svc->port == vport) 410 && (svc->port == vport)
419 && (svc->protocol == protocol)) { 411 && (svc->protocol == protocol)
412 && net_eq(svc->net, net)) {
420 /* HIT */ 413 /* HIT */
421 return svc; 414 return svc;
422 } 415 }
@@ -430,16 +423,17 @@ __ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr,
430 * Get service by {fwmark} in the service table. 423 * Get service by {fwmark} in the service table.
431 */ 424 */
432static inline struct ip_vs_service * 425static inline struct ip_vs_service *
433__ip_vs_svc_fwm_find(int af, __u32 fwmark) 426__ip_vs_svc_fwm_find(struct net *net, int af, __u32 fwmark)
434{ 427{
435 unsigned hash; 428 unsigned hash;
436 struct ip_vs_service *svc; 429 struct ip_vs_service *svc;
437 430
438 /* Check for fwmark addressed entries */ 431 /* Check for fwmark addressed entries */
439 hash = ip_vs_svc_fwm_hashkey(fwmark); 432 hash = ip_vs_svc_fwm_hashkey(net, fwmark);
440 433
441 list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) { 434 list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) {
442 if (svc->fwmark == fwmark && svc->af == af) { 435 if (svc->fwmark == fwmark && svc->af == af
436 && net_eq(svc->net, net)) {
443 /* HIT */ 437 /* HIT */
444 return svc; 438 return svc;
445 } 439 }
@@ -449,7 +443,7 @@ __ip_vs_svc_fwm_find(int af, __u32 fwmark)
449} 443}
450 444
451struct ip_vs_service * 445struct ip_vs_service *
452ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, 446ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
453 const union nf_inet_addr *vaddr, __be16 vport) 447 const union nf_inet_addr *vaddr, __be16 vport)
454{ 448{
455 struct ip_vs_service *svc; 449 struct ip_vs_service *svc;
@@ -459,14 +453,15 @@ ip_vs_service_get(int af, __u32 fwmark, __u16 protocol,
459 /* 453 /*
460 * Check the table hashed by fwmark first 454 * Check the table hashed by fwmark first
461 */ 455 */
462 if (fwmark && (svc = __ip_vs_svc_fwm_find(af, fwmark))) 456 svc = __ip_vs_svc_fwm_find(net, af, fwmark);
457 if (fwmark && svc)
463 goto out; 458 goto out;
464 459
465 /* 460 /*
466 * Check the table hashed by <protocol,addr,port> 461 * Check the table hashed by <protocol,addr,port>
467 * for "full" addressed entries 462 * for "full" addressed entries
468 */ 463 */
469 svc = __ip_vs_service_find(af, protocol, vaddr, vport); 464 svc = __ip_vs_service_find(net, af, protocol, vaddr, vport);
470 465
471 if (svc == NULL 466 if (svc == NULL
472 && protocol == IPPROTO_TCP 467 && protocol == IPPROTO_TCP
@@ -476,7 +471,7 @@ ip_vs_service_get(int af, __u32 fwmark, __u16 protocol,
476 * Check if ftp service entry exists, the packet 471 * Check if ftp service entry exists, the packet
477 * might belong to FTP data connections. 472 * might belong to FTP data connections.
478 */ 473 */
479 svc = __ip_vs_service_find(af, protocol, vaddr, FTPPORT); 474 svc = __ip_vs_service_find(net, af, protocol, vaddr, FTPPORT);
480 } 475 }
481 476
482 if (svc == NULL 477 if (svc == NULL
@@ -484,7 +479,7 @@ ip_vs_service_get(int af, __u32 fwmark, __u16 protocol,
484 /* 479 /*
485 * Check if the catch-all port (port zero) exists 480 * Check if the catch-all port (port zero) exists
486 */ 481 */
487 svc = __ip_vs_service_find(af, protocol, vaddr, 0); 482 svc = __ip_vs_service_find(net, af, protocol, vaddr, 0);
488 } 483 }
489 484
490 out: 485 out:
@@ -545,10 +540,10 @@ static inline unsigned ip_vs_rs_hashkey(int af,
545} 540}
546 541
547/* 542/*
548 * Hashes ip_vs_dest in ip_vs_rtable by <proto,addr,port>. 543 * Hashes ip_vs_dest in rs_table by <proto,addr,port>.
549 * should be called with locked tables. 544 * should be called with locked tables.
550 */ 545 */
551static int ip_vs_rs_hash(struct ip_vs_dest *dest) 546static int ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest)
552{ 547{
553 unsigned hash; 548 unsigned hash;
554 549
@@ -562,19 +557,19 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest)
562 */ 557 */
563 hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); 558 hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port);
564 559
565 list_add(&dest->d_list, &ip_vs_rtable[hash]); 560 list_add(&dest->d_list, &ipvs->rs_table[hash]);
566 561
567 return 1; 562 return 1;
568} 563}
569 564
570/* 565/*
571 * UNhashes ip_vs_dest from ip_vs_rtable. 566 * UNhashes ip_vs_dest from rs_table.
572 * should be called with locked tables. 567 * should be called with locked tables.
573 */ 568 */
574static int ip_vs_rs_unhash(struct ip_vs_dest *dest) 569static int ip_vs_rs_unhash(struct ip_vs_dest *dest)
575{ 570{
576 /* 571 /*
577 * Remove it from the ip_vs_rtable table. 572 * Remove it from the rs_table table.
578 */ 573 */
579 if (!list_empty(&dest->d_list)) { 574 if (!list_empty(&dest->d_list)) {
580 list_del(&dest->d_list); 575 list_del(&dest->d_list);
@@ -588,10 +583,11 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest)
588 * Lookup real service by <proto,addr,port> in the real service table. 583 * Lookup real service by <proto,addr,port> in the real service table.
589 */ 584 */
590struct ip_vs_dest * 585struct ip_vs_dest *
591ip_vs_lookup_real_service(int af, __u16 protocol, 586ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
592 const union nf_inet_addr *daddr, 587 const union nf_inet_addr *daddr,
593 __be16 dport) 588 __be16 dport)
594{ 589{
590 struct netns_ipvs *ipvs = net_ipvs(net);
595 unsigned hash; 591 unsigned hash;
596 struct ip_vs_dest *dest; 592 struct ip_vs_dest *dest;
597 593
@@ -602,7 +598,7 @@ ip_vs_lookup_real_service(int af, __u16 protocol,
602 hash = ip_vs_rs_hashkey(af, daddr, dport); 598 hash = ip_vs_rs_hashkey(af, daddr, dport);
603 599
604 read_lock(&__ip_vs_rs_lock); 600 read_lock(&__ip_vs_rs_lock);
605 list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { 601 list_for_each_entry(dest, &ipvs->rs_table[hash], d_list) {
606 if ((dest->af == af) 602 if ((dest->af == af)
607 && ip_vs_addr_equal(af, &dest->addr, daddr) 603 && ip_vs_addr_equal(af, &dest->addr, daddr)
608 && (dest->port == dport) 604 && (dest->port == dport)
@@ -652,7 +648,8 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
652 * ip_vs_lookup_real_service() looked promissing, but 648 * ip_vs_lookup_real_service() looked promissing, but
653 * seems not working as expected. 649 * seems not working as expected.
654 */ 650 */
655struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr, 651struct ip_vs_dest *ip_vs_find_dest(struct net *net, int af,
652 const union nf_inet_addr *daddr,
656 __be16 dport, 653 __be16 dport,
657 const union nf_inet_addr *vaddr, 654 const union nf_inet_addr *vaddr,
658 __be16 vport, __u16 protocol, __u32 fwmark) 655 __be16 vport, __u16 protocol, __u32 fwmark)
@@ -660,7 +657,7 @@ struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr,
660 struct ip_vs_dest *dest; 657 struct ip_vs_dest *dest;
661 struct ip_vs_service *svc; 658 struct ip_vs_service *svc;
662 659
663 svc = ip_vs_service_get(af, fwmark, protocol, vaddr, vport); 660 svc = ip_vs_service_get(net, af, fwmark, protocol, vaddr, vport);
664 if (!svc) 661 if (!svc)
665 return NULL; 662 return NULL;
666 dest = ip_vs_lookup_dest(svc, daddr, dport); 663 dest = ip_vs_lookup_dest(svc, daddr, dport);
@@ -768,6 +765,7 @@ static void
768__ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, 765__ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
769 struct ip_vs_dest_user_kern *udest, int add) 766 struct ip_vs_dest_user_kern *udest, int add)
770{ 767{
768 struct netns_ipvs *ipvs = net_ipvs(svc->net);
771 int conn_flags; 769 int conn_flags;
772 770
773 /* set the weight and the flags */ 771 /* set the weight and the flags */
@@ -780,11 +778,11 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
780 conn_flags |= IP_VS_CONN_F_NOOUTPUT; 778 conn_flags |= IP_VS_CONN_F_NOOUTPUT;
781 } else { 779 } else {
782 /* 780 /*
783 * Put the real service in ip_vs_rtable if not present. 781 * Put the real service in rs_table if not present.
784 * For now only for NAT! 782 * For now only for NAT!
785 */ 783 */
786 write_lock_bh(&__ip_vs_rs_lock); 784 write_lock_bh(&__ip_vs_rs_lock);
787 ip_vs_rs_hash(dest); 785 ip_vs_rs_hash(ipvs, dest);
788 write_unlock_bh(&__ip_vs_rs_lock); 786 write_unlock_bh(&__ip_vs_rs_lock);
789 } 787 }
790 atomic_set(&dest->conn_flags, conn_flags); 788 atomic_set(&dest->conn_flags, conn_flags);
@@ -1117,7 +1115,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
1117 * Add a service into the service hash table 1115 * Add a service into the service hash table
1118 */ 1116 */
1119static int 1117static int
1120ip_vs_add_service(struct ip_vs_service_user_kern *u, 1118ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
1121 struct ip_vs_service **svc_p) 1119 struct ip_vs_service **svc_p)
1122{ 1120{
1123 int ret = 0; 1121 int ret = 0;
@@ -1172,6 +1170,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
1172 svc->flags = u->flags; 1170 svc->flags = u->flags;
1173 svc->timeout = u->timeout * HZ; 1171 svc->timeout = u->timeout * HZ;
1174 svc->netmask = u->netmask; 1172 svc->netmask = u->netmask;
1173 svc->net = net;
1175 1174
1176 INIT_LIST_HEAD(&svc->destinations); 1175 INIT_LIST_HEAD(&svc->destinations);
1177 rwlock_init(&svc->sched_lock); 1176 rwlock_init(&svc->sched_lock);
@@ -1428,17 +1427,19 @@ static int ip_vs_del_service(struct ip_vs_service *svc)
1428/* 1427/*
1429 * Flush all the virtual services 1428 * Flush all the virtual services
1430 */ 1429 */
1431static int ip_vs_flush(void) 1430static int ip_vs_flush(struct net *net)
1432{ 1431{
1433 int idx; 1432 int idx;
1434 struct ip_vs_service *svc, *nxt; 1433 struct ip_vs_service *svc, *nxt;
1435 1434
1436 /* 1435 /*
1437 * Flush the service table hashed by <protocol,addr,port> 1436 * Flush the service table hashed by <netns,protocol,addr,port>
1438 */ 1437 */
1439 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 1438 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
1440 list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx], s_list) { 1439 list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx],
1441 ip_vs_unlink_service(svc); 1440 s_list) {
1441 if (net_eq(svc->net, net))
1442 ip_vs_unlink_service(svc);
1442 } 1443 }
1443 } 1444 }
1444 1445
@@ -1448,7 +1449,8 @@ static int ip_vs_flush(void)
1448 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 1449 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
1449 list_for_each_entry_safe(svc, nxt, 1450 list_for_each_entry_safe(svc, nxt,
1450 &ip_vs_svc_fwm_table[idx], f_list) { 1451 &ip_vs_svc_fwm_table[idx], f_list) {
1451 ip_vs_unlink_service(svc); 1452 if (net_eq(svc->net, net))
1453 ip_vs_unlink_service(svc);
1452 } 1454 }
1453 } 1455 }
1454 1456
@@ -1472,20 +1474,22 @@ static int ip_vs_zero_service(struct ip_vs_service *svc)
1472 return 0; 1474 return 0;
1473} 1475}
1474 1476
1475static int ip_vs_zero_all(void) 1477static int ip_vs_zero_all(struct net *net)
1476{ 1478{
1477 int idx; 1479 int idx;
1478 struct ip_vs_service *svc; 1480 struct ip_vs_service *svc;
1479 1481
1480 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 1482 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
1481 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { 1483 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
1482 ip_vs_zero_service(svc); 1484 if (net_eq(svc->net, net))
1485 ip_vs_zero_service(svc);
1483 } 1486 }
1484 } 1487 }
1485 1488
1486 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 1489 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
1487 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { 1490 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
1488 ip_vs_zero_service(svc); 1491 if (net_eq(svc->net, net))
1492 ip_vs_zero_service(svc);
1489 } 1493 }
1490 } 1494 }
1491 1495
@@ -1763,6 +1767,7 @@ static struct ctl_table_header * sysctl_header;
1763#ifdef CONFIG_PROC_FS 1767#ifdef CONFIG_PROC_FS
1764 1768
1765struct ip_vs_iter { 1769struct ip_vs_iter {
1770 struct seq_net_private p; /* Do not move this, netns depends upon it*/
1766 struct list_head *table; 1771 struct list_head *table;
1767 int bucket; 1772 int bucket;
1768}; 1773};
@@ -1789,6 +1794,7 @@ static inline const char *ip_vs_fwd_name(unsigned flags)
1789/* Get the Nth entry in the two lists */ 1794/* Get the Nth entry in the two lists */
1790static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos) 1795static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
1791{ 1796{
1797 struct net *net = seq_file_net(seq);
1792 struct ip_vs_iter *iter = seq->private; 1798 struct ip_vs_iter *iter = seq->private;
1793 int idx; 1799 int idx;
1794 struct ip_vs_service *svc; 1800 struct ip_vs_service *svc;
@@ -1796,7 +1802,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
1796 /* look in hash by protocol */ 1802 /* look in hash by protocol */
1797 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 1803 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
1798 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { 1804 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
1799 if (pos-- == 0){ 1805 if (net_eq(svc->net, net) && pos-- == 0) {
1800 iter->table = ip_vs_svc_table; 1806 iter->table = ip_vs_svc_table;
1801 iter->bucket = idx; 1807 iter->bucket = idx;
1802 return svc; 1808 return svc;
@@ -1807,7 +1813,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
1807 /* keep looking in fwmark */ 1813 /* keep looking in fwmark */
1808 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 1814 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
1809 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { 1815 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
1810 if (pos-- == 0) { 1816 if (net_eq(svc->net, net) && pos-- == 0) {
1811 iter->table = ip_vs_svc_fwm_table; 1817 iter->table = ip_vs_svc_fwm_table;
1812 iter->bucket = idx; 1818 iter->bucket = idx;
1813 return svc; 1819 return svc;
@@ -1961,7 +1967,7 @@ static const struct seq_operations ip_vs_info_seq_ops = {
1961 1967
1962static int ip_vs_info_open(struct inode *inode, struct file *file) 1968static int ip_vs_info_open(struct inode *inode, struct file *file)
1963{ 1969{
1964 return seq_open_private(file, &ip_vs_info_seq_ops, 1970 return seq_open_net(inode, file, &ip_vs_info_seq_ops,
1965 sizeof(struct ip_vs_iter)); 1971 sizeof(struct ip_vs_iter));
1966} 1972}
1967 1973
@@ -2011,7 +2017,7 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v)
2011 2017
2012static int ip_vs_stats_seq_open(struct inode *inode, struct file *file) 2018static int ip_vs_stats_seq_open(struct inode *inode, struct file *file)
2013{ 2019{
2014 return single_open(file, ip_vs_stats_show, NULL); 2020 return single_open_net(inode, file, ip_vs_stats_show);
2015} 2021}
2016 2022
2017static const struct file_operations ip_vs_stats_fops = { 2023static const struct file_operations ip_vs_stats_fops = {
@@ -2113,6 +2119,7 @@ static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
2113static int 2119static int
2114do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) 2120do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2115{ 2121{
2122 struct net *net = sock_net(sk);
2116 int ret; 2123 int ret;
2117 unsigned char arg[MAX_ARG_LEN]; 2124 unsigned char arg[MAX_ARG_LEN];
2118 struct ip_vs_service_user *usvc_compat; 2125 struct ip_vs_service_user *usvc_compat;
@@ -2147,7 +2154,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2147 2154
2148 if (cmd == IP_VS_SO_SET_FLUSH) { 2155 if (cmd == IP_VS_SO_SET_FLUSH) {
2149 /* Flush the virtual service */ 2156 /* Flush the virtual service */
2150 ret = ip_vs_flush(); 2157 ret = ip_vs_flush(net);
2151 goto out_unlock; 2158 goto out_unlock;
2152 } else if (cmd == IP_VS_SO_SET_TIMEOUT) { 2159 } else if (cmd == IP_VS_SO_SET_TIMEOUT) {
2153 /* Set timeout values for (tcp tcpfin udp) */ 2160 /* Set timeout values for (tcp tcpfin udp) */
@@ -2174,7 +2181,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2174 if (cmd == IP_VS_SO_SET_ZERO) { 2181 if (cmd == IP_VS_SO_SET_ZERO) {
2175 /* if no service address is set, zero counters in all */ 2182 /* if no service address is set, zero counters in all */
2176 if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) { 2183 if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) {
2177 ret = ip_vs_zero_all(); 2184 ret = ip_vs_zero_all(net);
2178 goto out_unlock; 2185 goto out_unlock;
2179 } 2186 }
2180 } 2187 }
@@ -2191,10 +2198,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2191 2198
2192 /* Lookup the exact service by <protocol, addr, port> or fwmark */ 2199 /* Lookup the exact service by <protocol, addr, port> or fwmark */
2193 if (usvc.fwmark == 0) 2200 if (usvc.fwmark == 0)
2194 svc = __ip_vs_service_find(usvc.af, usvc.protocol, 2201 svc = __ip_vs_service_find(net, usvc.af, usvc.protocol,
2195 &usvc.addr, usvc.port); 2202 &usvc.addr, usvc.port);
2196 else 2203 else
2197 svc = __ip_vs_svc_fwm_find(usvc.af, usvc.fwmark); 2204 svc = __ip_vs_svc_fwm_find(net, usvc.af, usvc.fwmark);
2198 2205
2199 if (cmd != IP_VS_SO_SET_ADD 2206 if (cmd != IP_VS_SO_SET_ADD
2200 && (svc == NULL || svc->protocol != usvc.protocol)) { 2207 && (svc == NULL || svc->protocol != usvc.protocol)) {
@@ -2207,7 +2214,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2207 if (svc != NULL) 2214 if (svc != NULL)
2208 ret = -EEXIST; 2215 ret = -EEXIST;
2209 else 2216 else
2210 ret = ip_vs_add_service(&usvc, &svc); 2217 ret = ip_vs_add_service(net, &usvc, &svc);
2211 break; 2218 break;
2212 case IP_VS_SO_SET_EDIT: 2219 case IP_VS_SO_SET_EDIT:
2213 ret = ip_vs_edit_service(svc, &usvc); 2220 ret = ip_vs_edit_service(svc, &usvc);
@@ -2267,7 +2274,8 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
2267} 2274}
2268 2275
2269static inline int 2276static inline int
2270__ip_vs_get_service_entries(const struct ip_vs_get_services *get, 2277__ip_vs_get_service_entries(struct net *net,
2278 const struct ip_vs_get_services *get,
2271 struct ip_vs_get_services __user *uptr) 2279 struct ip_vs_get_services __user *uptr)
2272{ 2280{
2273 int idx, count=0; 2281 int idx, count=0;
@@ -2278,7 +2286,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
2278 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 2286 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
2279 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { 2287 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
2280 /* Only expose IPv4 entries to old interface */ 2288 /* Only expose IPv4 entries to old interface */
2281 if (svc->af != AF_INET) 2289 if (svc->af != AF_INET || !net_eq(svc->net, net))
2282 continue; 2290 continue;
2283 2291
2284 if (count >= get->num_services) 2292 if (count >= get->num_services)
@@ -2297,7 +2305,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
2297 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 2305 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
2298 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { 2306 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
2299 /* Only expose IPv4 entries to old interface */ 2307 /* Only expose IPv4 entries to old interface */
2300 if (svc->af != AF_INET) 2308 if (svc->af != AF_INET || !net_eq(svc->net, net))
2301 continue; 2309 continue;
2302 2310
2303 if (count >= get->num_services) 2311 if (count >= get->num_services)
@@ -2317,7 +2325,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
2317} 2325}
2318 2326
2319static inline int 2327static inline int
2320__ip_vs_get_dest_entries(const struct ip_vs_get_dests *get, 2328__ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
2321 struct ip_vs_get_dests __user *uptr) 2329 struct ip_vs_get_dests __user *uptr)
2322{ 2330{
2323 struct ip_vs_service *svc; 2331 struct ip_vs_service *svc;
@@ -2325,9 +2333,9 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
2325 int ret = 0; 2333 int ret = 0;
2326 2334
2327 if (get->fwmark) 2335 if (get->fwmark)
2328 svc = __ip_vs_svc_fwm_find(AF_INET, get->fwmark); 2336 svc = __ip_vs_svc_fwm_find(net, AF_INET, get->fwmark);
2329 else 2337 else
2330 svc = __ip_vs_service_find(AF_INET, get->protocol, &addr, 2338 svc = __ip_vs_service_find(net, AF_INET, get->protocol, &addr,
2331 get->port); 2339 get->port);
2332 2340
2333 if (svc) { 2341 if (svc) {
@@ -2401,7 +2409,9 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2401 unsigned char arg[128]; 2409 unsigned char arg[128];
2402 int ret = 0; 2410 int ret = 0;
2403 unsigned int copylen; 2411 unsigned int copylen;
2412 struct net *net = sock_net(sk);
2404 2413
2414 BUG_ON(!net);
2405 if (!capable(CAP_NET_ADMIN)) 2415 if (!capable(CAP_NET_ADMIN))
2406 return -EPERM; 2416 return -EPERM;
2407 2417
@@ -2463,7 +2473,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2463 ret = -EINVAL; 2473 ret = -EINVAL;
2464 goto out; 2474 goto out;
2465 } 2475 }
2466 ret = __ip_vs_get_service_entries(get, user); 2476 ret = __ip_vs_get_service_entries(net, get, user);
2467 } 2477 }
2468 break; 2478 break;
2469 2479
@@ -2476,10 +2486,11 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2476 entry = (struct ip_vs_service_entry *)arg; 2486 entry = (struct ip_vs_service_entry *)arg;
2477 addr.ip = entry->addr; 2487 addr.ip = entry->addr;
2478 if (entry->fwmark) 2488 if (entry->fwmark)
2479 svc = __ip_vs_svc_fwm_find(AF_INET, entry->fwmark); 2489 svc = __ip_vs_svc_fwm_find(net, AF_INET, entry->fwmark);
2480 else 2490 else
2481 svc = __ip_vs_service_find(AF_INET, entry->protocol, 2491 svc = __ip_vs_service_find(net, AF_INET,
2482 &addr, entry->port); 2492 entry->protocol, &addr,
2493 entry->port);
2483 if (svc) { 2494 if (svc) {
2484 ip_vs_copy_service(entry, svc); 2495 ip_vs_copy_service(entry, svc);
2485 if (copy_to_user(user, entry, sizeof(*entry)) != 0) 2496 if (copy_to_user(user, entry, sizeof(*entry)) != 0)
@@ -2502,7 +2513,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2502 ret = -EINVAL; 2513 ret = -EINVAL;
2503 goto out; 2514 goto out;
2504 } 2515 }
2505 ret = __ip_vs_get_dest_entries(get, user); 2516 ret = __ip_vs_get_dest_entries(net, get, user);
2506 } 2517 }
2507 break; 2518 break;
2508 2519
@@ -2722,11 +2733,12 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
2722 int idx = 0, i; 2733 int idx = 0, i;
2723 int start = cb->args[0]; 2734 int start = cb->args[0];
2724 struct ip_vs_service *svc; 2735 struct ip_vs_service *svc;
2736 struct net *net = skb_sknet(skb);
2725 2737
2726 mutex_lock(&__ip_vs_mutex); 2738 mutex_lock(&__ip_vs_mutex);
2727 for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { 2739 for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) {
2728 list_for_each_entry(svc, &ip_vs_svc_table[i], s_list) { 2740 list_for_each_entry(svc, &ip_vs_svc_table[i], s_list) {
2729 if (++idx <= start) 2741 if (++idx <= start || !net_eq(svc->net, net))
2730 continue; 2742 continue;
2731 if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { 2743 if (ip_vs_genl_dump_service(skb, svc, cb) < 0) {
2732 idx--; 2744 idx--;
@@ -2737,7 +2749,7 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
2737 2749
2738 for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { 2750 for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) {
2739 list_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) { 2751 list_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) {
2740 if (++idx <= start) 2752 if (++idx <= start || !net_eq(svc->net, net))
2741 continue; 2753 continue;
2742 if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { 2754 if (ip_vs_genl_dump_service(skb, svc, cb) < 0) {
2743 idx--; 2755 idx--;
@@ -2753,7 +2765,8 @@ nla_put_failure:
2753 return skb->len; 2765 return skb->len;
2754} 2766}
2755 2767
2756static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc, 2768static int ip_vs_genl_parse_service(struct net *net,
2769 struct ip_vs_service_user_kern *usvc,
2757 struct nlattr *nla, int full_entry, 2770 struct nlattr *nla, int full_entry,
2758 struct ip_vs_service **ret_svc) 2771 struct ip_vs_service **ret_svc)
2759{ 2772{
@@ -2796,9 +2809,9 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
2796 } 2809 }
2797 2810
2798 if (usvc->fwmark) 2811 if (usvc->fwmark)
2799 svc = __ip_vs_svc_fwm_find(usvc->af, usvc->fwmark); 2812 svc = __ip_vs_svc_fwm_find(net, usvc->af, usvc->fwmark);
2800 else 2813 else
2801 svc = __ip_vs_service_find(usvc->af, usvc->protocol, 2814 svc = __ip_vs_service_find(net, usvc->af, usvc->protocol,
2802 &usvc->addr, usvc->port); 2815 &usvc->addr, usvc->port);
2803 *ret_svc = svc; 2816 *ret_svc = svc;
2804 2817
@@ -2835,13 +2848,14 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
2835 return 0; 2848 return 0;
2836} 2849}
2837 2850
2838static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla) 2851static struct ip_vs_service *ip_vs_genl_find_service(struct net *net,
2852 struct nlattr *nla)
2839{ 2853{
2840 struct ip_vs_service_user_kern usvc; 2854 struct ip_vs_service_user_kern usvc;
2841 struct ip_vs_service *svc; 2855 struct ip_vs_service *svc;
2842 int ret; 2856 int ret;
2843 2857
2844 ret = ip_vs_genl_parse_service(&usvc, nla, 0, &svc); 2858 ret = ip_vs_genl_parse_service(net, &usvc, nla, 0, &svc);
2845 return ret ? ERR_PTR(ret) : svc; 2859 return ret ? ERR_PTR(ret) : svc;
2846} 2860}
2847 2861
@@ -2909,6 +2923,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
2909 struct ip_vs_service *svc; 2923 struct ip_vs_service *svc;
2910 struct ip_vs_dest *dest; 2924 struct ip_vs_dest *dest;
2911 struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1]; 2925 struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
2926 struct net *net;
2912 2927
2913 mutex_lock(&__ip_vs_mutex); 2928 mutex_lock(&__ip_vs_mutex);
2914 2929
@@ -2917,7 +2932,8 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
2917 IPVS_CMD_ATTR_MAX, ip_vs_cmd_policy)) 2932 IPVS_CMD_ATTR_MAX, ip_vs_cmd_policy))
2918 goto out_err; 2933 goto out_err;
2919 2934
2920 svc = ip_vs_genl_find_service(attrs[IPVS_CMD_ATTR_SERVICE]); 2935 net = skb_sknet(skb);
2936 svc = ip_vs_genl_find_service(net, attrs[IPVS_CMD_ATTR_SERVICE]);
2921 if (IS_ERR(svc) || svc == NULL) 2937 if (IS_ERR(svc) || svc == NULL)
2922 goto out_err; 2938 goto out_err;
2923 2939
@@ -3102,13 +3118,15 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
3102 struct ip_vs_dest_user_kern udest; 3118 struct ip_vs_dest_user_kern udest;
3103 int ret = 0, cmd; 3119 int ret = 0, cmd;
3104 int need_full_svc = 0, need_full_dest = 0; 3120 int need_full_svc = 0, need_full_dest = 0;
3121 struct net *net;
3105 3122
3123 net = skb_sknet(skb);
3106 cmd = info->genlhdr->cmd; 3124 cmd = info->genlhdr->cmd;
3107 3125
3108 mutex_lock(&__ip_vs_mutex); 3126 mutex_lock(&__ip_vs_mutex);
3109 3127
3110 if (cmd == IPVS_CMD_FLUSH) { 3128 if (cmd == IPVS_CMD_FLUSH) {
3111 ret = ip_vs_flush(); 3129 ret = ip_vs_flush(net);
3112 goto out; 3130 goto out;
3113 } else if (cmd == IPVS_CMD_SET_CONFIG) { 3131 } else if (cmd == IPVS_CMD_SET_CONFIG) {
3114 ret = ip_vs_genl_set_config(info->attrs); 3132 ret = ip_vs_genl_set_config(info->attrs);
@@ -3133,7 +3151,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
3133 goto out; 3151 goto out;
3134 } else if (cmd == IPVS_CMD_ZERO && 3152 } else if (cmd == IPVS_CMD_ZERO &&
3135 !info->attrs[IPVS_CMD_ATTR_SERVICE]) { 3153 !info->attrs[IPVS_CMD_ATTR_SERVICE]) {
3136 ret = ip_vs_zero_all(); 3154 ret = ip_vs_zero_all(net);
3137 goto out; 3155 goto out;
3138 } 3156 }
3139 3157
@@ -3143,7 +3161,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
3143 if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE) 3161 if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE)
3144 need_full_svc = 1; 3162 need_full_svc = 1;
3145 3163
3146 ret = ip_vs_genl_parse_service(&usvc, 3164 ret = ip_vs_genl_parse_service(net, &usvc,
3147 info->attrs[IPVS_CMD_ATTR_SERVICE], 3165 info->attrs[IPVS_CMD_ATTR_SERVICE],
3148 need_full_svc, &svc); 3166 need_full_svc, &svc);
3149 if (ret) 3167 if (ret)
@@ -3173,7 +3191,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
3173 switch (cmd) { 3191 switch (cmd) {
3174 case IPVS_CMD_NEW_SERVICE: 3192 case IPVS_CMD_NEW_SERVICE:
3175 if (svc == NULL) 3193 if (svc == NULL)
3176 ret = ip_vs_add_service(&usvc, &svc); 3194 ret = ip_vs_add_service(net, &usvc, &svc);
3177 else 3195 else
3178 ret = -EEXIST; 3196 ret = -EEXIST;
3179 break; 3197 break;
@@ -3211,7 +3229,9 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
3211 struct sk_buff *msg; 3229 struct sk_buff *msg;
3212 void *reply; 3230 void *reply;
3213 int ret, cmd, reply_cmd; 3231 int ret, cmd, reply_cmd;
3232 struct net *net;
3214 3233
3234 net = skb_sknet(skb);
3215 cmd = info->genlhdr->cmd; 3235 cmd = info->genlhdr->cmd;
3216 3236
3217 if (cmd == IPVS_CMD_GET_SERVICE) 3237 if (cmd == IPVS_CMD_GET_SERVICE)
@@ -3240,7 +3260,8 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
3240 { 3260 {
3241 struct ip_vs_service *svc; 3261 struct ip_vs_service *svc;
3242 3262
3243 svc = ip_vs_genl_find_service(info->attrs[IPVS_CMD_ATTR_SERVICE]); 3263 svc = ip_vs_genl_find_service(net,
3264 info->attrs[IPVS_CMD_ATTR_SERVICE]);
3244 if (IS_ERR(svc)) { 3265 if (IS_ERR(svc)) {
3245 ret = PTR_ERR(svc); 3266 ret = PTR_ERR(svc);
3246 goto out_err; 3267 goto out_err;
@@ -3411,9 +3432,15 @@ static void ip_vs_genl_unregister(void)
3411 */ 3432 */
3412int __net_init __ip_vs_control_init(struct net *net) 3433int __net_init __ip_vs_control_init(struct net *net)
3413{ 3434{
3435 int idx;
3436 struct netns_ipvs *ipvs = net_ipvs(net);
3437
3414 if (!net_eq(net, &init_net)) /* netns not enabled yet */ 3438 if (!net_eq(net, &init_net)) /* netns not enabled yet */
3415 return -EPERM; 3439 return -EPERM;
3416 3440
3441 for (idx = 0; idx < IP_VS_RTAB_SIZE; idx++)
3442 INIT_LIST_HEAD(&ipvs->rs_table[idx]);
3443
3417 proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops); 3444 proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops);
3418 proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops); 3445 proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops);
3419 sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path, 3446 sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path,
@@ -3445,43 +3472,48 @@ static struct pernet_operations ipvs_control_ops = {
3445 3472
3446int __init ip_vs_control_init(void) 3473int __init ip_vs_control_init(void)
3447{ 3474{
3448 int ret;
3449 int idx; 3475 int idx;
3476 int ret;
3450 3477
3451 EnterFunction(2); 3478 EnterFunction(2);
3452 3479
3453 /* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */ 3480 /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
3454 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 3481 for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
3455 INIT_LIST_HEAD(&ip_vs_svc_table[idx]); 3482 INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
3456 INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); 3483 INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
3457 } 3484 }
3458 for(idx = 0; idx < IP_VS_RTAB_SIZE; idx++) { 3485
3459 INIT_LIST_HEAD(&ip_vs_rtable[idx]); 3486 ret = register_pernet_subsys(&ipvs_control_ops);
3487 if (ret) {
3488 pr_err("cannot register namespace.\n");
3489 goto err;
3460 } 3490 }
3461 smp_wmb(); 3491
3492 smp_wmb(); /* Do we really need it now ? */
3462 3493
3463 ret = nf_register_sockopt(&ip_vs_sockopts); 3494 ret = nf_register_sockopt(&ip_vs_sockopts);
3464 if (ret) { 3495 if (ret) {
3465 pr_err("cannot register sockopt.\n"); 3496 pr_err("cannot register sockopt.\n");
3466 return ret; 3497 goto err_net;
3467 } 3498 }
3468 3499
3469 ret = ip_vs_genl_register(); 3500 ret = ip_vs_genl_register();
3470 if (ret) { 3501 if (ret) {
3471 pr_err("cannot register Generic Netlink interface.\n"); 3502 pr_err("cannot register Generic Netlink interface.\n");
3472 nf_unregister_sockopt(&ip_vs_sockopts); 3503 nf_unregister_sockopt(&ip_vs_sockopts);
3473 return ret; 3504 goto err_net;
3474 } 3505 }
3475 3506
3476 ret = register_pernet_subsys(&ipvs_control_ops);
3477 if (ret)
3478 return ret;
3479
3480 /* Hook the defense timer */ 3507 /* Hook the defense timer */
3481 schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD); 3508 schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
3482 3509
3483 LeaveFunction(2); 3510 LeaveFunction(2);
3484 return 0; 3511 return 0;
3512
3513err_net:
3514 unregister_pernet_subsys(&ipvs_control_ops);
3515err:
3516 return ret;
3485} 3517}
3486 3518
3487 3519
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index a315159983a..521b827083f 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -12,6 +12,7 @@ static int
12sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, 12sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
13 int *verdict, struct ip_vs_conn **cpp) 13 int *verdict, struct ip_vs_conn **cpp)
14{ 14{
15 struct net *net;
15 struct ip_vs_service *svc; 16 struct ip_vs_service *svc;
16 sctp_chunkhdr_t _schunkh, *sch; 17 sctp_chunkhdr_t _schunkh, *sch;
17 sctp_sctphdr_t *sh, _sctph; 18 sctp_sctphdr_t *sh, _sctph;
@@ -27,9 +28,9 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
27 sizeof(_schunkh), &_schunkh); 28 sizeof(_schunkh), &_schunkh);
28 if (sch == NULL) 29 if (sch == NULL)
29 return 0; 30 return 0;
30 31 net = skb_net(skb);
31 if ((sch->type == SCTP_CID_INIT) && 32 if ((sch->type == SCTP_CID_INIT) &&
32 (svc = ip_vs_service_get(af, skb->mark, iph.protocol, 33 (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
33 &iph.daddr, sh->dest))) { 34 &iph.daddr, sh->dest))) {
34 int ignored; 35 int ignored;
35 36
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 1cdab12abfe..c175d316626 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -31,6 +31,7 @@ static int
31tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, 31tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
32 int *verdict, struct ip_vs_conn **cpp) 32 int *verdict, struct ip_vs_conn **cpp)
33{ 33{
34 struct net *net;
34 struct ip_vs_service *svc; 35 struct ip_vs_service *svc;
35 struct tcphdr _tcph, *th; 36 struct tcphdr _tcph, *th;
36 struct ip_vs_iphdr iph; 37 struct ip_vs_iphdr iph;
@@ -42,11 +43,11 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
42 *verdict = NF_DROP; 43 *verdict = NF_DROP;
43 return 0; 44 return 0;
44 } 45 }
45 46 net = skb_net(skb);
46 /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ 47 /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
47 if (th->syn && 48 if (th->syn &&
48 (svc = ip_vs_service_get(af, skb->mark, iph.protocol, &iph.daddr, 49 (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
49 th->dest))) { 50 &iph.daddr, th->dest))) {
50 int ignored; 51 int ignored;
51 52
52 if (ip_vs_todrop()) { 53 if (ip_vs_todrop()) {
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index cd398de010c..5ab54f64865 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -31,6 +31,7 @@ static int
31udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, 31udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
32 int *verdict, struct ip_vs_conn **cpp) 32 int *verdict, struct ip_vs_conn **cpp)
33{ 33{
34 struct net *net;
34 struct ip_vs_service *svc; 35 struct ip_vs_service *svc;
35 struct udphdr _udph, *uh; 36 struct udphdr _udph, *uh;
36 struct ip_vs_iphdr iph; 37 struct ip_vs_iphdr iph;
@@ -42,8 +43,8 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
42 *verdict = NF_DROP; 43 *verdict = NF_DROP;
43 return 0; 44 return 0;
44 } 45 }
45 46 net = skb_net(skb);
46 svc = ip_vs_service_get(af, skb->mark, iph.protocol, 47 svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
47 &iph.daddr, uh->dest); 48 &iph.daddr, uh->dest);
48 if (svc) { 49 if (svc) {
49 int ignored; 50 int ignored;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 3668739a6d0..662aa2c22a0 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -749,7 +749,7 @@ static void ip_vs_proc_conn(struct ip_vs_conn_param *param, unsigned flags,
749 * If it is not found the connection will remain unbound 749 * If it is not found the connection will remain unbound
750 * but still handled. 750 * but still handled.
751 */ 751 */
752 dest = ip_vs_find_dest(type, daddr, dport, param->vaddr, 752 dest = ip_vs_find_dest(&init_net, type, daddr, dport, param->vaddr,
753 param->vport, protocol, fwmark); 753 param->vport, protocol, fwmark);
754 754
755 /* Set the approprite ativity flag */ 755 /* Set the approprite ativity flag */