source: rtems-libbsd/freebsd/sys/netpfil/ipfw/ip_dn_glue.c @ 2017a6d

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2017a6d was 2017a6d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/16 at 07:48:12

Directly use <sys/time.h> provided by Newlib

  • Property mode set to 100644
File size: 22.3 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (c) 2010 Riccardo Panicucci, Universita` di Pisa
5 * All rights reserved
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * $FreeBSD$
31 *
32 * Binary compatibility support for /sbin/ipfw RELENG_7 and RELENG_8
33 */
34
35#include <rtems/bsd/local/opt_inet6.h>
36
37#include <rtems/bsd/sys/param.h>
38#include <sys/systm.h>
39#include <sys/malloc.h>
40#include <sys/mbuf.h>
41#include <sys/kernel.h>
42#include <rtems/bsd/sys/lock.h>
43#include <sys/module.h>
44#include <sys/priv.h>
45#include <sys/proc.h>
46#include <sys/rwlock.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/time.h>
50#include <sys/taskqueue.h>
51#include <net/if.h>     /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */
52#include <netinet/in.h>
53#include <netinet/ip_var.h>     /* ip_output(), IP_FORWARDING */
54#include <netinet/ip_fw.h>
55#include <netinet/ip_dummynet.h>
56
57#include <netpfil/ipfw/ip_fw_private.h>
58#include <netpfil/ipfw/dn_heap.h>
59#include <netpfil/ipfw/ip_dn_private.h>
60#include <netpfil/ipfw/dn_sched.h>
61
62/* FREEBSD7.2 ip_dummynet.h r191715*/
63
64struct dn_heap_entry7 {
65        int64_t key;        /* sorting key. Topmost element is smallest one */
66        void *object;      /* object pointer */
67};
68
69struct dn_heap7 {
70        int size;
71        int elements;
72        int offset; /* XXX if > 0 this is the offset of direct ptr to obj */
73        struct dn_heap_entry7 *p;   /* really an array of "size" entries */
74};
75
76/* Common to 7.2 and 8 */
77struct dn_flow_set {
78        SLIST_ENTRY(dn_flow_set)    next;   /* linked list in a hash slot */
79
80        u_short fs_nr ;             /* flow_set number       */
81        u_short flags_fs;
82#define DNOLD_HAVE_FLOW_MASK   0x0001
83#define DNOLD_IS_RED       0x0002
84#define DNOLD_IS_GENTLE_RED    0x0004
85#define DNOLD_QSIZE_IS_BYTES   0x0008  /* queue size is measured in bytes */
86#define DNOLD_NOERROR      0x0010  /* do not report ENOBUFS on drops  */
87#define DNOLD_HAS_PROFILE      0x0020  /* the pipe has a delay profile. */
88#define DNOLD_IS_PIPE      0x4000
89#define DNOLD_IS_QUEUE     0x8000
90
91        struct dn_pipe7 *pipe ;  /* pointer to parent pipe */
92        u_short parent_nr ;     /* parent pipe#, 0 if local to a pipe */
93
94        int weight ;        /* WFQ queue weight */
95        int qsize ;         /* queue size in slots or bytes */
96        int plr ;           /* pkt loss rate (2^31-1 means 100%) */
97
98        struct ipfw_flow_id flow_mask ;
99
100        /* hash table of queues onto this flow_set */
101        int rq_size ;       /* number of slots */
102        int rq_elements ;       /* active elements */
103        struct dn_flow_queue7 **rq;  /* array of rq_size entries */
104
105        u_int32_t last_expired ;    /* do not expire too frequently */
106        int backlogged ;        /* #active queues for this flowset */
107
108        /* RED parameters */
109#define SCALE_RED               16
110#define SCALE(x)                ( (x) << SCALE_RED )
111#define SCALE_VAL(x)            ( (x) >> SCALE_RED )
112#define SCALE_MUL(x,y)          ( ( (x) * (y) ) >> SCALE_RED )
113        int w_q ;           /* queue weight (scaled) */
114        int max_th ;        /* maximum threshold for queue (scaled) */
115        int min_th ;        /* minimum threshold for queue (scaled) */
116        int max_p ;         /* maximum value for p_b (scaled) */
117        u_int c_1 ;         /* max_p/(max_th-min_th) (scaled) */
118        u_int c_2 ;         /* max_p*min_th/(max_th-min_th) (scaled) */
119        u_int c_3 ;         /* for GRED, (1-max_p)/max_th (scaled) */
120        u_int c_4 ;         /* for GRED, 1 - 2*max_p (scaled) */
121        u_int * w_q_lookup ;    /* lookup table for computing (1-w_q)^t */
122        u_int lookup_depth ;    /* depth of lookup table */
123        int lookup_step ;       /* granularity inside the lookup table */
124        int lookup_weight ;     /* equal to (1-w_q)^t / (1-w_q)^(t+1) */
125        int avg_pkt_size ;      /* medium packet size */
126        int max_pkt_size ;      /* max packet size */
127};
128SLIST_HEAD(dn_flow_set_head, dn_flow_set);
129
130#define DN_IS_PIPE              0x4000
131#define DN_IS_QUEUE             0x8000
132struct dn_flow_queue7 {
133        struct dn_flow_queue7 *next ;
134        struct ipfw_flow_id id ;
135
136        struct mbuf *head, *tail ;  /* queue of packets */
137        u_int len ;
138        u_int len_bytes ;
139
140        u_long numbytes;
141
142        u_int64_t tot_pkts ;    /* statistics counters  */
143        u_int64_t tot_bytes ;
144        u_int32_t drops ;
145
146        int hash_slot ;     /* debugging/diagnostic */
147
148        /* RED parameters */
149        int avg ;                   /* average queue length est. (scaled) */
150        int count ;                 /* arrivals since last RED drop */
151        int random ;                /* random value (scaled) */
152        u_int32_t q_time;      /* start of queue idle time */
153
154        /* WF2Q+ support */
155        struct dn_flow_set *fs ;    /* parent flow set */
156        int heap_pos ;      /* position (index) of struct in heap */
157        int64_t sched_time ;     /* current time when queue enters ready_heap */
158
159        int64_t S,F ;        /* start time, finish time */
160};
161
162struct dn_pipe7 {        /* a pipe */
163        SLIST_ENTRY(dn_pipe7)    next;   /* linked list in a hash slot */
164
165        int pipe_nr ;       /* number   */
166        int bandwidth;      /* really, bytes/tick.  */
167        int delay ;         /* really, ticks    */
168
169        struct  mbuf *head, *tail ; /* packets in delay line */
170
171        /* WF2Q+ */
172        struct dn_heap7 scheduler_heap ; /* top extract - key Finish time*/
173        struct dn_heap7 not_eligible_heap; /* top extract- key Start time */
174        struct dn_heap7 idle_heap ; /* random extract - key Start=Finish time */
175
176        int64_t V ;          /* virtual time */
177        int sum;            /* sum of weights of all active sessions */
178
179        int numbytes;
180
181        int64_t sched_time ;     /* time pipe was scheduled in ready_heap */
182
183        /*
184        * When the tx clock come from an interface (if_name[0] != '\0'), its name
185        * is stored below, whereas the ifp is filled when the rule is configured.
186        */
187        char if_name[IFNAMSIZ];
188        struct ifnet *ifp ;
189        int ready ; /* set if ifp != NULL and we got a signal from it */
190
191        struct dn_flow_set fs ; /* used with fixed-rate flows */
192};
193SLIST_HEAD(dn_pipe_head7, dn_pipe7);
194
195
196/* FREEBSD8 ip_dummynet.h r196045 */
197struct dn_flow_queue8 {
198        struct dn_flow_queue8 *next ;
199        struct ipfw_flow_id id ;
200
201        struct mbuf *head, *tail ;  /* queue of packets */
202        u_int len ;
203        u_int len_bytes ;
204
205        uint64_t numbytes ;     /* credit for transmission (dynamic queues) */
206        int64_t extra_bits;     /* extra bits simulating unavailable channel */
207
208        u_int64_t tot_pkts ;    /* statistics counters  */
209        u_int64_t tot_bytes ;
210        u_int32_t drops ;
211
212        int hash_slot ;     /* debugging/diagnostic */
213
214        /* RED parameters */
215        int avg ;                   /* average queue length est. (scaled) */
216        int count ;                 /* arrivals since last RED drop */
217        int random ;                /* random value (scaled) */
218        int64_t idle_time;       /* start of queue idle time */
219
220        /* WF2Q+ support */
221        struct dn_flow_set *fs ;    /* parent flow set */
222        int heap_pos ;      /* position (index) of struct in heap */
223        int64_t sched_time ;     /* current time when queue enters ready_heap */
224
225        int64_t S,F ;        /* start time, finish time */
226};
227
228struct dn_pipe8 {        /* a pipe */
229        SLIST_ENTRY(dn_pipe8)    next;   /* linked list in a hash slot */
230
231        int pipe_nr ;       /* number   */
232        int bandwidth;      /* really, bytes/tick.  */
233        int delay ;         /* really, ticks    */
234
235        struct  mbuf *head, *tail ; /* packets in delay line */
236
237        /* WF2Q+ */
238        struct dn_heap7 scheduler_heap ; /* top extract - key Finish time*/
239        struct dn_heap7 not_eligible_heap; /* top extract- key Start time */
240        struct dn_heap7 idle_heap ; /* random extract - key Start=Finish time */
241
242        int64_t V ;          /* virtual time */
243        int sum;            /* sum of weights of all active sessions */
244
245        /* Same as in dn_flow_queue, numbytes can become large */
246        int64_t numbytes;       /* bits I can transmit (more or less). */
247        uint64_t burst;     /* burst size, scaled: bits * hz */
248
249        int64_t sched_time ;     /* time pipe was scheduled in ready_heap */
250        int64_t idle_time;       /* start of pipe idle time */
251
252        char if_name[IFNAMSIZ];
253        struct ifnet *ifp ;
254        int ready ; /* set if ifp != NULL and we got a signal from it */
255
256        struct dn_flow_set fs ; /* used with fixed-rate flows */
257
258    /* fields to simulate a delay profile */
259#define ED_MAX_NAME_LEN     32
260        char name[ED_MAX_NAME_LEN];
261        int loss_level;
262        int samples_no;
263        int *samples;
264};
265
266#define ED_MAX_SAMPLES_NO   1024
267struct dn_pipe_max8 {
268        struct dn_pipe8 pipe;
269        int samples[ED_MAX_SAMPLES_NO];
270};
271SLIST_HEAD(dn_pipe_head8, dn_pipe8);
272
273/*
274 * Changes from 7.2 to 8:
275 * dn_pipe:
276 *      numbytes from int to int64_t
277 *      add burst (int64_t)
278 *      add idle_time (int64_t)
279 *      add profile
280 *      add struct dn_pipe_max
281 *      add flag DN_HAS_PROFILE
282 *
283 * dn_flow_queue
284 *      numbytes from u_long to int64_t
285 *      add extra_bits (int64_t)
286 *      q_time from u_int32_t to int64_t and name idle_time
287 *
288 * dn_flow_set unchanged
289 *
290 */
291
292/* NOTE:XXX copied from dummynet.c */
293#define O_NEXT(p, len) ((void *)((char *)p + len))
294static void
295oid_fill(struct dn_id *oid, int len, int type, uintptr_t id)
296{
297        oid->len = len;
298        oid->type = type;
299        oid->subtype = 0;
300        oid->id = id;
301}
302/* make room in the buffer and move the pointer forward */
303static void *
304o_next(struct dn_id **o, int len, int type)
305{
306        struct dn_id *ret = *o;
307        oid_fill(ret, len, type, 0);
308        *o = O_NEXT(*o, len);
309        return ret;
310}
311
312
313static size_t pipesize7 = sizeof(struct dn_pipe7);
314static size_t pipesize8 = sizeof(struct dn_pipe8);
315static size_t pipesizemax8 = sizeof(struct dn_pipe_max8);
316
317/* Indicate 'ipfw' version
318 * 1: from FreeBSD 7.2
319 * 0: from FreeBSD 8
320 * -1: unknow (for now is unused)
321 *
322 * It is update when a IP_DUMMYNET_DEL or IP_DUMMYNET_CONFIGURE request arrives
323 * NOTE: if a IP_DUMMYNET_GET arrives and the 'ipfw' version is unknow,
324 *       it is suppose to be the FreeBSD 8 version.
325 */
326static int is7 = 0;
327
328static int
329convertflags2new(int src)
330{
331        int dst = 0;
332
333        if (src & DNOLD_HAVE_FLOW_MASK)
334                dst |= DN_HAVE_MASK;
335        if (src & DNOLD_QSIZE_IS_BYTES)
336                dst |= DN_QSIZE_BYTES;
337        if (src & DNOLD_NOERROR)
338                dst |= DN_NOERROR;
339        if (src & DNOLD_IS_RED)
340                dst |= DN_IS_RED;
341        if (src & DNOLD_IS_GENTLE_RED)
342                dst |= DN_IS_GENTLE_RED;
343        if (src & DNOLD_HAS_PROFILE)
344                dst |= DN_HAS_PROFILE;
345
346        return dst;
347}
348
349static int
350convertflags2old(int src)
351{
352        int dst = 0;
353
354        if (src & DN_HAVE_MASK)
355                dst |= DNOLD_HAVE_FLOW_MASK;
356        if (src & DN_IS_RED)
357                dst |= DNOLD_IS_RED;
358        if (src & DN_IS_GENTLE_RED)
359                dst |= DNOLD_IS_GENTLE_RED;
360        if (src & DN_NOERROR)
361                dst |= DNOLD_NOERROR;
362        if (src & DN_HAS_PROFILE)
363                dst |= DNOLD_HAS_PROFILE;
364        if (src & DN_QSIZE_BYTES)
365                dst |= DNOLD_QSIZE_IS_BYTES;
366
367        return dst;
368}
369
370static int
371dn_compat_del(void *v)
372{
373        struct dn_pipe7 *p = (struct dn_pipe7 *) v;
374        struct dn_pipe8 *p8 = (struct dn_pipe8 *) v;
375        struct {
376                struct dn_id oid;
377                uintptr_t a[1]; /* add more if we want a list */
378        } cmd;
379
380        /* XXX DN_API_VERSION ??? */
381        oid_fill((void *)&cmd, sizeof(cmd), DN_CMD_DELETE, DN_API_VERSION);
382
383        if (is7) {
384                if (p->pipe_nr == 0 && p->fs.fs_nr == 0)
385                        return EINVAL;
386                if (p->pipe_nr != 0 && p->fs.fs_nr != 0)
387                        return EINVAL;
388        } else {
389                if (p8->pipe_nr == 0 && p8->fs.fs_nr == 0)
390                        return EINVAL;
391                if (p8->pipe_nr != 0 && p8->fs.fs_nr != 0)
392                        return EINVAL;
393        }
394
395        if (p->pipe_nr != 0) { /* pipe x delete */
396                cmd.a[0] = p->pipe_nr;
397                cmd.oid.subtype = DN_LINK;
398        } else { /* queue x delete */
399                cmd.oid.subtype = DN_FS;
400                cmd.a[0] = (is7) ? p->fs.fs_nr : p8->fs.fs_nr;
401        }
402
403        return do_config(&cmd, cmd.oid.len);
404}
405
406static int
407dn_compat_config_queue(struct dn_fs *fs, void* v)
408{
409        struct dn_pipe7 *p7 = (struct dn_pipe7 *)v;
410        struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
411        struct dn_flow_set *f;
412
413        if (is7)
414                f = &p7->fs;
415        else
416                f = &p8->fs;
417
418        fs->fs_nr = f->fs_nr;
419        fs->sched_nr = f->parent_nr;
420        fs->flow_mask = f->flow_mask;
421        fs->buckets = f->rq_size;
422        fs->qsize = f->qsize;
423        fs->plr = f->plr;
424        fs->par[0] = f->weight;
425        fs->flags = convertflags2new(f->flags_fs);
426        if (fs->flags & DN_IS_GENTLE_RED || fs->flags & DN_IS_RED) {
427                fs->w_q = f->w_q;
428                fs->max_th = f->max_th;
429                fs->min_th = f->min_th;
430                fs->max_p = f->max_p;
431        }
432
433        return 0;
434}
435
436static int
437dn_compat_config_pipe(struct dn_sch *sch, struct dn_link *p,
438                      struct dn_fs *fs, void* v)
439{
440        struct dn_pipe7 *p7 = (struct dn_pipe7 *)v;
441        struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
442        int i = p7->pipe_nr;
443
444        sch->sched_nr = i;
445        sch->oid.subtype = 0;
446        p->link_nr = i;
447        fs->fs_nr = i + 2*DN_MAX_ID;
448        fs->sched_nr = i + DN_MAX_ID;
449
450        /* Common to 7 and 8 */
451        p->bandwidth = p7->bandwidth;
452        p->delay = p7->delay;
453        if (!is7) {
454                /* FreeBSD 8 has burst  */
455                p->burst = p8->burst;
456        }
457
458        /* fill the fifo flowset */
459        dn_compat_config_queue(fs, v);
460        fs->fs_nr = i + 2*DN_MAX_ID;
461        fs->sched_nr = i + DN_MAX_ID;
462
463        /* Move scheduler related parameter from fs to sch */
464        sch->buckets = fs->buckets; /*XXX*/
465        fs->buckets = 0;
466        if (fs->flags & DN_HAVE_MASK) {
467                sch->flags |= DN_HAVE_MASK;
468                fs->flags &= ~DN_HAVE_MASK;
469                sch->sched_mask = fs->flow_mask;
470                bzero(&fs->flow_mask, sizeof(struct ipfw_flow_id));
471        }
472
473        return 0;
474}
475
476static int
477dn_compat_config_profile(struct dn_profile *pf, struct dn_link *p,
478                         void *v)
479{
480        struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
481
482        p8->samples = &(((struct dn_pipe_max8 *)p8)->samples[0]);
483       
484        pf->link_nr = p->link_nr;
485        pf->loss_level = p8->loss_level;
486//      pf->bandwidth = p->bandwidth; //XXX bandwidth redundant?
487        pf->samples_no = p8->samples_no;
488        strncpy(pf->name, p8->name,sizeof(pf->name));
489        bcopy(p8->samples, pf->samples, sizeof(pf->samples));
490
491        return 0;
492}
493
494/*
495 * If p->pipe_nr != 0 the command is 'pipe x config', so need to create
496 * the three main struct, else only a flowset is created
497 */
498static int
499dn_compat_configure(void *v)
500{
501        struct dn_id *buf = NULL, *base;
502        struct dn_sch *sch = NULL;
503        struct dn_link *p = NULL;
504        struct dn_fs *fs = NULL;
505        struct dn_profile *pf = NULL;
506        int lmax;
507        int error;
508
509        struct dn_pipe7 *p7 = (struct dn_pipe7 *)v;
510        struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
511
512        int i; /* number of object to configure */
513
514        lmax = sizeof(struct dn_id);    /* command header */
515        lmax += sizeof(struct dn_sch) + sizeof(struct dn_link) +
516                sizeof(struct dn_fs) + sizeof(struct dn_profile);
517
518        base = buf = malloc(lmax, M_DUMMYNET, M_WAIT|M_ZERO);
519        o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIG);
520        base->id = DN_API_VERSION;
521
522        /* pipe_nr is the same in p7 and p8 */
523        i = p7->pipe_nr;
524        if (i != 0) { /* pipe config */
525                sch = o_next(&buf, sizeof(*sch), DN_SCH);
526                p = o_next(&buf, sizeof(*p), DN_LINK);
527                fs = o_next(&buf, sizeof(*fs), DN_FS);
528
529                error = dn_compat_config_pipe(sch, p, fs, v);
530                if (error) {
531                        free(buf, M_DUMMYNET);
532                        return error;
533                }
534                if (!is7 && p8->samples_no > 0) {
535                        /* Add profiles*/
536                        pf = o_next(&buf, sizeof(*pf), DN_PROFILE);
537                        error = dn_compat_config_profile(pf, p, v);
538                        if (error) {
539                                free(buf, M_DUMMYNET);
540                                return error;
541                        }
542                }
543        } else { /* queue config */
544                fs = o_next(&buf, sizeof(*fs), DN_FS);
545                error = dn_compat_config_queue(fs, v);
546                if (error) {
547                        free(buf, M_DUMMYNET);
548                        return error;
549                }
550        }
551        error = do_config(base, (char *)buf - (char *)base);
552
553        if (buf)
554                free(buf, M_DUMMYNET);
555        return error;
556}
557
558int
559dn_compat_calc_size(void)
560{
561        int need = 0;
562        /* XXX use FreeBSD 8 struct size */
563        /* NOTE:
564         * - half scheduler:            schk_count/2
565         * - all flowset:               fsk_count
566         * - all flowset queues:        queue_count
567         * - all pipe queue:            si_count
568         */
569        need += dn_cfg.schk_count * sizeof(struct dn_pipe8) / 2;
570        need += dn_cfg.fsk_count * sizeof(struct dn_flow_set);
571        need += dn_cfg.si_count * sizeof(struct dn_flow_queue8);
572        need += dn_cfg.queue_count * sizeof(struct dn_flow_queue8);
573
574        return need;
575}
576
577int
578dn_c_copy_q (void *_ni, void *arg)
579{
580        struct copy_args *a = arg;
581        struct dn_flow_queue7 *fq7 = (struct dn_flow_queue7 *)*a->start;
582        struct dn_flow_queue8 *fq8 = (struct dn_flow_queue8 *)*a->start;
583        struct dn_flow *ni = (struct dn_flow *)_ni;
584        int size = 0;
585
586        /* XXX hash slot not set */
587        /* No difference between 7.2/8 */
588        fq7->len = ni->length;
589        fq7->len_bytes = ni->len_bytes;
590        fq7->id = ni->fid;
591
592        if (is7) {
593                size = sizeof(struct dn_flow_queue7);
594                fq7->tot_pkts = ni->tot_pkts;
595                fq7->tot_bytes = ni->tot_bytes;
596                fq7->drops = ni->drops;
597        } else {
598                size = sizeof(struct dn_flow_queue8);
599                fq8->tot_pkts = ni->tot_pkts;
600                fq8->tot_bytes = ni->tot_bytes;
601                fq8->drops = ni->drops;
602        }
603
604        *a->start += size;
605        return 0;
606}
607
608int
609dn_c_copy_pipe(struct dn_schk *s, struct copy_args *a, int nq)
610{
611        struct dn_link *l = &s->link;
612        struct dn_fsk *f = s->fs;
613
614        struct dn_pipe7 *pipe7 = (struct dn_pipe7 *)*a->start;
615        struct dn_pipe8 *pipe8 = (struct dn_pipe8 *)*a->start;
616        struct dn_flow_set *fs;
617        int size = 0;
618
619        if (is7) {
620                fs = &pipe7->fs;
621                size = sizeof(struct dn_pipe7);
622        } else {
623                fs = &pipe8->fs;
624                size = sizeof(struct dn_pipe8);
625        }
626
627        /* These 4 field are the same in pipe7 and pipe8 */
628        pipe7->next.sle_next = (struct dn_pipe7 *)DN_IS_PIPE;
629        pipe7->bandwidth = l->bandwidth;
630        pipe7->delay = l->delay * 1000 / hz;
631        pipe7->pipe_nr = l->link_nr - DN_MAX_ID;
632
633        if (!is7) {
634                if (s->profile) {
635                        struct dn_profile *pf = s->profile;
636                        strncpy(pipe8->name, pf->name, sizeof(pf->name));
637                        pipe8->loss_level = pf->loss_level;
638                        pipe8->samples_no = pf->samples_no;
639                }
640                pipe8->burst = div64(l->burst , 8 * hz);
641        }
642
643        fs->flow_mask = s->sch.sched_mask;
644        fs->rq_size = s->sch.buckets ? s->sch.buckets : 1;
645
646        fs->parent_nr = l->link_nr - DN_MAX_ID;
647        fs->qsize = f->fs.qsize;
648        fs->plr = f->fs.plr;
649        fs->w_q = f->fs.w_q;
650        fs->max_th = f->max_th;
651        fs->min_th = f->min_th;
652        fs->max_p = f->fs.max_p;
653        fs->rq_elements = nq;
654
655        fs->flags_fs = convertflags2old(f->fs.flags);
656
657        *a->start += size;
658        return 0;
659}
660
661
662int
663dn_compat_copy_pipe(struct copy_args *a, void *_o)
664{
665        int have = a->end - *a->start;
666        int need = 0;
667        int pipe_size = sizeof(struct dn_pipe8);
668        int queue_size = sizeof(struct dn_flow_queue8);
669        int n_queue = 0; /* number of queues */
670
671        struct dn_schk *s = (struct dn_schk *)_o;
672        /* calculate needed space:
673         * - struct dn_pipe
674         * - if there are instances, dn_queue * n_instances
675         */
676        n_queue = (s->sch.flags & DN_HAVE_MASK ? dn_ht_entries(s->siht) :
677                                                (s->siht ? 1 : 0));
678        need = pipe_size + queue_size * n_queue;
679        if (have < need) {
680                D("have %d < need %d", have, need);
681                return 1;
682        }
683        /* copy pipe */
684        dn_c_copy_pipe(s, a, n_queue);
685
686        /* copy queues */
687        if (s->sch.flags & DN_HAVE_MASK)
688                dn_ht_scan(s->siht, dn_c_copy_q, a);
689        else if (s->siht)
690                dn_c_copy_q(s->siht, a);
691        return 0;
692}
693
694int
695dn_c_copy_fs(struct dn_fsk *f, struct copy_args *a, int nq)
696{
697        struct dn_flow_set *fs = (struct dn_flow_set *)*a->start;
698
699        fs->next.sle_next = (struct dn_flow_set *)DN_IS_QUEUE;
700        fs->fs_nr = f->fs.fs_nr;
701        fs->qsize = f->fs.qsize;
702        fs->plr = f->fs.plr;
703        fs->w_q = f->fs.w_q;
704        fs->max_th = f->max_th;
705        fs->min_th = f->min_th;
706        fs->max_p = f->fs.max_p;
707        fs->flow_mask = f->fs.flow_mask;
708        fs->rq_elements = nq;
709        fs->rq_size = (f->fs.buckets ? f->fs.buckets : 1);
710        fs->parent_nr = f->fs.sched_nr;
711        fs->weight = f->fs.par[0];
712
713        fs->flags_fs = convertflags2old(f->fs.flags);
714        *a->start += sizeof(struct dn_flow_set);
715        return 0;
716}
717
718int
719dn_compat_copy_queue(struct copy_args *a, void *_o)
720{
721        int have = a->end - *a->start;
722        int need = 0;
723        int fs_size = sizeof(struct dn_flow_set);
724        int queue_size = sizeof(struct dn_flow_queue8);
725
726        struct dn_fsk *fs = (struct dn_fsk *)_o;
727        int n_queue = 0; /* number of queues */
728
729        n_queue = (fs->fs.flags & DN_HAVE_MASK ? dn_ht_entries(fs->qht) :
730                                                (fs->qht ? 1 : 0));
731
732        need = fs_size + queue_size * n_queue;
733        if (have < need) {
734                D("have < need");
735                return 1;
736        }
737
738        /* copy flowset */
739        dn_c_copy_fs(fs, a, n_queue);
740
741        /* copy queues */
742        if (fs->fs.flags & DN_HAVE_MASK)
743                dn_ht_scan(fs->qht, dn_c_copy_q, a);
744        else if (fs->qht)
745                dn_c_copy_q(fs->qht, a);
746
747        return 0;
748}
749
750int
751copy_data_helper_compat(void *_o, void *_arg)
752{
753        struct copy_args *a = _arg;
754
755        if (a->type == DN_COMPAT_PIPE) {
756                struct dn_schk *s = _o;
757                if (s->sch.oid.subtype != 1 || s->sch.sched_nr <= DN_MAX_ID) {
758                        return 0;       /* not old type */
759                }
760                /* copy pipe parameters, and if instance exists, copy
761                 * other parameters and eventually queues.
762                 */
763                if(dn_compat_copy_pipe(a, _o))
764                        return DNHT_SCAN_END;
765        } else if (a->type == DN_COMPAT_QUEUE) {
766                struct dn_fsk *fs = _o;
767                if (fs->fs.fs_nr >= DN_MAX_ID)
768                        return 0;
769                if (dn_compat_copy_queue(a, _o))
770                        return DNHT_SCAN_END;
771        }
772        return 0;
773}
774
775/* Main function to manage old requests */
776int
777ip_dummynet_compat(struct sockopt *sopt)
778{
779        int error=0;
780        void *v = NULL;
781        struct dn_id oid;
782
783        /* Lenght of data, used to found ipfw version... */
784        int len = sopt->sopt_valsize;
785
786        /* len can be 0 if command was dummynet_flush */
787        if (len == pipesize7) {
788                D("setting compatibility with FreeBSD 7.2");
789                is7 = 1;
790        }
791        else if (len == pipesize8 || len == pipesizemax8) {
792                D("setting compatibility with FreeBSD 8");
793                is7 = 0;
794        }
795
796        switch (sopt->sopt_name) {
797        default:
798                printf("dummynet: -- unknown option %d", sopt->sopt_name);
799                error = EINVAL;
800                break;
801
802        case IP_DUMMYNET_FLUSH:
803                oid_fill(&oid, sizeof(oid), DN_CMD_FLUSH, DN_API_VERSION);
804                do_config(&oid, oid.len);
805                break;
806
807        case IP_DUMMYNET_DEL:
808                v = malloc(len, M_TEMP, M_WAITOK);
809                error = sooptcopyin(sopt, v, len, len);
810                if (error)
811                        break;
812                error = dn_compat_del(v);
813                free(v, M_TEMP);
814                break;
815
816        case IP_DUMMYNET_CONFIGURE:
817                v = malloc(len, M_TEMP, M_WAITOK);
818                error = sooptcopyin(sopt, v, len, len);
819                if (error)
820                        break;
821                error = dn_compat_configure(v);
822                free(v, M_TEMP);
823                break;
824
825        case IP_DUMMYNET_GET: {
826                void *buf;
827                int ret;
828                int original_size = sopt->sopt_valsize;
829                int size;
830
831                ret = dummynet_get(sopt, &buf);
832                if (ret)
833                        return 0;//XXX ?
834                size = sopt->sopt_valsize;
835                sopt->sopt_valsize = original_size;
836                D("size=%d, buf=%p", size, buf);
837                ret = sooptcopyout(sopt, buf, size);
838                if (ret)
839                        printf("  %s ERROR sooptcopyout\n", __FUNCTION__);
840                if (buf)
841                        free(buf, M_DUMMYNET);
842            }
843        }
844
845        return error;
846}
847
848
Note: See TracBrowser for help on using the repository browser.