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

« back to all changes in this revision

Viewing changes to net/netfilter/ipvs/ip_vs_core.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:
41
41
#include <net/icmp.h>                   /* for icmp_send */
42
42
#include <net/route.h>
43
43
#include <net/ip6_checksum.h>
 
44
#include <net/netns/generic.h>          /* net_generic() */
44
45
 
45
46
#include <linux/netfilter.h>
46
47
#include <linux/netfilter_ipv4.h>
68
69
EXPORT_SYMBOL(ip_vs_get_debug_level);
69
70
#endif
70
71
 
 
72
int ip_vs_net_id __read_mostly;
 
73
#ifdef IP_VS_GENERIC_NETNS
 
74
EXPORT_SYMBOL(ip_vs_net_id);
 
75
#endif
 
76
/* netns cnt used for uniqueness */
 
77
static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);
71
78
 
72
79
/* ID used in ICMP lookups */
73
80
#define icmp_id(icmph)          (((icmph)->un).echo.id)
108
115
ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
109
116
{
110
117
        struct ip_vs_dest *dest = cp->dest;
 
118
        struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
 
119
 
111
120
        if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
112
 
                spin_lock(&dest->stats.lock);
113
 
                dest->stats.ustats.inpkts++;
114
 
                dest->stats.ustats.inbytes += skb->len;
115
 
                spin_unlock(&dest->stats.lock);
116
 
 
117
 
                spin_lock(&dest->svc->stats.lock);
118
 
                dest->svc->stats.ustats.inpkts++;
119
 
                dest->svc->stats.ustats.inbytes += skb->len;
120
 
                spin_unlock(&dest->svc->stats.lock);
121
 
 
122
 
                spin_lock(&ip_vs_stats.lock);
123
 
                ip_vs_stats.ustats.inpkts++;
124
 
                ip_vs_stats.ustats.inbytes += skb->len;
125
 
                spin_unlock(&ip_vs_stats.lock);
 
121
                struct ip_vs_cpu_stats *s;
 
122
 
 
123
                s = this_cpu_ptr(dest->stats.cpustats);
 
124
                s->ustats.inpkts++;
 
125
                u64_stats_update_begin(&s->syncp);
 
126
                s->ustats.inbytes += skb->len;
 
127
                u64_stats_update_end(&s->syncp);
 
128
 
 
129
                s = this_cpu_ptr(dest->svc->stats.cpustats);
 
130
                s->ustats.inpkts++;
 
131
                u64_stats_update_begin(&s->syncp);
 
132
                s->ustats.inbytes += skb->len;
 
133
                u64_stats_update_end(&s->syncp);
 
134
 
 
135
                s = this_cpu_ptr(ipvs->tot_stats.cpustats);
 
136
                s->ustats.inpkts++;
 
137
                u64_stats_update_begin(&s->syncp);
 
138
                s->ustats.inbytes += skb->len;
 
139
                u64_stats_update_end(&s->syncp);
126
140
        }
127
141
}
128
142
 
131
145
ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
132
146
{
133
147
        struct ip_vs_dest *dest = cp->dest;
 
148
        struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
 
149
 
134
150
        if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
135
 
                spin_lock(&dest->stats.lock);
136
 
                dest->stats.ustats.outpkts++;
137
 
                dest->stats.ustats.outbytes += skb->len;
138
 
                spin_unlock(&dest->stats.lock);
139
 
 
140
 
                spin_lock(&dest->svc->stats.lock);
141
 
                dest->svc->stats.ustats.outpkts++;
142
 
                dest->svc->stats.ustats.outbytes += skb->len;
143
 
                spin_unlock(&dest->svc->stats.lock);
144
 
 
145
 
                spin_lock(&ip_vs_stats.lock);
146
 
                ip_vs_stats.ustats.outpkts++;
147
 
                ip_vs_stats.ustats.outbytes += skb->len;
148
 
                spin_unlock(&ip_vs_stats.lock);
 
151
                struct ip_vs_cpu_stats *s;
 
152
 
 
153
                s = this_cpu_ptr(dest->stats.cpustats);
 
154
                s->ustats.outpkts++;
 
155
                u64_stats_update_begin(&s->syncp);
 
156
                s->ustats.outbytes += skb->len;
 
157
                u64_stats_update_end(&s->syncp);
 
158
 
 
159
                s = this_cpu_ptr(dest->svc->stats.cpustats);
 
160
                s->ustats.outpkts++;
 
161
                u64_stats_update_begin(&s->syncp);
 
162
                s->ustats.outbytes += skb->len;
 
163
                u64_stats_update_end(&s->syncp);
 
164
 
 
165
                s = this_cpu_ptr(ipvs->tot_stats.cpustats);
 
166
                s->ustats.outpkts++;
 
167
                u64_stats_update_begin(&s->syncp);
 
168
                s->ustats.outbytes += skb->len;
 
169
                u64_stats_update_end(&s->syncp);
149
170
        }
150
171
}
151
172
 
153
174
static inline void
154
175
ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
155
176
{
156
 
        spin_lock(&cp->dest->stats.lock);
157
 
        cp->dest->stats.ustats.conns++;
158
 
        spin_unlock(&cp->dest->stats.lock);
159
 
 
160
 
        spin_lock(&svc->stats.lock);
161
 
        svc->stats.ustats.conns++;
162
 
        spin_unlock(&svc->stats.lock);
163
 
 
164
 
        spin_lock(&ip_vs_stats.lock);
165
 
        ip_vs_stats.ustats.conns++;
166
 
        spin_unlock(&ip_vs_stats.lock);
 
177
        struct netns_ipvs *ipvs = net_ipvs(svc->net);
 
178
        struct ip_vs_cpu_stats *s;
 
179
 
 
180
        s = this_cpu_ptr(cp->dest->stats.cpustats);
 
181
        s->ustats.conns++;
 
182
 
 
183
        s = this_cpu_ptr(svc->stats.cpustats);
 
184
        s->ustats.conns++;
 
185
 
 
186
        s = this_cpu_ptr(ipvs->tot_stats.cpustats);
 
187
        s->ustats.conns++;
167
188
}
168
189
 
169
190
 
170
191
static inline int
171
192
ip_vs_set_state(struct ip_vs_conn *cp, int direction,
172
193
                const struct sk_buff *skb,
173
 
                struct ip_vs_protocol *pp)
 
194
                struct ip_vs_proto_data *pd)
174
195
{
175
 
        if (unlikely(!pp->state_transition))
 
196
        if (unlikely(!pd->pp->state_transition))
176
197
                return 0;
177
 
        return pp->state_transition(cp, direction, skb, pp);
 
198
        return pd->pp->state_transition(cp, direction, skb, pd);
178
199
}
179
200
 
180
 
static inline void
 
201
static inline int
181
202
ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
182
203
                              struct sk_buff *skb, int protocol,
183
204
                              const union nf_inet_addr *caddr, __be16 cport,
184
205
                              const union nf_inet_addr *vaddr, __be16 vport,
185
206
                              struct ip_vs_conn_param *p)
186
207
{
187
 
        ip_vs_conn_fill_param(svc->af, protocol, caddr, cport, vaddr, vport, p);
 
208
        ip_vs_conn_fill_param(svc->net, svc->af, protocol, caddr, cport, vaddr,
 
209
                              vport, p);
188
210
        p->pe = svc->pe;
189
211
        if (p->pe && p->pe->fill_param)
190
 
                p->pe->fill_param(p, skb);
 
212
                return p->pe->fill_param(p, skb);
 
213
 
 
214
        return 0;
191
215
}
192
216
 
193
217
/*
200
224
static struct ip_vs_conn *
201
225
ip_vs_sched_persist(struct ip_vs_service *svc,
202
226
                    struct sk_buff *skb,
203
 
                    __be16 ports[2])
 
227
                    __be16 src_port, __be16 dst_port, int *ignored)
204
228
{
205
229
        struct ip_vs_conn *cp = NULL;
206
230
        struct ip_vs_iphdr iph;
224
248
 
225
249
        IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
226
250
                      "mnet %s\n",
227
 
                      IP_VS_DBG_ADDR(svc->af, &iph.saddr), ntohs(ports[0]),
228
 
                      IP_VS_DBG_ADDR(svc->af, &iph.daddr), ntohs(ports[1]),
 
251
                      IP_VS_DBG_ADDR(svc->af, &iph.saddr), ntohs(src_port),
 
252
                      IP_VS_DBG_ADDR(svc->af, &iph.daddr), ntohs(dst_port),
229
253
                      IP_VS_DBG_ADDR(svc->af, &snet));
230
254
 
231
255
        /*
247
271
                const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
248
272
                __be16 vport = 0;
249
273
 
250
 
                if (ports[1] == svc->port) {
 
274
                if (dst_port == svc->port) {
251
275
                        /* non-FTP template:
252
276
                         * <protocol, caddr, 0, vaddr, vport, daddr, dport>
253
277
                         * FTP template:
254
278
                         * <protocol, caddr, 0, vaddr, 0, daddr, 0>
255
279
                         */
256
280
                        if (svc->port != FTPPORT)
257
 
                                vport = ports[1];
 
281
                                vport = dst_port;
258
282
                } else {
259
283
                        /* Note: persistent fwmark-based services and
260
284
                         * persistent port zero service are handled here.
268
292
                                vaddr = &fwmark;
269
293
                        }
270
294
                }
271
 
                ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0,
272
 
                                              vaddr, vport, &param);
 
295
                /* return *ignored = -1 so NF_DROP can be used */
 
296
                if (ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0,
 
297
                                                  vaddr, vport, &param) < 0) {
 
298
                        *ignored = -1;
 
299
                        return NULL;
 
300
                }
273
301
        }
274
302
 
275
303
        /* Check if a template already exists */
276
304
        ct = ip_vs_ct_in_get(&param);
277
305
        if (!ct || !ip_vs_check_template(ct)) {
278
 
                /* No template found or the dest of the connection
 
306
                /*
 
307
                 * No template found or the dest of the connection
279
308
                 * template is not available.
 
309
                 * return *ignored=0 i.e. ICMP and NF_DROP
280
310
                 */
281
311
                dest = svc->scheduler->schedule(svc, skb);
282
312
                if (!dest) {
283
313
                        IP_VS_DBG(1, "p-schedule: no dest found.\n");
284
314
                        kfree(param.pe_data);
 
315
                        *ignored = 0;
285
316
                        return NULL;
286
317
                }
287
318
 
288
 
                if (ports[1] == svc->port && svc->port != FTPPORT)
 
319
                if (dst_port == svc->port && svc->port != FTPPORT)
289
320
                        dport = dest->port;
290
321
 
291
322
                /* Create a template
293
324
                 * and thus param.pe_data will be destroyed
294
325
                 * when the template expires */
295
326
                ct = ip_vs_conn_new(&param, &dest->addr, dport,
296
 
                                    IP_VS_CONN_F_TEMPLATE, dest);
 
327
                                    IP_VS_CONN_F_TEMPLATE, dest, skb->mark);
297
328
                if (ct == NULL) {
298
329
                        kfree(param.pe_data);
 
330
                        *ignored = -1;
299
331
                        return NULL;
300
332
                }
301
333
 
306
338
                kfree(param.pe_data);
307
339
        }
308
340
 
309
 
        dport = ports[1];
 
341
        dport = dst_port;
310
342
        if (dport == svc->port && dest->port)
311
343
                dport = dest->port;
312
344
 
317
349
        /*
318
350
         *    Create a new connection according to the template
319
351
         */
320
 
        ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr, ports[0],
321
 
                              &iph.daddr, ports[1], &param);
322
 
        cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest);
 
352
        ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol, &iph.saddr,
 
353
                              src_port, &iph.daddr, dst_port, &param);
 
354
 
 
355
        cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest, skb->mark);
323
356
        if (cp == NULL) {
324
357
                ip_vs_conn_put(ct);
 
358
                *ignored = -1;
325
359
                return NULL;
326
360
        }
327
361
 
341
375
 *  It selects a server according to the virtual service, and
342
376
 *  creates a connection entry.
343
377
 *  Protocols supported: TCP, UDP
 
378
 *
 
379
 *  Usage of *ignored
 
380
 *
 
381
 * 1 :   protocol tried to schedule (eg. on SYN), found svc but the
 
382
 *       svc/scheduler decides that this packet should be accepted with
 
383
 *       NF_ACCEPT because it must not be scheduled.
 
384
 *
 
385
 * 0 :   scheduler can not find destination, so try bypass or
 
386
 *       return ICMP and then NF_DROP (ip_vs_leave).
 
387
 *
 
388
 * -1 :  scheduler tried to schedule but fatal error occurred, eg.
 
389
 *       ip_vs_conn_new failure (ENOMEM) or ip_vs_sip_fill_param
 
390
 *       failure such as missing Call-ID, ENOMEM on skb_linearize
 
391
 *       or pe_data. In this case we should return NF_DROP without
 
392
 *       any attempts to send ICMP with ip_vs_leave.
344
393
 */
345
394
struct ip_vs_conn *
346
395
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
347
 
               struct ip_vs_protocol *pp, int *ignored)
 
396
               struct ip_vs_proto_data *pd, int *ignored)
348
397
{
 
398
        struct ip_vs_protocol *pp = pd->pp;
349
399
        struct ip_vs_conn *cp = NULL;
350
400
        struct ip_vs_iphdr iph;
351
401
        struct ip_vs_dest *dest;
371
421
        }
372
422
 
373
423
        /*
374
 
         * Do not schedule replies from local real server. It is risky
375
 
         * for fwmark services but mostly for persistent services.
 
424
         *    Do not schedule replies from local real server.
376
425
         */
377
426
        if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
378
 
            (svc->flags & IP_VS_SVC_F_PERSISTENT || svc->fwmark) &&
379
 
            (cp = pp->conn_in_get(svc->af, skb, pp, &iph, iph.len, 1))) {
 
427
            (cp = pp->conn_in_get(svc->af, skb, &iph, iph.len, 1))) {
380
428
                IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
381
429
                              "Not scheduling reply for existing connection");
382
430
                __ip_vs_conn_put(cp);
386
434
        /*
387
435
         *    Persistent service
388
436
         */
389
 
        if (svc->flags & IP_VS_SVC_F_PERSISTENT) {
390
 
                *ignored = 0;
391
 
                return ip_vs_sched_persist(svc, skb, pptr);
392
 
        }
 
437
        if (svc->flags & IP_VS_SVC_F_PERSISTENT)
 
438
                return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored);
 
439
 
 
440
        *ignored = 0;
393
441
 
394
442
        /*
395
443
         *    Non-persistent service
402
450
                return NULL;
403
451
        }
404
452
 
405
 
        *ignored = 0;
406
 
 
407
453
        dest = svc->scheduler->schedule(svc, skb);
408
454
        if (dest == NULL) {
409
455
                IP_VS_DBG(1, "Schedule: no dest found.\n");
419
465
         */
420
466
        {
421
467
                struct ip_vs_conn_param p;
422
 
                ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr,
423
 
                                      pptr[0], &iph.daddr, pptr[1], &p);
 
468
 
 
469
                ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
 
470
                                      &iph.saddr, pptr[0], &iph.daddr, pptr[1],
 
471
                                      &p);
424
472
                cp = ip_vs_conn_new(&p, &dest->addr,
425
473
                                    dest->port ? dest->port : pptr[1],
426
 
                                    flags, dest);
427
 
                if (!cp)
 
474
                                    flags, dest, skb->mark);
 
475
                if (!cp) {
 
476
                        *ignored = -1;
428
477
                        return NULL;
 
478
                }
429
479
        }
430
480
 
431
481
        IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
447
497
 *  no destination is available for a new connection.
448
498
 */
449
499
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
450
 
                struct ip_vs_protocol *pp)
 
500
                struct ip_vs_proto_data *pd)
451
501
{
452
502
        __be16 _ports[2], *pptr;
453
503
        struct ip_vs_iphdr iph;
 
504
#ifdef CONFIG_SYSCTL
 
505
        struct net *net;
 
506
        struct netns_ipvs *ipvs;
454
507
        int unicast;
 
508
#endif
 
509
 
455
510
        ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
456
511
 
457
512
        pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
460
515
                return NF_DROP;
461
516
        }
462
517
 
 
518
#ifdef CONFIG_SYSCTL
 
519
        net = skb_net(skb);
 
520
 
463
521
#ifdef CONFIG_IP_VS_IPV6
464
522
        if (svc->af == AF_INET6)
465
523
                unicast = ipv6_addr_type(&iph.daddr.in6) & IPV6_ADDR_UNICAST;
466
524
        else
467
525
#endif
468
 
                unicast = (inet_addr_type(&init_net, iph.daddr.ip) == RTN_UNICAST);
 
526
                unicast = (inet_addr_type(net, iph.daddr.ip) == RTN_UNICAST);
469
527
 
470
528
        /* if it is fwmark-based service, the cache_bypass sysctl is up
471
529
           and the destination is a non-local unicast, then create
472
530
           a cache_bypass connection entry */
473
 
        if (sysctl_ip_vs_cache_bypass && svc->fwmark && unicast) {
 
531
        ipvs = net_ipvs(net);
 
532
        if (ipvs->sysctl_cache_bypass && svc->fwmark && unicast) {
474
533
                int ret, cs;
475
534
                struct ip_vs_conn *cp;
476
535
                unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
484
543
                IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
485
544
                {
486
545
                        struct ip_vs_conn_param p;
487
 
                        ip_vs_conn_fill_param(svc->af, iph.protocol,
 
546
                        ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
488
547
                                              &iph.saddr, pptr[0],
489
548
                                              &iph.daddr, pptr[1], &p);
490
549
                        cp = ip_vs_conn_new(&p, &daddr, 0,
491
550
                                            IP_VS_CONN_F_BYPASS | flags,
492
 
                                            NULL);
 
551
                                            NULL, skb->mark);
493
552
                        if (!cp)
494
553
                                return NF_DROP;
495
554
                }
498
557
                ip_vs_in_stats(cp, skb);
499
558
 
500
559
                /* set state */
501
 
                cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
 
560
                cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
502
561
 
503
562
                /* transmit the first SYN packet */
504
 
                ret = cp->packet_xmit(skb, cp, pp);
 
563
                ret = cp->packet_xmit(skb, cp, pd->pp);
505
564
                /* do not touch skb anymore */
506
565
 
507
566
                atomic_inc(&cp->in_pkts);
508
567
                ip_vs_conn_put(cp);
509
568
                return ret;
510
569
        }
 
570
#endif
511
571
 
512
572
        /*
513
573
         * When the virtual ftp service is presented, packets destined
544
604
        return NF_DROP;
545
605
}
546
606
 
 
607
#ifdef CONFIG_SYSCTL
 
608
 
 
609
static int sysctl_snat_reroute(struct sk_buff *skb)
 
610
{
 
611
        struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
 
612
        return ipvs->sysctl_snat_reroute;
 
613
}
 
614
 
 
615
static int sysctl_nat_icmp_send(struct net *net)
 
616
{
 
617
        struct netns_ipvs *ipvs = net_ipvs(net);
 
618
        return ipvs->sysctl_nat_icmp_send;
 
619
}
 
620
 
 
621
static int sysctl_expire_nodest_conn(struct netns_ipvs *ipvs)
 
622
{
 
623
        return ipvs->sysctl_expire_nodest_conn;
 
624
}
 
625
 
 
626
#else
 
627
 
 
628
static int sysctl_snat_reroute(struct sk_buff *skb) { return 0; }
 
629
static int sysctl_nat_icmp_send(struct net *net) { return 0; }
 
630
static int sysctl_expire_nodest_conn(struct netns_ipvs *ipvs) { return 0; }
 
631
 
 
632
#endif
 
633
 
547
634
__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
548
635
{
549
636
        return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
576
663
}
577
664
#endif
578
665
 
 
666
static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
 
667
{
 
668
#ifdef CONFIG_IP_VS_IPV6
 
669
        if (af == AF_INET6) {
 
670
                if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0)
 
671
                        return 1;
 
672
        } else
 
673
#endif
 
674
                if ((sysctl_snat_reroute(skb) ||
 
675
                     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
 
676
                    ip_route_me_harder(skb, RTN_LOCAL) != 0)
 
677
                        return 1;
 
678
 
 
679
        return 0;
 
680
}
 
681
 
579
682
/*
580
683
 * Packet has been made sufficiently writable in caller
581
684
 * - inout: 1=in->out, 0=out->in
674
777
#endif
675
778
 
676
779
/* Handle relevant response ICMP messages - forward to the right
677
 
 * destination host. Used for NAT and local client.
 
780
 * destination host.
678
781
 */
679
782
static int handle_response_icmp(int af, struct sk_buff *skb,
680
783
                                union nf_inet_addr *snet,
710
813
#endif
711
814
                ip_vs_nat_icmp(skb, pp, cp, 1);
712
815
 
713
 
#ifdef CONFIG_IP_VS_IPV6
714
 
        if (af == AF_INET6) {
715
 
                if (sysctl_ip_vs_snat_reroute && ip6_route_me_harder(skb) != 0)
716
 
                        goto out;
717
 
        } else
718
 
#endif
719
 
                if ((sysctl_ip_vs_snat_reroute ||
720
 
                     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
721
 
                    ip_route_me_harder(skb, RTN_LOCAL) != 0)
722
 
                        goto out;
 
816
        if (ip_vs_route_me_harder(af, skb))
 
817
                goto out;
723
818
 
724
819
        /* do the statistics and put it back */
725
820
        ip_vs_out_stats(cp, skb);
808
903
 
809
904
        ip_vs_fill_iphdr(AF_INET, cih, &ciph);
810
905
        /* The embedded headers contain source and dest in reverse order */
811
 
        cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1);
 
906
        cp = pp->conn_out_get(AF_INET, skb, &ciph, offset, 1);
812
907
        if (!cp)
813
908
                return NF_ACCEPT;
814
909
 
885
980
 
886
981
        ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
887
982
        /* The embedded headers contain source and dest in reverse order */
888
 
        cp = pp->conn_out_get(AF_INET6, skb, pp, &ciph, offset, 1);
 
983
        cp = pp->conn_out_get(AF_INET6, skb, &ciph, offset, 1);
889
984
        if (!cp)
890
985
                return NF_ACCEPT;
891
986
 
921
1016
}
922
1017
 
923
1018
/* Handle response packets: rewrite addresses and send away...
924
 
 * Used for NAT and local client.
925
1019
 */
926
1020
static unsigned int
927
 
handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 
1021
handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
928
1022
                struct ip_vs_conn *cp, int ihl)
929
1023
{
 
1024
        struct ip_vs_protocol *pp = pd->pp;
 
1025
 
930
1026
        IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
931
1027
 
932
1028
        if (!skb_make_writable(skb, ihl))
961
1057
         * if it came from this machine itself.  So re-compute
962
1058
         * the routing information.
963
1059
         */
964
 
#ifdef CONFIG_IP_VS_IPV6
965
 
        if (af == AF_INET6) {
966
 
                if (sysctl_ip_vs_snat_reroute && ip6_route_me_harder(skb) != 0)
967
 
                        goto drop;
968
 
        } else
969
 
#endif
970
 
                if ((sysctl_ip_vs_snat_reroute ||
971
 
                     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
972
 
                    ip_route_me_harder(skb, RTN_LOCAL) != 0)
973
 
                        goto drop;
 
1060
        if (ip_vs_route_me_harder(af, skb))
 
1061
                goto drop;
974
1062
 
975
1063
        IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
976
1064
 
977
1065
        ip_vs_out_stats(cp, skb);
978
 
        ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
 
1066
        ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd);
979
1067
        skb->ipvs_property = 1;
980
1068
        if (!(cp->flags & IP_VS_CONN_F_NFCT))
981
1069
                ip_vs_notrack(skb);
999
1087
static unsigned int
1000
1088
ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
1001
1089
{
 
1090
        struct net *net = NULL;
1002
1091
        struct ip_vs_iphdr iph;
1003
1092
        struct ip_vs_protocol *pp;
 
1093
        struct ip_vs_proto_data *pd;
1004
1094
        struct ip_vs_conn *cp;
1005
1095
 
1006
1096
        EnterFunction(11);
1022
1112
        if (unlikely(!skb_dst(skb)))
1023
1113
                return NF_ACCEPT;
1024
1114
 
 
1115
        net = skb_net(skb);
 
1116
        if (!net_ipvs(net)->enable)
 
1117
                return NF_ACCEPT;
 
1118
 
1025
1119
        ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
1026
1120
#ifdef CONFIG_IP_VS_IPV6
1027
1121
        if (af == AF_INET6) {
1045
1139
                        ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
1046
1140
                }
1047
1141
 
1048
 
        pp = ip_vs_proto_get(iph.protocol);
1049
 
        if (unlikely(!pp))
 
1142
        pd = ip_vs_proto_data_get(net, iph.protocol);
 
1143
        if (unlikely(!pd))
1050
1144
                return NF_ACCEPT;
 
1145
        pp = pd->pp;
1051
1146
 
1052
1147
        /* reassemble IP fragments */
1053
1148
#ifdef CONFIG_IP_VS_IPV6
1073
1168
        /*
1074
1169
         * Check if the packet belongs to an existing entry
1075
1170
         */
1076
 
        cp = pp->conn_out_get(af, skb, pp, &iph, iph.len, 0);
 
1171
        cp = pp->conn_out_get(af, skb, &iph, iph.len, 0);
1077
1172
 
1078
1173
        if (likely(cp))
1079
 
                return handle_response(af, skb, pp, cp, iph.len);
1080
 
        if (sysctl_ip_vs_nat_icmp_send &&
 
1174
                return handle_response(af, skb, pd, cp, iph.len);
 
1175
        if (sysctl_nat_icmp_send(net) &&
1081
1176
            (pp->protocol == IPPROTO_TCP ||
1082
1177
             pp->protocol == IPPROTO_UDP ||
1083
1178
             pp->protocol == IPPROTO_SCTP)) {
1087
1182
                                          sizeof(_ports), _ports);
1088
1183
                if (pptr == NULL)
1089
1184
                        return NF_ACCEPT;       /* Not for me */
1090
 
                if (ip_vs_lookup_real_service(af, iph.protocol,
 
1185
                if (ip_vs_lookup_real_service(net, af, iph.protocol,
1091
1186
                                              &iph.saddr,
1092
1187
                                              pptr[0])) {
1093
1188
                        /*
1202
1297
static int
1203
1298
ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
1204
1299
{
 
1300
        struct net *net = NULL;
1205
1301
        struct iphdr *iph;
1206
1302
        struct icmphdr  _icmph, *ic;
1207
1303
        struct iphdr    _ciph, *cih;    /* The ip header contained within the ICMP */
1208
1304
        struct ip_vs_iphdr ciph;
1209
1305
        struct ip_vs_conn *cp;
1210
1306
        struct ip_vs_protocol *pp;
 
1307
        struct ip_vs_proto_data *pd;
1211
1308
        unsigned int offset, ihl, verdict;
1212
 
        union nf_inet_addr snet;
1213
1309
 
1214
1310
        *related = 1;
1215
1311
 
1249
1345
        if (cih == NULL)
1250
1346
                return NF_ACCEPT; /* The packet looks wrong, ignore */
1251
1347
 
1252
 
        pp = ip_vs_proto_get(cih->protocol);
1253
 
        if (!pp)
 
1348
        net = skb_net(skb);
 
1349
 
 
1350
        pd = ip_vs_proto_data_get(net, cih->protocol);
 
1351
        if (!pd)
1254
1352
                return NF_ACCEPT;
 
1353
        pp = pd->pp;
1255
1354
 
1256
1355
        /* Is the embedded protocol header present? */
1257
1356
        if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
1265
1364
 
1266
1365
        ip_vs_fill_iphdr(AF_INET, cih, &ciph);
1267
1366
        /* The embedded headers contain source and dest in reverse order */
1268
 
        cp = pp->conn_in_get(AF_INET, skb, pp, &ciph, offset, 1);
1269
 
        if (!cp) {
1270
 
                /* The packet could also belong to a local client */
1271
 
                cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1);
1272
 
                if (cp) {
1273
 
                        snet.ip = iph->saddr;
1274
 
                        return handle_response_icmp(AF_INET, skb, &snet,
1275
 
                                                    cih->protocol, cp, pp,
1276
 
                                                    offset, ihl);
1277
 
                }
 
1367
        cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, 1);
 
1368
        if (!cp)
1278
1369
                return NF_ACCEPT;
1279
 
        }
1280
1370
 
1281
1371
        verdict = NF_DROP;
1282
1372
 
1292
1382
        ip_vs_in_stats(cp, skb);
1293
1383
        if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
1294
1384
                offset += 2 * sizeof(__u16);
1295
 
        verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
1296
 
        /* LOCALNODE from FORWARD hook is not supported */
1297
 
        if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD &&
1298
 
            skb_rtable(skb)->rt_flags & RTCF_LOCAL) {
1299
 
                IP_VS_DBG(1, "%s(): "
1300
 
                          "local delivery to %pI4 but in FORWARD\n",
1301
 
                          __func__, &skb_rtable(skb)->rt_dst);
1302
 
                verdict = NF_DROP;
1303
 
        }
 
1385
        verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum);
1304
1386
 
1305
1387
  out:
1306
1388
        __ip_vs_conn_put(cp);
1312
1394
static int
1313
1395
ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
1314
1396
{
 
1397
        struct net *net = NULL;
1315
1398
        struct ipv6hdr *iph;
1316
1399
        struct icmp6hdr _icmph, *ic;
1317
1400
        struct ipv6hdr  _ciph, *cih;    /* The ip header contained
1319
1402
        struct ip_vs_iphdr ciph;
1320
1403
        struct ip_vs_conn *cp;
1321
1404
        struct ip_vs_protocol *pp;
 
1405
        struct ip_vs_proto_data *pd;
1322
1406
        unsigned int offset, verdict;
1323
 
        union nf_inet_addr snet;
1324
 
        struct rt6_info *rt;
1325
1407
 
1326
1408
        *related = 1;
1327
1409
 
1361
1443
        if (cih == NULL)
1362
1444
                return NF_ACCEPT; /* The packet looks wrong, ignore */
1363
1445
 
1364
 
        pp = ip_vs_proto_get(cih->nexthdr);
1365
 
        if (!pp)
 
1446
        net = skb_net(skb);
 
1447
        pd = ip_vs_proto_data_get(net, cih->nexthdr);
 
1448
        if (!pd)
1366
1449
                return NF_ACCEPT;
 
1450
        pp = pd->pp;
1367
1451
 
1368
1452
        /* Is the embedded protocol header present? */
1369
1453
        /* TODO: we don't support fragmentation at the moment anyways */
1377
1461
 
1378
1462
        ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
1379
1463
        /* The embedded headers contain source and dest in reverse order */
1380
 
        cp = pp->conn_in_get(AF_INET6, skb, pp, &ciph, offset, 1);
1381
 
        if (!cp) {
1382
 
                /* The packet could also belong to a local client */
1383
 
                cp = pp->conn_out_get(AF_INET6, skb, pp, &ciph, offset, 1);
1384
 
                if (cp) {
1385
 
                        ipv6_addr_copy(&snet.in6, &iph->saddr);
1386
 
                        return handle_response_icmp(AF_INET6, skb, &snet,
1387
 
                                                    cih->nexthdr,
1388
 
                                                    cp, pp, offset,
1389
 
                                                    sizeof(struct ipv6hdr));
1390
 
                }
 
1464
        cp = pp->conn_in_get(AF_INET6, skb, &ciph, offset, 1);
 
1465
        if (!cp)
1391
1466
                return NF_ACCEPT;
1392
 
        }
1393
 
 
1394
 
        verdict = NF_DROP;
1395
1467
 
1396
1468
        /* do the statistics and put it back */
1397
1469
        ip_vs_in_stats(cp, skb);
1398
1470
        if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr ||
1399
1471
            IPPROTO_SCTP == cih->nexthdr)
1400
1472
                offset += 2 * sizeof(__u16);
1401
 
        verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset);
1402
 
        /* LOCALNODE from FORWARD hook is not supported */
1403
 
        if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD &&
1404
 
            (rt = (struct rt6_info *) skb_dst(skb)) &&
1405
 
            rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) {
1406
 
                IP_VS_DBG(1, "%s(): "
1407
 
                          "local delivery to %pI6 but in FORWARD\n",
1408
 
                          __func__, &rt->rt6i_dst);
1409
 
                verdict = NF_DROP;
1410
 
        }
 
1473
        verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum);
1411
1474
 
1412
1475
        __ip_vs_conn_put(cp);
1413
1476
 
1423
1486
static unsigned int
1424
1487
ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1425
1488
{
 
1489
        struct net *net;
1426
1490
        struct ip_vs_iphdr iph;
1427
1491
        struct ip_vs_protocol *pp;
 
1492
        struct ip_vs_proto_data *pd;
1428
1493
        struct ip_vs_conn *cp;
1429
1494
        int ret, restart, pkts;
 
1495
        struct netns_ipvs *ipvs;
1430
1496
 
1431
1497
        /* Already marked as IPVS request or reply? */
1432
1498
        if (skb->ipvs_property)
1447
1513
                              IP_VS_DBG_ADDR(af, &iph.daddr), hooknum);
1448
1514
                return NF_ACCEPT;
1449
1515
        }
 
1516
        /* ipvs enabled in this netns ? */
 
1517
        net = skb_net(skb);
 
1518
        if (!net_ipvs(net)->enable)
 
1519
                return NF_ACCEPT;
 
1520
 
1450
1521
        ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
1451
1522
 
1452
1523
        /* Bad... Do not break raw sockets */
1481
1552
                }
1482
1553
 
1483
1554
        /* Protocol supported? */
1484
 
        pp = ip_vs_proto_get(iph.protocol);
1485
 
        if (unlikely(!pp))
 
1555
        pd = ip_vs_proto_data_get(net, iph.protocol);
 
1556
        if (unlikely(!pd))
1486
1557
                return NF_ACCEPT;
1487
 
 
 
1558
        pp = pd->pp;
1488
1559
        /*
1489
1560
         * Check if the packet belongs to an existing connection entry
1490
1561
         */
1491
 
        cp = pp->conn_in_get(af, skb, pp, &iph, iph.len, 0);
 
1562
        cp = pp->conn_in_get(af, skb, &iph, iph.len, 0);
1492
1563
 
1493
1564
        if (unlikely(!cp)) {
1494
1565
                int v;
1495
1566
 
1496
 
                if (!pp->conn_schedule(af, skb, pp, &v, &cp))
 
1567
                if (!pp->conn_schedule(af, skb, pd, &v, &cp))
1497
1568
                        return v;
1498
1569
        }
1499
1570
 
1505
1576
        }
1506
1577
 
1507
1578
        IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
1508
 
 
 
1579
        ipvs = net_ipvs(net);
1509
1580
        /* Check the server status */
1510
1581
        if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
1511
1582
                /* the destination server is not available */
1512
1583
 
1513
 
                if (sysctl_ip_vs_expire_nodest_conn) {
 
1584
                if (sysctl_expire_nodest_conn(ipvs)) {
1514
1585
                        /* try to expire the connection immediately */
1515
1586
                        ip_vs_conn_expire_now(cp);
1516
1587
                }
1521
1592
        }
1522
1593
 
1523
1594
        ip_vs_in_stats(cp, skb);
1524
 
        restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
 
1595
        restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
1525
1596
        if (cp->packet_xmit)
1526
1597
                ret = cp->packet_xmit(skb, cp, pp);
1527
1598
                /* do not touch skb anymore */
1535
1606
         *
1536
1607
         * Sync connection if it is about to close to
1537
1608
         * encorage the standby servers to update the connections timeout
 
1609
         *
 
1610
         * For ONE_PKT let ip_vs_sync_conn() do the filter work.
1538
1611
         */
1539
 
        pkts = atomic_add_return(1, &cp->in_pkts);
1540
 
        if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) &&
 
1612
 
 
1613
        if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
 
1614
                pkts = sysctl_sync_threshold(ipvs);
 
1615
        else
 
1616
                pkts = atomic_add_return(1, &cp->in_pkts);
 
1617
 
 
1618
        if ((ipvs->sync_state & IP_VS_STATE_MASTER) &&
1541
1619
            cp->protocol == IPPROTO_SCTP) {
1542
1620
                if ((cp->state == IP_VS_SCTP_S_ESTABLISHED &&
1543
 
                        (pkts % sysctl_ip_vs_sync_threshold[1]
1544
 
                         == sysctl_ip_vs_sync_threshold[0])) ||
 
1621
                        (pkts % sysctl_sync_period(ipvs)
 
1622
                         == sysctl_sync_threshold(ipvs))) ||
1545
1623
                                (cp->old_state != cp->state &&
1546
1624
                                 ((cp->state == IP_VS_SCTP_S_CLOSED) ||
1547
1625
                                  (cp->state == IP_VS_SCTP_S_SHUT_ACK_CLI) ||
1548
1626
                                  (cp->state == IP_VS_SCTP_S_SHUT_ACK_SER)))) {
1549
 
                        ip_vs_sync_conn(cp);
 
1627
                        ip_vs_sync_conn(net, cp);
1550
1628
                        goto out;
1551
1629
                }
1552
1630
        }
1553
1631
 
1554
1632
        /* Keep this block last: TCP and others with pp->num_states <= 1 */
1555
 
        else if (af == AF_INET &&
1556
 
            (ip_vs_sync_state & IP_VS_STATE_MASTER) &&
 
1633
        else if ((ipvs->sync_state & IP_VS_STATE_MASTER) &&
1557
1634
            (((cp->protocol != IPPROTO_TCP ||
1558
1635
               cp->state == IP_VS_TCP_S_ESTABLISHED) &&
1559
 
              (pkts % sysctl_ip_vs_sync_threshold[1]
1560
 
               == sysctl_ip_vs_sync_threshold[0])) ||
 
1636
              (pkts % sysctl_sync_period(ipvs)
 
1637
               == sysctl_sync_threshold(ipvs))) ||
1561
1638
             ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) &&
1562
1639
              ((cp->state == IP_VS_TCP_S_FIN_WAIT) ||
1563
1640
               (cp->state == IP_VS_TCP_S_CLOSE) ||
1564
1641
               (cp->state == IP_VS_TCP_S_CLOSE_WAIT) ||
1565
1642
               (cp->state == IP_VS_TCP_S_TIME_WAIT)))))
1566
 
                ip_vs_sync_conn(cp);
 
1643
                ip_vs_sync_conn(net, cp);
1567
1644
out:
1568
1645
        cp->old_state = cp->state;
1569
1646
 
1653
1730
                   int (*okfn)(struct sk_buff *))
1654
1731
{
1655
1732
        int r;
 
1733
        struct net *net;
1656
1734
 
1657
1735
        if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
1658
1736
                return NF_ACCEPT;
1659
1737
 
 
1738
        /* ipvs enabled in this netns ? */
 
1739
        net = skb_net(skb);
 
1740
        if (!net_ipvs(net)->enable)
 
1741
                return NF_ACCEPT;
 
1742
 
1660
1743
        return ip_vs_in_icmp(skb, &r, hooknum);
1661
1744
}
1662
1745
 
1667
1750
                      int (*okfn)(struct sk_buff *))
1668
1751
{
1669
1752
        int r;
 
1753
        struct net *net;
1670
1754
 
1671
1755
        if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6)
1672
1756
                return NF_ACCEPT;
1673
1757
 
 
1758
        /* ipvs enabled in this netns ? */
 
1759
        net = skb_net(skb);
 
1760
        if (!net_ipvs(net)->enable)
 
1761
                return NF_ACCEPT;
 
1762
 
1674
1763
        return ip_vs_in_icmp_v6(skb, &r, hooknum);
1675
1764
}
1676
1765
#endif
1683
1772
                .owner          = THIS_MODULE,
1684
1773
                .pf             = PF_INET,
1685
1774
                .hooknum        = NF_INET_LOCAL_IN,
1686
 
                .priority       = 99,
 
1775
                .priority       = NF_IP_PRI_NAT_SRC - 2,
1687
1776
        },
1688
1777
        /* After packet filtering, forward packet through VS/DR, VS/TUN,
1689
1778
         * or VS/NAT(change destination), so that filtering rules can be
1693
1782
                .owner          = THIS_MODULE,
1694
1783
                .pf             = PF_INET,
1695
1784
                .hooknum        = NF_INET_LOCAL_IN,
1696
 
                .priority       = 101,
 
1785
                .priority       = NF_IP_PRI_NAT_SRC - 1,
1697
1786
        },
1698
1787
        /* Before ip_vs_in, change source only for VS/NAT */
1699
1788
        {
1701
1790
                .owner          = THIS_MODULE,
1702
1791
                .pf             = PF_INET,
1703
1792
                .hooknum        = NF_INET_LOCAL_OUT,
1704
 
                .priority       = -99,
 
1793
                .priority       = NF_IP_PRI_NAT_DST + 1,
1705
1794
        },
1706
1795
        /* After mangle, schedule and forward local requests */
1707
1796
        {
1709
1798
                .owner          = THIS_MODULE,
1710
1799
                .pf             = PF_INET,
1711
1800
                .hooknum        = NF_INET_LOCAL_OUT,
1712
 
                .priority       = -98,
 
1801
                .priority       = NF_IP_PRI_NAT_DST + 2,
1713
1802
        },
1714
1803
        /* After packet filtering (but before ip_vs_out_icmp), catch icmp
1715
1804
         * destined for 0.0.0.0/0, which is for incoming IPVS connections */
1735
1824
                .owner          = THIS_MODULE,
1736
1825
                .pf             = PF_INET6,
1737
1826
                .hooknum        = NF_INET_LOCAL_IN,
1738
 
                .priority       = 99,
 
1827
                .priority       = NF_IP6_PRI_NAT_SRC - 2,
1739
1828
        },
1740
1829
        /* After packet filtering, forward packet through VS/DR, VS/TUN,
1741
1830
         * or VS/NAT(change destination), so that filtering rules can be
1745
1834
                .owner          = THIS_MODULE,
1746
1835
                .pf             = PF_INET6,
1747
1836
                .hooknum        = NF_INET_LOCAL_IN,
1748
 
                .priority       = 101,
 
1837
                .priority       = NF_IP6_PRI_NAT_SRC - 1,
1749
1838
        },
1750
1839
        /* Before ip_vs_in, change source only for VS/NAT */
1751
1840
        {
1753
1842
                .owner          = THIS_MODULE,
1754
1843
                .pf             = PF_INET,
1755
1844
                .hooknum        = NF_INET_LOCAL_OUT,
1756
 
                .priority       = -99,
 
1845
                .priority       = NF_IP6_PRI_NAT_DST + 1,
1757
1846
        },
1758
1847
        /* After mangle, schedule and forward local requests */
1759
1848
        {
1761
1850
                .owner          = THIS_MODULE,
1762
1851
                .pf             = PF_INET6,
1763
1852
                .hooknum        = NF_INET_LOCAL_OUT,
1764
 
                .priority       = -98,
 
1853
                .priority       = NF_IP6_PRI_NAT_DST + 2,
1765
1854
        },
1766
1855
        /* After packet filtering (but before ip_vs_out_icmp), catch icmp
1767
1856
         * destined for 0.0.0.0/0, which is for incoming IPVS connections */
1782
1871
        },
1783
1872
#endif
1784
1873
};
1785
 
 
 
1874
/*
 
1875
 *      Initialize IP Virtual Server netns mem.
 
1876
 */
 
1877
static int __net_init __ip_vs_init(struct net *net)
 
1878
{
 
1879
        struct netns_ipvs *ipvs;
 
1880
 
 
1881
        ipvs = net_generic(net, ip_vs_net_id);
 
1882
        if (ipvs == NULL) {
 
1883
                pr_err("%s(): no memory.\n", __func__);
 
1884
                return -ENOMEM;
 
1885
        }
 
1886
        /* Hold the beast until a service is registerd */
 
1887
        ipvs->enable = 0;
 
1888
        ipvs->net = net;
 
1889
        /* Counters used for creating unique names */
 
1890
        ipvs->gen = atomic_read(&ipvs_netns_cnt);
 
1891
        atomic_inc(&ipvs_netns_cnt);
 
1892
        net->ipvs = ipvs;
 
1893
 
 
1894
        if (__ip_vs_estimator_init(net) < 0)
 
1895
                goto estimator_fail;
 
1896
 
 
1897
        if (__ip_vs_control_init(net) < 0)
 
1898
                goto control_fail;
 
1899
 
 
1900
        if (__ip_vs_protocol_init(net) < 0)
 
1901
                goto protocol_fail;
 
1902
 
 
1903
        if (__ip_vs_app_init(net) < 0)
 
1904
                goto app_fail;
 
1905
 
 
1906
        if (__ip_vs_conn_init(net) < 0)
 
1907
                goto conn_fail;
 
1908
 
 
1909
        if (__ip_vs_sync_init(net) < 0)
 
1910
                goto sync_fail;
 
1911
 
 
1912
        printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
 
1913
                         sizeof(struct netns_ipvs), ipvs->gen);
 
1914
        return 0;
 
1915
/*
 
1916
 * Error handling
 
1917
 */
 
1918
 
 
1919
sync_fail:
 
1920
        __ip_vs_conn_cleanup(net);
 
1921
conn_fail:
 
1922
        __ip_vs_app_cleanup(net);
 
1923
app_fail:
 
1924
        __ip_vs_protocol_cleanup(net);
 
1925
protocol_fail:
 
1926
        __ip_vs_control_cleanup(net);
 
1927
control_fail:
 
1928
        __ip_vs_estimator_cleanup(net);
 
1929
estimator_fail:
 
1930
        return -ENOMEM;
 
1931
}
 
1932
 
 
1933
static void __net_exit __ip_vs_cleanup(struct net *net)
 
1934
{
 
1935
        __ip_vs_service_cleanup(net);   /* ip_vs_flush() with locks */
 
1936
        __ip_vs_conn_cleanup(net);
 
1937
        __ip_vs_app_cleanup(net);
 
1938
        __ip_vs_protocol_cleanup(net);
 
1939
        __ip_vs_control_cleanup(net);
 
1940
        __ip_vs_estimator_cleanup(net);
 
1941
        IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
 
1942
}
 
1943
 
 
1944
static void __net_exit __ip_vs_dev_cleanup(struct net *net)
 
1945
{
 
1946
        EnterFunction(2);
 
1947
        net_ipvs(net)->enable = 0;      /* Disable packet reception */
 
1948
        smp_wmb();
 
1949
        __ip_vs_sync_cleanup(net);
 
1950
        LeaveFunction(2);
 
1951
}
 
1952
 
 
1953
static struct pernet_operations ipvs_core_ops = {
 
1954
        .init = __ip_vs_init,
 
1955
        .exit = __ip_vs_cleanup,
 
1956
        .id   = &ip_vs_net_id,
 
1957
        .size = sizeof(struct netns_ipvs),
 
1958
};
 
1959
 
 
1960
static struct pernet_operations ipvs_core_dev_ops = {
 
1961
        .exit = __ip_vs_dev_cleanup,
 
1962
};
1786
1963
 
1787
1964
/*
1788
1965
 *      Initialize IP Virtual Server
1792
1969
        int ret;
1793
1970
 
1794
1971
        ip_vs_estimator_init();
1795
 
 
1796
1972
        ret = ip_vs_control_init();
1797
1973
        if (ret < 0) {
1798
1974
                pr_err("can't setup control.\n");
1813
1989
                goto cleanup_app;
1814
1990
        }
1815
1991
 
 
1992
        ret = ip_vs_sync_init();
 
1993
        if (ret < 0) {
 
1994
                pr_err("can't setup sync data.\n");
 
1995
                goto cleanup_conn;
 
1996
        }
 
1997
 
 
1998
        ret = register_pernet_subsys(&ipvs_core_ops);   /* Alloc ip_vs struct */
 
1999
        if (ret < 0)
 
2000
                goto cleanup_sync;
 
2001
 
 
2002
        ret = register_pernet_device(&ipvs_core_dev_ops);
 
2003
        if (ret < 0)
 
2004
                goto cleanup_sub;
 
2005
 
1816
2006
        ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
1817
2007
        if (ret < 0) {
1818
2008
                pr_err("can't register hooks.\n");
1819
 
                goto cleanup_conn;
 
2009
                goto cleanup_dev;
1820
2010
        }
1821
2011
 
1822
2012
        pr_info("ipvs loaded.\n");
 
2013
 
1823
2014
        return ret;
1824
2015
 
 
2016
cleanup_dev:
 
2017
        unregister_pernet_device(&ipvs_core_dev_ops);
 
2018
cleanup_sub:
 
2019
        unregister_pernet_subsys(&ipvs_core_ops);
 
2020
cleanup_sync:
 
2021
        ip_vs_sync_cleanup();
1825
2022
  cleanup_conn:
1826
2023
        ip_vs_conn_cleanup();
1827
2024
  cleanup_app:
1837
2034
static void __exit ip_vs_cleanup(void)
1838
2035
{
1839
2036
        nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
 
2037
        unregister_pernet_device(&ipvs_core_dev_ops);
 
2038
        unregister_pernet_subsys(&ipvs_core_ops);       /* free ip_vs struct */
 
2039
        ip_vs_sync_cleanup();
1840
2040
        ip_vs_conn_cleanup();
1841
2041
        ip_vs_app_cleanup();
1842
2042
        ip_vs_protocol_cleanup();