source: rtems-libbsd/freebsd/sys/netinet/ipfw/ip_dn_glue.c @ f244de9

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f244de9 was f244de9, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 07:56:38

Rename rtems-bsd-config.h

Rename rtems-bsd-config.h in rtems-bsd-kernel-space.h.

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