diff options
-rw-r--r-- | include/net/netns/ip_vs.h | 8 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto.c | 3 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_udp.c | 86 |
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 | |||
358 | static struct list_head udp_apps[UDP_APP_TAB_SIZE]; | ||
359 | static DEFINE_SPINLOCK(udp_app_lock); | ||
360 | |||
361 | static inline __u16 udp_app_hashkey(__be16 port) | 349 | static 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) | |||
394 | static void | 384 | static void |
395 | udp_unregister_app(struct ip_vs_app *inc) | 385 | udp_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 | ||
404 | static int udp_app_conn_bind(struct ip_vs_conn *cp) | 397 | static 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 | ||
446 | static int udp_timeouts[IP_VS_UDP_S_LAST+1] = { | 440 | static 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 | |||
457 | static int | ||
458 | udp_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 | |||
464 | static const char * udp_state_name(int state) | 450 | static 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 | ||
480 | static void udp_init(struct ip_vs_protocol *pp) | 474 | static 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 | ||
486 | static void udp_exit(struct ip_vs_protocol *pp) | 484 | static 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 | }; |