~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/netfilter/ipvs/ip_vs_proto_udp.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 *              as published by the Free Software Foundation; either version
10
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
 
28
29
#include <net/ip6_checksum.h>
29
30
 
30
31
static int
31
 
udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 
32
udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
32
33
                  int *verdict, struct ip_vs_conn **cpp)
33
34
{
 
35
        struct net *net;
34
36
        struct ip_vs_service *svc;
35
37
        struct udphdr _udph, *uh;
36
38
        struct ip_vs_iphdr iph;
42
44
                *verdict = NF_DROP;
43
45
                return 0;
44
46
        }
45
 
 
46
 
        svc = ip_vs_service_get(af, skb->mark, iph.protocol,
 
47
        net = skb_net(skb);
 
48
        svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
47
49
                                &iph.daddr, uh->dest);
48
50
        if (svc) {
49
51
                int ignored;
50
52
 
51
 
                if (ip_vs_todrop()) {
 
53
                if (ip_vs_todrop(net_ipvs(net))) {
52
54
                        /*
53
55
                         * It seems that we are very loaded.
54
56
                         * We have to drop this packet :(
62
64
                 * Let the virtual server select a real server for the
63
65
                 * incoming connection, and create a connection entry.
64
66
                 */
65
 
                *cpp = ip_vs_schedule(svc, skb, pp, &ignored);
66
 
                if (!*cpp && !ignored) {
67
 
                        *verdict = ip_vs_leave(svc, skb, pp);
 
67
                *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
 
68
                if (!*cpp && ignored <= 0) {
 
69
                        if (!ignored)
 
70
                                *verdict = ip_vs_leave(svc, skb, pd);
 
71
                        else {
 
72
                                ip_vs_service_put(svc);
 
73
                                *verdict = NF_DROP;
 
74
                        }
68
75
                        return 0;
69
76
                }
70
77
                ip_vs_service_put(svc);
71
78
        }
 
79
        /* NF_ACCEPT */
72
80
        return 1;
73
81
}
74
82
 
338
346
        return 1;
339
347
}
340
348
 
341
 
 
342
 
/*
343
 
 *      Note: the caller guarantees that only one of register_app,
344
 
 *      unregister_app or app_conn_bind is called each time.
345
 
 */
346
 
 
347
 
#define UDP_APP_TAB_BITS        4
348
 
#define UDP_APP_TAB_SIZE        (1 << UDP_APP_TAB_BITS)
349
 
#define UDP_APP_TAB_MASK        (UDP_APP_TAB_SIZE - 1)
350
 
 
351
 
static struct list_head udp_apps[UDP_APP_TAB_SIZE];
352
 
static DEFINE_SPINLOCK(udp_app_lock);
353
 
 
354
349
static inline __u16 udp_app_hashkey(__be16 port)
355
350
{
356
351
        return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port)
358
353
}
359
354
 
360
355
 
361
 
static int udp_register_app(struct ip_vs_app *inc)
 
356
static int udp_register_app(struct net *net, struct ip_vs_app *inc)
362
357
{
363
358
        struct ip_vs_app *i;
364
359
        __u16 hash;
365
360
        __be16 port = inc->port;
366
361
        int ret = 0;
 
362
        struct netns_ipvs *ipvs = net_ipvs(net);
 
363
        struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
367
364
 
368
365
        hash = udp_app_hashkey(port);
369
366
 
370
367
 
371
 
        spin_lock_bh(&udp_app_lock);
372
 
        list_for_each_entry(i, &udp_apps[hash], p_list) {
 
368
        spin_lock_bh(&ipvs->udp_app_lock);
 
369
        list_for_each_entry(i, &ipvs->udp_apps[hash], p_list) {
373
370
                if (i->port == port) {
374
371
                        ret = -EEXIST;
375
372
                        goto out;
376
373
                }
377
374
        }
378
 
        list_add(&inc->p_list, &udp_apps[hash]);
379
 
        atomic_inc(&ip_vs_protocol_udp.appcnt);
 
375
        list_add(&inc->p_list, &ipvs->udp_apps[hash]);
 
376
        atomic_inc(&pd->appcnt);
380
377
 
381
378
  out:
382
 
        spin_unlock_bh(&udp_app_lock);
 
379
        spin_unlock_bh(&ipvs->udp_app_lock);
383
380
        return ret;
384
381
}
385
382
 
386
383
 
387
384
static void
388
 
udp_unregister_app(struct ip_vs_app *inc)
 
385
udp_unregister_app(struct net *net, struct ip_vs_app *inc)
389
386
{
390
 
        spin_lock_bh(&udp_app_lock);
391
 
        atomic_dec(&ip_vs_protocol_udp.appcnt);
 
387
        struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
 
388
        struct netns_ipvs *ipvs = net_ipvs(net);
 
389
 
 
390
        spin_lock_bh(&ipvs->udp_app_lock);
 
391
        atomic_dec(&pd->appcnt);
392
392
        list_del(&inc->p_list);
393
 
        spin_unlock_bh(&udp_app_lock);
 
393
        spin_unlock_bh(&ipvs->udp_app_lock);
394
394
}
395
395
 
396
396
 
397
397
static int udp_app_conn_bind(struct ip_vs_conn *cp)
398
398
{
 
399
        struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
399
400
        int hash;
400
401
        struct ip_vs_app *inc;
401
402
        int result = 0;
407
408
        /* Lookup application incarnations and bind the right one */
408
409
        hash = udp_app_hashkey(cp->vport);
409
410
 
410
 
        spin_lock(&udp_app_lock);
411
 
        list_for_each_entry(inc, &udp_apps[hash], p_list) {
 
411
        spin_lock(&ipvs->udp_app_lock);
 
412
        list_for_each_entry(inc, &ipvs->udp_apps[hash], p_list) {
412
413
                if (inc->port == cp->vport) {
413
414
                        if (unlikely(!ip_vs_app_inc_get(inc)))
414
415
                                break;
415
 
                        spin_unlock(&udp_app_lock);
 
416
                        spin_unlock(&ipvs->udp_app_lock);
416
417
 
417
418
                        IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->"
418
419
                                      "%s:%u to app %s on port %u\n",
429
430
                        goto out;
430
431
                }
431
432
        }
432
 
        spin_unlock(&udp_app_lock);
 
433
        spin_unlock(&ipvs->udp_app_lock);
433
434
 
434
435
  out:
435
436
        return result;
436
437
}
437
438
 
438
439
 
439
 
static int udp_timeouts[IP_VS_UDP_S_LAST+1] = {
 
440
static const int udp_timeouts[IP_VS_UDP_S_LAST+1] = {
440
441
        [IP_VS_UDP_S_NORMAL]            =       5*60*HZ,
441
442
        [IP_VS_UDP_S_LAST]              =       2*HZ,
442
443
};
446
447
        [IP_VS_UDP_S_LAST]              =       "BUG!",
447
448
};
448
449
 
449
 
 
450
 
static int
451
 
udp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
452
 
{
453
 
        return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_UDP_S_LAST,
454
 
                                       udp_state_name_table, sname, to);
455
 
}
456
 
 
457
450
static const char * udp_state_name(int state)
458
451
{
459
452
        if (state >= IP_VS_UDP_S_LAST)
464
457
static int
465
458
udp_state_transition(struct ip_vs_conn *cp, int direction,
466
459
                     const struct sk_buff *skb,
467
 
                     struct ip_vs_protocol *pp)
 
460
                     struct ip_vs_proto_data *pd)
468
461
{
469
 
        cp->timeout = pp->timeout_table[IP_VS_UDP_S_NORMAL];
 
462
        if (unlikely(!pd)) {
 
463
                pr_err("UDP no ns data\n");
 
464
                return 0;
 
465
        }
 
466
 
 
467
        cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
470
468
        return 1;
471
469
}
472
470
 
473
 
static void udp_init(struct ip_vs_protocol *pp)
 
471
static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
474
472
{
475
 
        IP_VS_INIT_HASH_TABLE(udp_apps);
476
 
        pp->timeout_table = udp_timeouts;
 
473
        struct netns_ipvs *ipvs = net_ipvs(net);
 
474
 
 
475
        ip_vs_init_hash_table(ipvs->udp_apps, UDP_APP_TAB_SIZE);
 
476
        spin_lock_init(&ipvs->udp_app_lock);
 
477
        pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
 
478
                                                        sizeof(udp_timeouts));
477
479
}
478
480
 
479
 
static void udp_exit(struct ip_vs_protocol *pp)
 
481
static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
480
482
{
 
483
        kfree(pd->timeout_table);
481
484
}
482
485
 
483
486
 
486
489
        .protocol =             IPPROTO_UDP,
487
490
        .num_states =           IP_VS_UDP_S_LAST,
488
491
        .dont_defrag =          0,
489
 
        .init =                 udp_init,
490
 
        .exit =                 udp_exit,
 
492
        .init =                 NULL,
 
493
        .exit =                 NULL,
 
494
        .init_netns =           __udp_init,
 
495
        .exit_netns =           __udp_exit,
491
496
        .conn_schedule =        udp_conn_schedule,
492
497
        .conn_in_get =          ip_vs_conn_in_get_proto,
493
498
        .conn_out_get =         ip_vs_conn_out_get_proto,
501
506
        .app_conn_bind =        udp_app_conn_bind,
502
507
        .debug_packet =         ip_vs_tcpudp_debug_packet,
503
508
        .timeout_change =       NULL,
504
 
        .set_state_timeout =    udp_set_state_timeout,
505
509
};