2 * Copyright (c) 2010 Riccardo Panicucci, Universita` di Pisa
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $Id: ip_dn_glue.c 6031 2010-04-09 15:25:41Z svn_panicucci $
30 * Binary compatibility support for /sbin/ipfw RELENG_7 and RELENG_8
33 #include "opt_inet6.h"
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
39 #include <sys/kernel.h>
41 #include <sys/module.h>
44 #include <sys/rwlock.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
48 #include <sys/taskqueue.h>
49 #include <net/if.h> /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */
50 #include <netinet/in.h>
51 #include <netinet/ip_var.h> /* ip_output(), IP_FORWARDING */
52 #include <netinet/ip_fw.h>
53 #include <netinet/ipfw/ip_fw_private.h>
54 #include <netinet/ipfw/dn_heap.h>
55 #include <netinet/ip_dummynet.h>
56 #include <netinet/ipfw/ip_dn_private.h>
57 #include <netinet/ipfw/dn_sched.h>
59 /* FREEBSD7.2 ip_dummynet.h r191715*/
61 struct dn_heap_entry7 {
62 int64_t key; /* sorting key. Topmost element is smallest one */
63 void *object; /* object pointer */
69 int offset; /* XXX if > 0 this is the offset of direct ptr to obj */
70 struct dn_heap_entry7 *p; /* really an array of "size" entries */
73 /* Common to 7.2 and 8 */
75 SLIST_ENTRY(dn_flow_set) next; /* linked list in a hash slot */
77 u_short fs_nr ; /* flow_set number */
79 #define DNOLD_HAVE_FLOW_MASK 0x0001
80 #define DNOLD_IS_RED 0x0002
81 #define DNOLD_IS_GENTLE_RED 0x0004
82 #define DNOLD_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */
83 #define DNOLD_NOERROR 0x0010 /* do not report ENOBUFS on drops */
84 #define DNOLD_HAS_PROFILE 0x0020 /* the pipe has a delay profile. */
85 #define DNOLD_IS_PIPE 0x4000
86 #define DNOLD_IS_QUEUE 0x8000
88 struct dn_pipe7 *pipe ; /* pointer to parent pipe */
89 u_short parent_nr ; /* parent pipe#, 0 if local to a pipe */
91 int weight ; /* WFQ queue weight */
92 int qsize ; /* queue size in slots or bytes */
93 int plr ; /* pkt loss rate (2^31-1 means 100%) */
95 struct ipfw_flow_id flow_mask ;
97 /* hash table of queues onto this flow_set */
98 int rq_size ; /* number of slots */
99 int rq_elements ; /* active elements */
100 struct dn_flow_queue7 **rq; /* array of rq_size entries */
102 u_int32_t last_expired ; /* do not expire too frequently */
103 int backlogged ; /* #active queues for this flowset */
107 #define SCALE(x) ( (x) << SCALE_RED )
108 #define SCALE_VAL(x) ( (x) >> SCALE_RED )
109 #define SCALE_MUL(x,y) ( ( (x) * (y) ) >> SCALE_RED )
110 int w_q ; /* queue weight (scaled) */
111 int max_th ; /* maximum threshold for queue (scaled) */
112 int min_th ; /* minimum threshold for queue (scaled) */
113 int max_p ; /* maximum value for p_b (scaled) */
114 u_int c_1 ; /* max_p/(max_th-min_th) (scaled) */
115 u_int c_2 ; /* max_p*min_th/(max_th-min_th) (scaled) */
116 u_int c_3 ; /* for GRED, (1-max_p)/max_th (scaled) */
117 u_int c_4 ; /* for GRED, 1 - 2*max_p (scaled) */
118 u_int * w_q_lookup ; /* lookup table for computing (1-w_q)^t */
119 u_int lookup_depth ; /* depth of lookup table */
120 int lookup_step ; /* granularity inside the lookup table */
121 int lookup_weight ; /* equal to (1-w_q)^t / (1-w_q)^(t+1) */
122 int avg_pkt_size ; /* medium packet size */
123 int max_pkt_size ; /* max packet size */
125 SLIST_HEAD(dn_flow_set_head, dn_flow_set);
127 #define DN_IS_PIPE 0x4000
128 #define DN_IS_QUEUE 0x8000
129 struct dn_flow_queue7 {
130 struct dn_flow_queue7 *next ;
131 struct ipfw_flow_id id ;
133 struct mbuf *head, *tail ; /* queue of packets */
139 u_int64_t tot_pkts ; /* statistics counters */
140 u_int64_t tot_bytes ;
143 int hash_slot ; /* debugging/diagnostic */
146 int avg ; /* average queue length est. (scaled) */
147 int count ; /* arrivals since last RED drop */
148 int random ; /* random value (scaled) */
149 u_int32_t q_time; /* start of queue idle time */
152 struct dn_flow_set *fs ; /* parent flow set */
153 int heap_pos ; /* position (index) of struct in heap */
154 int64_t sched_time ; /* current time when queue enters ready_heap */
156 int64_t S,F ; /* start time, finish time */
159 struct dn_pipe7 { /* a pipe */
160 SLIST_ENTRY(dn_pipe7) next; /* linked list in a hash slot */
162 int pipe_nr ; /* number */
163 int bandwidth; /* really, bytes/tick. */
164 int delay ; /* really, ticks */
166 struct mbuf *head, *tail ; /* packets in delay line */
169 struct dn_heap7 scheduler_heap ; /* top extract - key Finish time*/
170 struct dn_heap7 not_eligible_heap; /* top extract- key Start time */
171 struct dn_heap7 idle_heap ; /* random extract - key Start=Finish time */
173 int64_t V ; /* virtual time */
174 int sum; /* sum of weights of all active sessions */
178 int64_t sched_time ; /* time pipe was scheduled in ready_heap */
181 * When the tx clock come from an interface (if_name[0] != '\0'), its name
182 * is stored below, whereas the ifp is filled when the rule is configured.
184 char if_name[IFNAMSIZ];
186 int ready ; /* set if ifp != NULL and we got a signal from it */
188 struct dn_flow_set fs ; /* used with fixed-rate flows */
190 SLIST_HEAD(dn_pipe_head7, dn_pipe7);
193 /* FREEBSD8 ip_dummynet.h r196045 */
194 struct dn_flow_queue8 {
195 struct dn_flow_queue8 *next ;
196 struct ipfw_flow_id id ;
198 struct mbuf *head, *tail ; /* queue of packets */
202 uint64_t numbytes ; /* credit for transmission (dynamic queues) */
203 int64_t extra_bits; /* extra bits simulating unavailable channel */
205 u_int64_t tot_pkts ; /* statistics counters */
206 u_int64_t tot_bytes ;
209 int hash_slot ; /* debugging/diagnostic */
212 int avg ; /* average queue length est. (scaled) */
213 int count ; /* arrivals since last RED drop */
214 int random ; /* random value (scaled) */
215 int64_t idle_time; /* start of queue idle time */
218 struct dn_flow_set *fs ; /* parent flow set */
219 int heap_pos ; /* position (index) of struct in heap */
220 int64_t sched_time ; /* current time when queue enters ready_heap */
222 int64_t S,F ; /* start time, finish time */
225 struct dn_pipe8 { /* a pipe */
226 SLIST_ENTRY(dn_pipe8) next; /* linked list in a hash slot */
228 int pipe_nr ; /* number */
229 int bandwidth; /* really, bytes/tick. */
230 int delay ; /* really, ticks */
232 struct mbuf *head, *tail ; /* packets in delay line */
235 struct dn_heap7 scheduler_heap ; /* top extract - key Finish time*/
236 struct dn_heap7 not_eligible_heap; /* top extract- key Start time */
237 struct dn_heap7 idle_heap ; /* random extract - key Start=Finish time */
239 int64_t V ; /* virtual time */
240 int sum; /* sum of weights of all active sessions */
242 /* Same as in dn_flow_queue, numbytes can become large */
243 int64_t numbytes; /* bits I can transmit (more or less). */
244 uint64_t burst; /* burst size, scaled: bits * hz */
246 int64_t sched_time ; /* time pipe was scheduled in ready_heap */
247 int64_t idle_time; /* start of pipe idle time */
249 char if_name[IFNAMSIZ];
251 int ready ; /* set if ifp != NULL and we got a signal from it */
253 struct dn_flow_set fs ; /* used with fixed-rate flows */
255 /* fields to simulate a delay profile */
256 #define ED_MAX_NAME_LEN 32
257 char name[ED_MAX_NAME_LEN];
263 #define ED_MAX_SAMPLES_NO 1024
264 struct dn_pipe_max8 {
265 struct dn_pipe8 pipe;
266 int samples[ED_MAX_SAMPLES_NO];
268 SLIST_HEAD(dn_pipe_head8, dn_pipe8);
271 * Changes from 7.2 to 8:
273 * numbytes from int to int64_t
274 * add burst (int64_t)
275 * add idle_time (int64_t)
277 * add struct dn_pipe_max
278 * add flag DN_HAS_PROFILE
281 * numbytes from u_long to int64_t
282 * add extra_bits (int64_t)
283 * q_time from u_int32_t to int64_t and name idle_time
285 * dn_flow_set unchanged
289 /* NOTE:XXX copied from dummynet.c */
290 #define O_NEXT(p, len) ((void *)((char *)p + len))
292 oid_fill(struct dn_id *oid, int len, int type, uintptr_t id)
299 /* make room in the buffer and move the pointer forward */
301 o_next(struct dn_id **o, int len, int type)
303 struct dn_id *ret = *o;
304 oid_fill(ret, len, type, 0);
305 *o = O_NEXT(*o, len);
310 static size_t pipesize7 = sizeof(struct dn_pipe7);
311 static size_t pipesize8 = sizeof(struct dn_pipe8);
312 static size_t pipesizemax8 = sizeof(struct dn_pipe_max8);
314 /* Indicate 'ipfw' version
315 * 1: from FreeBSD 7.2
317 * -1: unknow (for now is unused)
319 * It is update when a IP_DUMMYNET_DEL or IP_DUMMYNET_CONFIGURE request arrives
320 * NOTE: if a IP_DUMMYNET_GET arrives and the 'ipfw' version is unknow,
321 * it is suppose to be the FreeBSD 8 version.
326 convertflags2new(int src)
330 if (src & DNOLD_HAVE_FLOW_MASK)
332 if (src & DNOLD_QSIZE_IS_BYTES)
333 dst |= DN_QSIZE_BYTES;
334 if (src & DNOLD_NOERROR)
336 if (src & DNOLD_IS_RED)
338 if (src & DNOLD_IS_GENTLE_RED)
339 dst |= DN_IS_GENTLE_RED;
340 if (src & DNOLD_HAS_PROFILE)
341 dst |= DN_HAS_PROFILE;
347 convertflags2old(int src)
351 if (src & DN_HAVE_MASK)
352 dst |= DNOLD_HAVE_FLOW_MASK;
355 if (src & DN_IS_GENTLE_RED)
356 dst |= DNOLD_IS_GENTLE_RED;
357 if (src & DN_NOERROR)
358 dst |= DNOLD_NOERROR;
359 if (src & DN_HAS_PROFILE)
360 dst |= DNOLD_HAS_PROFILE;
361 if (src & DN_QSIZE_BYTES)
362 dst |= DNOLD_QSIZE_IS_BYTES;
368 dn_compat_del(void *v)
370 struct dn_pipe7 *p = (struct dn_pipe7 *) v;
371 struct dn_pipe8 *p8 = (struct dn_pipe8 *) v;
374 uintptr_t a[1]; /* add more if we want a list */
377 /* XXX DN_API_VERSION ??? */
378 oid_fill((void *)&cmd, sizeof(cmd), DN_CMD_DELETE, DN_API_VERSION);
381 if (p->pipe_nr == 0 && p->fs.fs_nr == 0)
383 if (p->pipe_nr != 0 && p->fs.fs_nr != 0)
386 if (p8->pipe_nr == 0 && p8->fs.fs_nr == 0)
388 if (p8->pipe_nr != 0 && p8->fs.fs_nr != 0)
392 if (p->pipe_nr != 0) { /* pipe x delete */
393 cmd.a[0] = p->pipe_nr;
394 cmd.oid.subtype = DN_LINK;
395 } else { /* queue x delete */
396 cmd.oid.subtype = DN_FS;
397 cmd.a[0] = (is7) ? p->fs.fs_nr : p8->fs.fs_nr;
400 return do_config(&cmd, cmd.oid.len);
404 dn_compat_config_queue(struct dn_fs *fs, void* v)
406 struct dn_pipe7 *p7 = (struct dn_pipe7 *)v;
407 struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
408 struct dn_flow_set *f;
415 fs->fs_nr = f->fs_nr;
416 fs->sched_nr = f->parent_nr;
417 fs->flow_mask = f->flow_mask;
418 fs->buckets = f->rq_size;
419 fs->qsize = f->qsize;
421 fs->par[0] = f->weight;
422 fs->flags = convertflags2new(f->flags_fs);
423 if (fs->flags & DN_IS_GENTLE_RED || fs->flags & DN_IS_RED) {
425 fs->max_th = f->max_th;
426 fs->min_th = f->min_th;
427 fs->max_p = f->max_p;
434 dn_compat_config_pipe(struct dn_sch *sch, struct dn_link *p,
435 struct dn_fs *fs, void* v)
437 struct dn_pipe7 *p7 = (struct dn_pipe7 *)v;
438 struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
442 sch->oid.subtype = 0;
444 fs->fs_nr = i + 2*DN_MAX_ID;
445 fs->sched_nr = i + DN_MAX_ID;
447 /* Common to 7 and 8 */
448 p->bandwidth = p7->bandwidth;
449 p->delay = p7->delay;
451 /* FreeBSD 8 has burst */
452 p->burst = p8->burst;
455 /* fill the fifo flowset */
456 dn_compat_config_queue(fs, v);
457 fs->fs_nr = i + 2*DN_MAX_ID;
458 fs->sched_nr = i + DN_MAX_ID;
460 /* Move scheduler related parameter from fs to sch */
461 sch->buckets = fs->buckets; /*XXX*/
463 if (fs->flags & DN_HAVE_MASK) {
464 sch->flags |= DN_HAVE_MASK;
465 fs->flags &= ~DN_HAVE_MASK;
466 sch->sched_mask = fs->flow_mask;
467 bzero(&fs->flow_mask, sizeof(struct ipfw_flow_id));
474 dn_compat_config_profile(struct dn_profile *pf, struct dn_link *p,
477 struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
479 p8->samples = &(((struct dn_pipe_max8 *)p8)->samples[0]);
481 pf->link_nr = p->link_nr;
482 pf->loss_level = p8->loss_level;
483 // pf->bandwidth = p->bandwidth; //XXX bandwidth redundant?
484 pf->samples_no = p8->samples_no;
485 strncpy(pf->name, p8->name,sizeof(pf->name));
486 bcopy(p8->samples, pf->samples, sizeof(pf->samples));
492 * If p->pipe_nr != 0 the command is 'pipe x config', so need to create
493 * the three main struct, else only a flowset is created
496 dn_compat_configure(void *v)
498 struct dn_id *buf = NULL, *base;
499 struct dn_sch *sch = NULL;
500 struct dn_link *p = NULL;
501 struct dn_fs *fs = NULL;
502 struct dn_profile *pf = NULL;
506 struct dn_pipe7 *p7 = (struct dn_pipe7 *)v;
507 struct dn_pipe8 *p8 = (struct dn_pipe8 *)v;
509 int i; /* number of object to configure */
511 lmax = sizeof(struct dn_id); /* command header */
512 lmax += sizeof(struct dn_sch) + sizeof(struct dn_link) +
513 sizeof(struct dn_fs) + sizeof(struct dn_profile);
515 base = buf = malloc(lmax, M_DUMMYNET, M_WAIT|M_ZERO);
516 o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIG);
517 base->id = DN_API_VERSION;
519 /* pipe_nr is the same in p7 and p8 */
521 if (i != 0) { /* pipe config */
522 sch = o_next(&buf, sizeof(*sch), DN_SCH);
523 p = o_next(&buf, sizeof(*p), DN_LINK);
524 fs = o_next(&buf, sizeof(*fs), DN_FS);
526 error = dn_compat_config_pipe(sch, p, fs, v);
528 free(buf, M_DUMMYNET);
531 if (!is7 && p8->samples_no > 0) {
533 pf = o_next(&buf, sizeof(*pf), DN_PROFILE);
534 error = dn_compat_config_profile(pf, p, v);
536 free(buf, M_DUMMYNET);
540 } else { /* queue config */
541 fs = o_next(&buf, sizeof(*fs), DN_FS);
542 error = dn_compat_config_queue(fs, v);
544 free(buf, M_DUMMYNET);
548 error = do_config(base, (char *)buf - (char *)base);
551 free(buf, M_DUMMYNET);
556 dn_compat_calc_size(void)
559 /* XXX use FreeBSD 8 struct size */
561 * - half scheduler: schk_count/2
562 * - all flowset: fsk_count
563 * - all flowset queues: queue_count
564 * - all pipe queue: si_count
566 need += dn_cfg.schk_count * sizeof(struct dn_pipe8) / 2;
567 need += dn_cfg.fsk_count * sizeof(struct dn_flow_set);
568 need += dn_cfg.si_count * sizeof(struct dn_flow_queue8);
569 need += dn_cfg.queue_count * sizeof(struct dn_flow_queue8);
575 dn_c_copy_q (void *_ni, void *arg)
577 struct copy_args *a = arg;
578 struct dn_flow_queue7 *fq7 = (struct dn_flow_queue7 *)*a->start;
579 struct dn_flow_queue8 *fq8 = (struct dn_flow_queue8 *)*a->start;
580 struct dn_flow *ni = (struct dn_flow *)_ni;
583 /* XXX hash slot not set */
584 /* No difference between 7.2/8 */
585 fq7->len = ni->length;
586 fq7->len_bytes = ni->len_bytes;
590 size = sizeof(struct dn_flow_queue7);
591 fq7->tot_pkts = ni->tot_pkts;
592 fq7->tot_bytes = ni->tot_bytes;
593 fq7->drops = ni->drops;
595 size = sizeof(struct dn_flow_queue8);
596 fq8->tot_pkts = ni->tot_pkts;
597 fq8->tot_bytes = ni->tot_bytes;
598 fq8->drops = ni->drops;
606 dn_c_copy_pipe(struct dn_schk *s, struct copy_args *a, int nq)
608 struct dn_link *l = &s->link;
609 struct dn_fsk *f = s->fs;
611 struct dn_pipe7 *pipe7 = (struct dn_pipe7 *)*a->start;
612 struct dn_pipe8 *pipe8 = (struct dn_pipe8 *)*a->start;
613 struct dn_flow_set *fs;
618 size = sizeof(struct dn_pipe7);
621 size = sizeof(struct dn_pipe8);
624 /* These 4 field are the same in pipe7 and pipe8 */
625 pipe7->next.sle_next = (struct dn_pipe7 *)DN_IS_PIPE;
626 pipe7->bandwidth = l->bandwidth;
627 pipe7->delay = l->delay;
628 pipe7->pipe_nr = l->link_nr - DN_MAX_ID;
632 struct dn_profile *pf = s->profile;
633 strncpy(pipe8->name, pf->name, sizeof(pf->name));
634 pipe8->loss_level = pf->loss_level;
635 pipe8->samples_no = pf->samples_no;
637 pipe8->burst = div64(l->burst , 8 * hz);
640 fs->flow_mask = s->sch.sched_mask;
641 fs->rq_size = s->sch.buckets ? s->sch.buckets : 1;
643 fs->parent_nr = l->link_nr - DN_MAX_ID;
644 fs->qsize = f->fs.qsize;
647 fs->max_th = f->max_th;
648 fs->min_th = f->min_th;
649 fs->max_p = f->fs.max_p;
650 fs->rq_elements = nq;
652 fs->flags_fs = convertflags2old(f->fs.flags);
660 dn_compat_copy_pipe(struct copy_args *a, void *_o)
662 int have = a->end - *a->start;
664 int pipe_size = sizeof(struct dn_pipe8);
665 int queue_size = sizeof(struct dn_flow_queue8);
666 int n_queue = 0; /* number of queues */
668 struct dn_schk *s = (struct dn_schk *)_o;
669 /* calculate needed space:
671 * - if there are instances, dn_queue * n_instances
673 n_queue = (s->sch.flags & DN_HAVE_MASK ? dn_ht_entries(s->siht) :
675 need = pipe_size + queue_size * n_queue;
677 D("have %d < need %d", have, need);
681 dn_c_copy_pipe(s, a, n_queue);
684 if (s->sch.flags & DN_HAVE_MASK)
685 dn_ht_scan(s->siht, dn_c_copy_q, a);
687 dn_c_copy_q(s->siht, a);
692 dn_c_copy_fs(struct dn_fsk *f, struct copy_args *a, int nq)
694 struct dn_flow_set *fs = (struct dn_flow_set *)*a->start;
696 fs->next.sle_next = (struct dn_flow_set *)DN_IS_QUEUE;
697 fs->fs_nr = f->fs.fs_nr;
698 fs->qsize = f->fs.qsize;
701 fs->max_th = f->max_th;
702 fs->min_th = f->min_th;
703 fs->max_p = f->fs.max_p;
704 fs->flow_mask = f->fs.flow_mask;
705 fs->rq_elements = nq;
706 fs->rq_size = (f->fs.buckets ? f->fs.buckets : 1);
707 fs->parent_nr = f->fs.sched_nr;
708 fs->weight = f->fs.par[0];
710 fs->flags_fs = convertflags2old(f->fs.flags);
711 *a->start += sizeof(struct dn_flow_set);
716 dn_compat_copy_queue(struct copy_args *a, void *_o)
718 int have = a->end - *a->start;
720 int fs_size = sizeof(struct dn_flow_set);
721 int queue_size = sizeof(struct dn_flow_queue8);
723 struct dn_fsk *fs = (struct dn_fsk *)_o;
724 int n_queue = 0; /* number of queues */
726 n_queue = (fs->fs.flags & DN_HAVE_MASK ? dn_ht_entries(fs->qht) :
729 need = fs_size + queue_size * n_queue;
736 dn_c_copy_fs(fs, a, n_queue);
739 if (fs->fs.flags & DN_HAVE_MASK)
740 dn_ht_scan(fs->qht, dn_c_copy_q, a);
742 dn_c_copy_q(fs->qht, a);
748 copy_data_helper_compat(void *_o, void *_arg)
750 struct copy_args *a = _arg;
752 if (a->type == DN_COMPAT_PIPE) {
753 struct dn_schk *s = _o;
754 if (s->sch.oid.subtype != 1 || s->sch.sched_nr <= DN_MAX_ID) {
755 return 0; /* not old type */
757 /* copy pipe parameters, and if instance exists, copy
758 * other parameters and eventually queues.
760 if(dn_compat_copy_pipe(a, _o))
761 return DNHT_SCAN_END;
762 } else if (a->type == DN_COMPAT_QUEUE) {
763 struct dn_fsk *fs = _o;
764 if (fs->fs.fs_nr >= DN_MAX_ID)
766 if (dn_compat_copy_queue(a, _o))
767 return DNHT_SCAN_END;
772 /* Main function to manage old requests */
774 ip_dummynet_compat(struct sockopt *sopt)
780 /* Lenght of data, used to found ipfw version... */
781 int len = sopt->sopt_valsize;
783 /* len can be 0 if command was dummynet_flush */
784 if (len == pipesize7) {
785 D("setting compatibility with FreeBSD 7.2");
788 else if (len == pipesize8 || len == pipesizemax8) {
789 D("setting compatibility with FreeBSD 8");
793 switch (sopt->sopt_name) {
795 printf("dummynet: -- unknown option %d", sopt->sopt_name);
799 case IP_DUMMYNET_FLUSH:
800 oid_fill(&oid, sizeof(oid), DN_CMD_FLUSH, DN_API_VERSION);
801 do_config(&oid, oid.len);
804 case IP_DUMMYNET_DEL:
805 v = malloc(len, M_TEMP, M_WAITOK);
806 error = sooptcopyin(sopt, v, len, len);
809 error = dn_compat_del(v);
813 case IP_DUMMYNET_CONFIGURE:
814 v = malloc(len, M_TEMP, M_WAITOK);
815 error = sooptcopyin(sopt, v, len, len);
818 error = dn_compat_configure(v);
822 case IP_DUMMYNET_GET: {
825 int original_size = sopt->sopt_valsize;
828 ret = dummynet_get(sopt, &buf);
831 size = sopt->sopt_valsize;
832 sopt->sopt_valsize = original_size;
833 D("size=%d, buf=%p", size, buf);
834 ret = sooptcopyout(sopt, buf, size);
836 printf(" %s ERROR sooptcopyout\n", __FUNCTION__);
838 free(buf, M_DUMMYNET);