aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netns/ip_vs.h8
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c86
3 files changed, 54 insertions, 43 deletions
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h
index ac77363647ab..62b1448d3795 100644
--- a/include/net/netns/ip_vs.h
+++ b/include/net/netns/ip_vs.h
@@ -39,6 +39,14 @@ struct netns_ipvs {
39 struct list_head tcp_apps[TCP_APP_TAB_SIZE]; 39 struct list_head tcp_apps[TCP_APP_TAB_SIZE];
40 spinlock_t tcp_app_lock; 40 spinlock_t tcp_app_lock;
41#endif 41#endif
42 /* ip_vs_proto_udp */
43#ifdef CONFIG_IP_VS_PROTO_UDP
44 #define UDP_APP_TAB_BITS 4
45 #define UDP_APP_TAB_SIZE (1 << UDP_APP_TAB_BITS)
46 #define UDP_APP_TAB_MASK (UDP_APP_TAB_SIZE - 1)
47 struct list_head udp_apps[UDP_APP_TAB_SIZE];
48 spinlock_t udp_app_lock;
49#endif
42 50
43 /* ip_vs_lblc */ 51 /* ip_vs_lblc */
44 int sysctl_lblc_expiration; 52 int sysctl_lblc_expiration;
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 320c6a65f370..cdc414238fcb 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -310,6 +310,9 @@ static int __net_init __ip_vs_protocol_init(struct net *net)
310#ifdef CONFIG_IP_VS_PROTO_TCP 310#ifdef CONFIG_IP_VS_PROTO_TCP
311 register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); 311 register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
312#endif 312#endif
313#ifdef CONFIG_IP_VS_PROTO_UDP
314 register_ip_vs_proto_netns(net, &ip_vs_protocol_udp);
315#endif
313 return 0; 316 return 0;
314} 317}
315 318
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index 5ab54f648654..71a4721a8f8a 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -9,7 +9,8 @@
9 * as published by the Free Software Foundation; either version 9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 * 11 *
12 * Changes: 12 * Changes: Hans Schillstrom <hans.schillstrom@ericsson.com>
13 * Network name space (netns) aware.
13 * 14 *
14 */ 15 */
15 16
@@ -345,19 +346,6 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
345 return 1; 346 return 1;
346} 347}
347 348
348
349/*
350 * Note: the caller guarantees that only one of register_app,
351 * unregister_app or app_conn_bind is called each time.
352 */
353
354#define UDP_APP_TAB_BITS 4
355#define UDP_APP_TAB_SIZE (1 << UDP_APP_TAB_BITS)
356#define UDP_APP_TAB_MASK (UDP_APP_TAB_SIZE - 1)
357
358static struct list_head udp_apps[UDP_APP_TAB_SIZE];
359static DEFINE_SPINLOCK(udp_app_lock);
360
361static inline __u16 udp_app_hashkey(__be16 port) 349static inline __u16 udp_app_hashkey(__be16 port)
362{ 350{
363 return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port) 351 return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port)
@@ -371,22 +359,24 @@ static int udp_register_app(struct ip_vs_app *inc)
371 __u16 hash; 359 __u16 hash;
372 __be16 port = inc->port; 360 __be16 port = inc->port;
373 int ret = 0; 361 int ret = 0;
362 struct netns_ipvs *ipvs = net_ipvs(&init_net);
363 struct ip_vs_proto_data *pd = ip_vs_proto_data_get(&init_net, IPPROTO_UDP);
374 364
375 hash = udp_app_hashkey(port); 365 hash = udp_app_hashkey(port);
376 366
377 367
378 spin_lock_bh(&udp_app_lock); 368 spin_lock_bh(&ipvs->udp_app_lock);
379 list_for_each_entry(i, &udp_apps[hash], p_list) { 369 list_for_each_entry(i, &ipvs->udp_apps[hash], p_list) {
380 if (i->port == port) { 370 if (i->port == port) {
381 ret = -EEXIST; 371 ret = -EEXIST;
382 goto out; 372 goto out;
383 } 373 }
384 } 374 }
385 list_add(&inc->p_list, &udp_apps[hash]); 375 list_add(&inc->p_list, &ipvs->udp_apps[hash]);
386 atomic_inc(&ip_vs_protocol_udp.appcnt); 376 atomic_inc(&pd->pp->appcnt);
387 377
388 out: 378 out:
389 spin_unlock_bh(&udp_app_lock); 379 spin_unlock_bh(&ipvs->udp_app_lock);
390 return ret; 380 return ret;
391} 381}
392 382
@@ -394,15 +384,19 @@ static int udp_register_app(struct ip_vs_app *inc)
394static void 384static void
395udp_unregister_app(struct ip_vs_app *inc) 385udp_unregister_app(struct ip_vs_app *inc)
396{ 386{
397 spin_lock_bh(&udp_app_lock); 387 struct ip_vs_proto_data *pd = ip_vs_proto_data_get(&init_net, IPPROTO_UDP);
398 atomic_dec(&ip_vs_protocol_udp.appcnt); 388 struct netns_ipvs *ipvs = net_ipvs(&init_net);
389
390 spin_lock_bh(&ipvs->udp_app_lock);
391 atomic_dec(&pd->pp->appcnt);
399 list_del(&inc->p_list); 392 list_del(&inc->p_list);
400 spin_unlock_bh(&udp_app_lock); 393 spin_unlock_bh(&ipvs->udp_app_lock);
401} 394}
402 395
403 396
404static int udp_app_conn_bind(struct ip_vs_conn *cp) 397static int udp_app_conn_bind(struct ip_vs_conn *cp)
405{ 398{
399 struct netns_ipvs *ipvs = net_ipvs(&init_net);
406 int hash; 400 int hash;
407 struct ip_vs_app *inc; 401 struct ip_vs_app *inc;
408 int result = 0; 402 int result = 0;
@@ -414,12 +408,12 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
414 /* Lookup application incarnations and bind the right one */ 408 /* Lookup application incarnations and bind the right one */
415 hash = udp_app_hashkey(cp->vport); 409 hash = udp_app_hashkey(cp->vport);
416 410
417 spin_lock(&udp_app_lock); 411 spin_lock(&ipvs->udp_app_lock);
418 list_for_each_entry(inc, &udp_apps[hash], p_list) { 412 list_for_each_entry(inc, &ipvs->udp_apps[hash], p_list) {
419 if (inc->port == cp->vport) { 413 if (inc->port == cp->vport) {
420 if (unlikely(!ip_vs_app_inc_get(inc))) 414 if (unlikely(!ip_vs_app_inc_get(inc)))
421 break; 415 break;
422 spin_unlock(&udp_app_lock); 416 spin_unlock(&ipvs->udp_app_lock);
423 417
424 IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->" 418 IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->"
425 "%s:%u to app %s on port %u\n", 419 "%s:%u to app %s on port %u\n",
@@ -436,14 +430,14 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
436 goto out; 430 goto out;
437 } 431 }
438 } 432 }
439 spin_unlock(&udp_app_lock); 433 spin_unlock(&ipvs->udp_app_lock);
440 434
441 out: 435 out:
442 return result; 436 return result;
443} 437}
444 438
445 439
446static int udp_timeouts[IP_VS_UDP_S_LAST+1] = { 440static const int udp_timeouts[IP_VS_UDP_S_LAST+1] = {
447 [IP_VS_UDP_S_NORMAL] = 5*60*HZ, 441 [IP_VS_UDP_S_NORMAL] = 5*60*HZ,
448 [IP_VS_UDP_S_LAST] = 2*HZ, 442 [IP_VS_UDP_S_LAST] = 2*HZ,
449}; 443};
@@ -453,14 +447,6 @@ static const char *const udp_state_name_table[IP_VS_UDP_S_LAST+1] = {
453 [IP_VS_UDP_S_LAST] = "BUG!", 447 [IP_VS_UDP_S_LAST] = "BUG!",
454}; 448};
455 449
456
457static int
458udp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
459{
460 return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_UDP_S_LAST,
461 udp_state_name_table, sname, to);
462}
463
464static const char * udp_state_name(int state) 450static const char * udp_state_name(int state)
465{ 451{
466 if (state >= IP_VS_UDP_S_LAST) 452 if (state >= IP_VS_UDP_S_LAST)
@@ -473,18 +459,31 @@ udp_state_transition(struct ip_vs_conn *cp, int direction,
473 const struct sk_buff *skb, 459 const struct sk_buff *skb,
474 struct ip_vs_protocol *pp) 460 struct ip_vs_protocol *pp)
475{ 461{
476 cp->timeout = pp->timeout_table[IP_VS_UDP_S_NORMAL]; 462 struct ip_vs_proto_data *pd; /* Temp fix, pp will be replaced by pd */
463
464 pd = ip_vs_proto_data_get(&init_net, IPPROTO_UDP);
465 if (unlikely(!pd)) {
466 pr_err("UDP no ns data\n");
467 return 0;
468 }
469
470 cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
477 return 1; 471 return 1;
478} 472}
479 473
480static void udp_init(struct ip_vs_protocol *pp) 474static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
481{ 475{
482 IP_VS_INIT_HASH_TABLE(udp_apps); 476 struct netns_ipvs *ipvs = net_ipvs(net);
483 pp->timeout_table = udp_timeouts; 477
478 ip_vs_init_hash_table(ipvs->udp_apps, UDP_APP_TAB_SIZE);
479 spin_lock_init(&ipvs->udp_app_lock);
480 pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
481 sizeof(udp_timeouts));
484} 482}
485 483
486static void udp_exit(struct ip_vs_protocol *pp) 484static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
487{ 485{
486 kfree(pd->timeout_table);
488} 487}
489 488
490 489
@@ -493,8 +492,10 @@ struct ip_vs_protocol ip_vs_protocol_udp = {
493 .protocol = IPPROTO_UDP, 492 .protocol = IPPROTO_UDP,
494 .num_states = IP_VS_UDP_S_LAST, 493 .num_states = IP_VS_UDP_S_LAST,
495 .dont_defrag = 0, 494 .dont_defrag = 0,
496 .init = udp_init, 495 .init = NULL,
497 .exit = udp_exit, 496 .exit = NULL,
497 .init_netns = __udp_init,
498 .exit_netns = __udp_exit,
498 .conn_schedule = udp_conn_schedule, 499 .conn_schedule = udp_conn_schedule,
499 .conn_in_get = ip_vs_conn_in_get_proto, 500 .conn_in_get = ip_vs_conn_in_get_proto,
500 .conn_out_get = ip_vs_conn_out_get_proto, 501 .conn_out_get = ip_vs_conn_out_get_proto,
@@ -508,5 +509,4 @@ struct ip_vs_protocol ip_vs_protocol_udp = {
508 .app_conn_bind = udp_app_conn_bind, 509 .app_conn_bind = udp_app_conn_bind,
509 .debug_packet = ip_vs_tcpudp_debug_packet, 510 .debug_packet = ip_vs_tcpudp_debug_packet,
510 .timeout_change = NULL, 511 .timeout_change = NULL,
511 .set_state_timeout = udp_set_state_timeout,
512}; 512};