Lines Matching +full:touch +full:- +full:key +full:- +full:connected

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Codel/FQ_Codel and PIE/FQ-PIE Code:
9 * Implemented by Rasool Al-Saadi <ralsaadi@swin.edu.au>
11 * Copyright (c) 1998-2002,2010 Luigi Rizzo, Universita` di Pisa
88 /*---- callout hooks. ----*/
131 /*----- end of callout hooks -----*/
143 if (d->type == type || (name && !strcasecmp(d->name, name))) in find_aqm_type()
159 if (d->type == type || (name && !strcasecmp(d->name, name))) in find_sched_type()
187 /*---- flow_id mask, hash and compare functions ---*/
189 * The flow_id includes the 5-tuple, the queue/pipe number
199 id->dst_port &= mask->dst_port; in flow_id_mask()
200 id->src_port &= mask->src_port; in flow_id_mask()
201 id->proto &= mask->proto; in flow_id_mask()
202 id->extra &= mask->extra; in flow_id_mask()
204 APPLY_MASK(&id->dst_ip6, &mask->dst_ip6); in flow_id_mask()
205 APPLY_MASK(&id->src_ip6, &mask->src_ip6); in flow_id_mask()
206 id->flow_id6 &= mask->flow_id6; in flow_id_mask()
208 id->dst_ip &= mask->dst_ip; in flow_id_mask()
209 id->src_ip &= mask->src_ip; in flow_id_mask()
220 dst->dst_port |= src->dst_port; in flow_id_or()
221 dst->src_port |= src->src_port; in flow_id_or()
222 dst->proto |= src->proto; in flow_id_or()
223 dst->extra |= src->extra; in flow_id_or()
226 (_d)->__u6_addr.__u6_addr32[0] |= (_s)->__u6_addr.__u6_addr32[0]; \ in flow_id_or()
227 (_d)->__u6_addr.__u6_addr32[1] |= (_s)->__u6_addr.__u6_addr32[1]; \ in flow_id_or()
228 (_d)->__u6_addr.__u6_addr32[2] |= (_s)->__u6_addr.__u6_addr32[2]; \ in flow_id_or()
229 (_d)->__u6_addr.__u6_addr32[3] |= (_s)->__u6_addr.__u6_addr32[3]; in flow_id_or()
230 OR_MASK(&dst->dst_ip6, &src->dst_ip6); in flow_id_or()
231 OR_MASK(&dst->src_ip6, &src->src_ip6); in flow_id_or()
233 dst->flow_id6 |= src->flow_id6; in flow_id_or()
235 dst->dst_ip |= src->dst_ip; in flow_id_or()
236 dst->src_ip |= src->src_ip; in flow_id_or()
244 if (m->dst_port || m->src_port || m->proto || m->extra) in nonzero_mask()
248 m->dst_ip6.__u6_addr.__u6_addr32[0] || in nonzero_mask()
249 m->dst_ip6.__u6_addr.__u6_addr32[1] || in nonzero_mask()
250 m->dst_ip6.__u6_addr.__u6_addr32[2] || in nonzero_mask()
251 m->dst_ip6.__u6_addr.__u6_addr32[3] || in nonzero_mask()
252 m->src_ip6.__u6_addr.__u6_addr32[0] || in nonzero_mask()
253 m->src_ip6.__u6_addr.__u6_addr32[1] || in nonzero_mask()
254 m->src_ip6.__u6_addr.__u6_addr32[2] || in nonzero_mask()
255 m->src_ip6.__u6_addr.__u6_addr32[3] || in nonzero_mask()
256 m->flow_id6; in nonzero_mask()
258 return m->dst_ip || m->src_ip; in nonzero_mask()
269 uint32_t *d = (uint32_t *)&id->dst_ip6; in flow_id_hash()
270 uint32_t *s = (uint32_t *)&id->src_ip6; in flow_id_hash()
279 (id->dst_port << 1) ^ (id->src_port) ^ in flow_id_hash()
280 (id->extra) ^ in flow_id_hash()
281 (id->proto ) ^ (id->flow_id6); in flow_id_hash()
283 i = (id->dst_ip) ^ (id->dst_ip >> 15) ^ in flow_id_hash()
284 (id->src_ip << 1) ^ (id->src_ip >> 16) ^ in flow_id_hash()
285 (id->extra) ^ in flow_id_hash()
286 (id->dst_port << 1) ^ (id->src_port) ^ (id->proto); in flow_id_hash()
301 return (id1->dst_ip == id2->dst_ip && in flow_id_cmp()
302 id1->src_ip == id2->src_ip && in flow_id_cmp()
303 id1->dst_port == id2->dst_port && in flow_id_cmp()
304 id1->src_port == id2->src_port && in flow_id_cmp()
305 id1->proto == id2->proto && in flow_id_cmp()
306 id1->extra == id2->extra) ? 0 : 1; in flow_id_cmp()
310 !bcmp(&id1->dst_ip6,&id2->dst_ip6, sizeof(id1->dst_ip6)) && in flow_id_cmp()
311 !bcmp(&id1->src_ip6,&id2->src_ip6, sizeof(id1->src_ip6)) && in flow_id_cmp()
312 id1->dst_port == id2->dst_port && in flow_id_cmp()
313 id1->src_port == id2->src_port && in flow_id_cmp()
314 id1->proto == id2->proto && in flow_id_cmp()
315 id1->extra == id2->extra && in flow_id_cmp()
316 id1->flow_id6 == id2->flow_id6) ? 0 : 1; in flow_id_cmp()
318 /*--------- end of flow-id mask, hash and compare ---------*/
320 /*--- support functions for the qht hashtable ----
321 * Entries are hashed by flow-id
324 q_hash(uintptr_t key, int flags, void *arg) in q_hash() argument
328 &((struct dn_queue *)key)->ni.fid : in q_hash()
329 (struct ipfw_flow_id *)key; in q_hash()
335 q_match(void *obj, uintptr_t key, int flags, void *arg) in q_match() argument
342 id2 = &((struct dn_queue *)key)->ni.fid; in q_match()
344 id2 = (struct ipfw_flow_id *)key; in q_match()
346 return (0 == flow_id_cmp(&o->ni.fid, id2)); in q_match()
350 * create a new queue instance for the given 'key'.
353 q_new(uintptr_t key, int flags, void *arg) in q_new() argument
356 struct dn_fsk *fs = template->fs; in q_new()
357 int size = sizeof(*q) + fs->sched->fp->q_datalen; in q_new()
365 set_oid(&q->ni.oid, DN_QUEUE, size); in q_new()
366 if (fs->fs.flags & DN_QHT_HASH) in q_new()
367 q->ni.fid = *(struct ipfw_flow_id *)key; in q_new()
368 q->fs = fs; in q_new()
369 q->_si = template->_si; in q_new()
370 q->_si->q_count++; in q_new()
372 if (fs->sched->fp->new_queue) in q_new()
373 fs->sched->fp->new_queue(q); in q_new()
377 if (fs->aqmfp && fs->aqmfp->init) in q_new()
378 if(fs->aqmfp->init(q)) in q_new()
379 D("unable to init AQM for fs %d", fs->fs.fs_nr); in q_new()
394 struct dn_fsk *fs = q->fs; in dn_delete_queue()
400 if (fs && fs->aqmfp && fs->aqmfp->cleanup) in dn_delete_queue()
401 fs->aqmfp->cleanup(q); in dn_delete_queue()
403 // D("fs %p si %p\n", fs, q->_si); in dn_delete_queue()
405 if (fs && fs->sched->fp->free_queue) in dn_delete_queue()
406 fs->sched->fp->free_queue(q); in dn_delete_queue()
407 q->_si->q_count--; in dn_delete_queue()
408 q->_si = NULL; in dn_delete_queue()
410 if (q->mq.head) in dn_delete_queue()
411 dn_free_pkts(q->mq.head); in dn_delete_queue()
414 V_dn_cfg.queue_count--; in dn_delete_queue()
435 fs->fs.fs_nr, flags, fs->qht); in qht_delete()
436 if (!fs->qht) in qht_delete()
438 if (fs->fs.flags & DN_QHT_HASH) { in qht_delete()
439 dn_ht_scan(fs->qht, q_delete_cb, (void *)(uintptr_t)flags); in qht_delete()
441 dn_ht_free(fs->qht, 0); in qht_delete()
442 fs->qht = NULL; in qht_delete()
445 dn_delete_queue((struct dn_queue *)(fs->qht), flags); in qht_delete()
447 fs->qht = NULL; in qht_delete()
464 if (fs->fs.flags & DN_QHT_HASH) { in ipdn_q_find()
466 if (fs->qht == NULL) { in ipdn_q_find()
467 fs->qht = dn_ht_init(NULL, fs->fs.buckets, in ipdn_q_find()
470 if (fs->qht == NULL) in ipdn_q_find()
474 flow_id_mask(&fs->fsk_mask, &masked_id); in ipdn_q_find()
475 return dn_ht_find(fs->qht, (uintptr_t)&masked_id, in ipdn_q_find()
478 if (fs->qht == NULL) in ipdn_q_find()
479 fs->qht = q_new(0, 0, &template); in ipdn_q_find()
480 return (struct dn_queue *)fs->qht; in ipdn_q_find()
483 /*--- end of queue hash table ---*/
485 /*--- support functions for the sch_inst hashtable ----
487 * These are hashed by flow-id
490 si_hash(uintptr_t key, int flags, void *arg) in si_hash() argument
494 &((struct dn_sch_inst *)key)->ni.fid : in si_hash()
495 (struct ipfw_flow_id *)key; in si_hash()
501 si_match(void *obj, uintptr_t key, int flags, void *arg) in si_match() argument
507 &((struct dn_sch_inst *)key)->ni.fid : in si_match()
508 (struct ipfw_flow_id *)key; in si_match()
509 return flow_id_cmp(&o->ni.fid, id2) == 0; in si_match()
513 * create a new instance for the given 'key'
517 si_new(uintptr_t key, int flags, void *arg) in si_new() argument
521 int l = sizeof(*si) + s->fp->si_datalen; in si_new()
528 set_oid(&si->ni.oid, DN_SCH_I, sizeof(struct dn_flow)); in si_new()
529 set_oid(&(si->dline.oid), DN_DELAY_LINE, in si_new()
532 si->ni.oid.id = si->dline.oid.id = -1; in si_new()
534 si->sched = s; in si_new()
535 si->dline.si = si; in si_new()
537 if (s->fp->new_sched && s->fp->new_sched(si)) { in si_new()
541 if (s->sch.flags & DN_HAVE_MASK) in si_new()
542 si->ni.fid = *(struct ipfw_flow_id *)key; in si_new()
546 if (!(s->fp->flags & DN_MULTIQUEUE)) in si_new()
547 if (s->fs->aqmfp && s->fs->aqmfp->init) in si_new()
548 if(s->fs->aqmfp->init((struct dn_queue *)(si + 1))) { in si_new()
549 D("unable to init AQM for fs %d", s->fs->fs.fs_nr); in si_new()
575 struct dn_schk *s = si->sched; in si_destroy()
576 struct delay_line *dl = &si->dline; in si_destroy()
578 if (dl->oid.subtype) /* remove delay line from event heap */ in si_destroy()
580 dn_free_pkts(dl->mq.head); /* drain delay line */ in si_destroy()
581 if (si->kflags & DN_ACTIVE) /* remove si from event heap */ in si_destroy()
587 * When drain_scheduler is called s->fs and q->fs are pointing in si_destroy()
590 if (!(s->fp->flags & DN_MULTIQUEUE)) { in si_destroy()
592 if (q->aqm_status && q->fs->aqmfp) in si_destroy()
593 if (q->fs->aqmfp->cleanup) in si_destroy()
594 q->fs->aqmfp->cleanup(q); in si_destroy()
597 if (s->fp->free_sched) in si_destroy()
598 s->fp->free_sched(si); in si_destroy()
601 V_dn_cfg.si_count--; in si_destroy()
614 if (s->sch.flags & DN_HAVE_MASK) { in ipdn_si_find()
616 flow_id_mask(&s->sch.sched_mask, &id_t); in ipdn_si_find()
617 return dn_ht_find(s->siht, (uintptr_t)&id_t, in ipdn_si_find()
620 if (!s->siht) in ipdn_si_find()
621 s->siht = si_new(0, 0, s); in ipdn_si_find()
622 return (struct dn_sch_inst *)s->siht; in ipdn_si_find()
630 struct dn_link *p = &si->sched->link; in si_reset_credit()
632 si->credit = p->burst + (V_dn_cfg.io_fast ? p->bandwidth : 0); in si_reset_credit()
639 if (s->sch.flags & DN_HAVE_MASK) in schk_reset_credit()
640 dn_ht_scan(s->siht, si_reset_credit, NULL); in schk_reset_credit()
641 else if (s->siht) in schk_reset_credit()
642 si_reset_credit(s->siht, NULL); in schk_reset_credit()
644 /*---- end of sch_inst hashtable ---------------------*/
646 /*-------------------------------------------------------
652 fsk_hash(uintptr_t key, int flags, void *arg) in fsk_hash() argument
654 uint32_t i = !(flags & DNHT_KEY_IS_OBJ) ? key : in fsk_hash()
655 ((struct dn_fsk *)key)->fs.fs_nr; in fsk_hash()
661 fsk_match(void *obj, uintptr_t key, int flags, void *arg) in fsk_match() argument
664 int i = !(flags & DNHT_KEY_IS_OBJ) ? key : in fsk_match()
665 ((struct dn_fsk *)key)->fs.fs_nr; in fsk_match()
667 return (fs->fs.fs_nr == i); in fsk_match()
671 fsk_new(uintptr_t key, int flags, void *arg) in fsk_new() argument
677 set_oid(&fs->fs.oid, DN_FS, sizeof(fs->fs)); in fsk_new()
679 fs->drain_bucket = 0; in fsk_new()
687 * connected to scheduler instance '_si' (for !DN_MULTIQUEUE only).
694 if (!(si->sched->fp->flags & DN_MULTIQUEUE)) { in si_cleanup_q()
695 if (si->sched->fs->aqmfp && si->sched->fs->aqmfp->cleanup) in si_cleanup_q()
696 si->sched->fs->aqmfp->cleanup((struct dn_queue *) (si+1)); in si_cleanup_q()
706 q->fs->aqmfp->cleanup(q); in q_cleanup_q()
719 if (fs->fs.fs_nr > DN_MAX_ID) { in aqm_cleanup_deconfig_fs()
720 if (fs->sched && !(fs->sched->fp->flags & DN_MULTIQUEUE)) { in aqm_cleanup_deconfig_fs()
721 if (fs->sched->sch.flags & DN_HAVE_MASK) in aqm_cleanup_deconfig_fs()
722 dn_ht_scan(fs->sched->siht, si_cleanup_q, NULL); in aqm_cleanup_deconfig_fs()
725 si = (struct dn_sch_inst *) fs->sched->siht; in aqm_cleanup_deconfig_fs()
726 if (si && fs->aqmfp && fs->aqmfp->cleanup) in aqm_cleanup_deconfig_fs()
727 fs->aqmfp->cleanup((struct dn_queue *) (si+1)); in aqm_cleanup_deconfig_fs()
733 if (fs->sched && fs->sched->fp->flags & DN_MULTIQUEUE && fs->qht) { in aqm_cleanup_deconfig_fs()
734 if (fs->fs.flags & DN_QHT_HASH) in aqm_cleanup_deconfig_fs()
735 dn_ht_scan(fs->qht, q_cleanup_q, NULL); in aqm_cleanup_deconfig_fs()
737 fs->aqmfp->cleanup((struct dn_queue *)(fs->qht)); in aqm_cleanup_deconfig_fs()
741 if(fs->aqmcfg && fs->aqmfp && fs->aqmfp->deconfig) in aqm_cleanup_deconfig_fs()
742 fs->aqmfp->deconfig(fs); in aqm_cleanup_deconfig_fs()
758 fs->fs.fs_nr, fs->fs.sched_nr, in fsk_detach()
764 h = fs->sched ? &fs->sched->fsk_list : &V_dn_cfg.fsu; in fsk_detach()
770 free(fs->w_q_lookup, M_DUMMYNET); in fsk_detach()
771 fs->w_q_lookup = NULL; in fsk_detach()
777 if (fs->sched && fs->sched->fp->free_fsk) in fsk_detach()
778 fs->sched->fp->free_fsk(fs); in fsk_detach()
779 fs->sched = NULL; in fsk_detach()
783 V_dn_cfg.fsk_count--; in fsk_detach()
812 * called on 'queue X delete' -- removes the flowset from fshash,
835 /*----- end of flowset hashtable support -------------*/
837 /*------------------------------------------------------------
844 schk_hash(uintptr_t key, int flags, void *_arg) in schk_hash() argument
846 uint32_t i = !(flags & DNHT_KEY_IS_OBJ) ? key : in schk_hash()
847 ((struct dn_schk *)key)->sch.sched_nr; in schk_hash()
852 schk_match(void *obj, uintptr_t key, int flags, void *_arg) in schk_match() argument
855 int i = !(flags & DNHT_KEY_IS_OBJ) ? key : in schk_match()
856 ((struct dn_schk *)key)->sch.sched_nr; in schk_match()
857 return (s->sch.sched_nr == i); in schk_match()
862 * Leave s->fp unset so we can tell whether a dn_ht_find() returns
866 schk_new(uintptr_t key, int flags, void *arg) in schk_new() argument
870 int l = sizeof(*s) +a->fp->schk_datalen; in schk_new()
875 set_oid(&s->link.oid, DN_LINK, sizeof(s->link)); in schk_new()
876 s->sch = *a->sch; // copy initial values in schk_new()
877 s->link.link_nr = s->sch.sched_nr; in schk_new()
878 SLIST_INIT(&s->fsk_list); in schk_new()
880 s->fp = a->fp; /* si_new needs this */ in schk_new()
881 s->drain_bucket = 0; in schk_new()
882 if (s->sch.flags & DN_HAVE_MASK) { in schk_new()
883 s->siht = dn_ht_init(NULL, s->sch.buckets, in schk_new()
886 if (s->siht == NULL) { in schk_new()
891 s->fp = NULL; /* mark as a new scheduler */ in schk_new()
911 s->sch.sched_nr, in schk_delete_cb()
915 fsk_detach_list(&s->fsk_list, arg ? DN_DESTROY : 0); in schk_delete_cb()
917 if (s->sch.flags & DN_HAVE_MASK) { in schk_delete_cb()
918 dn_ht_scan(s->siht, si_destroy, NULL); in schk_delete_cb()
919 dn_ht_free(s->siht, 0); in schk_delete_cb()
920 } else if (s->siht) in schk_delete_cb()
921 si_destroy(s->siht, NULL); in schk_delete_cb()
923 free(s->profile, M_DUMMYNET); in schk_delete_cb()
924 s->profile = NULL; in schk_delete_cb()
925 s->siht = NULL; in schk_delete_cb()
926 if (s->fp->destroy) in schk_delete_cb()
927 s->fp->destroy(s); in schk_delete_cb()
930 V_dn_cfg.schk_count--; in schk_delete_cb()
953 /*--- end of schk hashtable support ---*/
963 int have = end - *start; in copy_obj()
991 * Copies only the user-visible part of a queue (which is in
998 int have = end - *start; in copy_obj_q()
1001 if (have < len || o->len == 0 || o->type != DN_QUEUE) { in copy_obj_q()
1003 o->type, msg, i, have, len); in copy_obj_q()
1006 ND("type %d %s %d len %d", o->type, msg, i, len); in copy_obj_q()
1008 ((struct dn_id*)(*start))->len = len; in copy_obj_q()
1018 struct dn_flow *ni = (struct dn_flow *)(*a->start); in copy_q_cb()
1019 if (copy_obj_q(a->start, a->end, &q->ni, "queue", -1)) in copy_q_cb()
1021 ni->oid.type = DN_FLOW; /* override the DN_QUEUE */ in copy_q_cb()
1022 ni->oid.id = si_hash((uintptr_t)&ni->fid, 0, NULL); in copy_q_cb()
1029 if (!fs->qht) in copy_q()
1031 if (fs->fs.flags & DN_QHT_HASH) in copy_q()
1032 dn_ht_scan(fs->qht, copy_q_cb, a); in copy_q()
1034 copy_q_cb(fs->qht, a); in copy_q()
1044 int have = a->end - *a->start; in copy_profile()
1046 int profile_len = sizeof(struct dn_profile) - in copy_profile()
1055 memcpy(*a->start, p, profile_len); in copy_profile()
1056 ((struct dn_id *)(*a->start))->len = profile_len; in copy_profile()
1057 *a->start += profile_len; in copy_profile()
1064 struct dn_fs *ufs = (struct dn_fs *)(*a->start); in copy_flowset()
1067 ND("flowset %d", fs->fs.fs_nr); in copy_flowset()
1068 if (copy_obj(a->start, a->end, &fs->fs, "flowset", fs->fs.fs_nr)) in copy_flowset()
1070 ufs->oid.id = (fs->fs.flags & DN_QHT_HASH) ? in copy_flowset()
1071 dn_ht_entries(fs->qht) : (fs->qht ? 1 : 0); in copy_flowset()
1083 struct dn_flow *ni = (struct dn_flow *)(*a->start); in copy_si_cb()
1084 if (copy_obj(a->start, a->end, &si->ni, "inst", in copy_si_cb()
1085 si->sched->sch.sched_nr)) in copy_si_cb()
1087 ni->oid.type = DN_FLOW; /* override the DN_SCH_I */ in copy_si_cb()
1088 ni->oid.id = si_hash((uintptr_t)si, DNHT_KEY_IS_OBJ, NULL); in copy_si_cb()
1095 if (s->sch.flags & DN_HAVE_MASK) in copy_si()
1096 dn_ht_scan(s->siht, copy_si_cb, a); in copy_si()
1097 else if (s->siht) in copy_si()
1098 copy_si_cb(s->siht, a); in copy_si()
1113 SLIST_FOREACH(fs, &s->fsk_list, sch_chain) { in copy_fsk_list()
1114 if (fs->fs.fs_nr < DN_MAX_ID) in copy_fsk_list()
1118 DX(3, "sched %d has %d flowsets", s->sch.sched_nr, n); in copy_fsk_list()
1119 if (a->end - *(a->start) < space) in copy_fsk_list()
1121 o = (struct dn_id *)(*(a->start)); in copy_fsk_list()
1122 o->len = space; in copy_fsk_list()
1123 *a->start += o->len; in copy_fsk_list()
1124 o->type = DN_TEXT; in copy_fsk_list()
1126 SLIST_FOREACH(fs, &s->fsk_list, sch_chain) in copy_fsk_list()
1127 if (fs->fs.fs_nr < DN_MAX_ID) in copy_fsk_list()
1128 *p++ = fs->fs.fs_nr; in copy_fsk_list()
1136 uint32_t *r = a->extra->r; /* start of first range */ in copy_data_helper()
1140 lim = (uint32_t *)((char *)(a->extra) + a->extra->o.len); in copy_data_helper()
1142 if (a->type == DN_LINK || a->type == DN_SCH) { in copy_data_helper()
1146 n = s->sch.sched_nr; in copy_data_helper()
1147 if (a->type == DN_SCH && n >= DN_MAX_ID) in copy_data_helper()
1149 if (a->type == DN_LINK && n <= DN_MAX_ID) in copy_data_helper()
1157 if (a->flags & DN_C_LINK) { in copy_data_helper()
1158 if (copy_obj(a->start, a->end, in copy_data_helper()
1159 &s->link, "link", n)) in copy_data_helper()
1161 if (copy_profile(a, s->profile)) in copy_data_helper()
1163 if (copy_flowset(a, s->fs, 0)) in copy_data_helper()
1166 if (a->flags & DN_C_SCH) { in copy_data_helper()
1167 if (copy_obj(a->start, a->end, in copy_data_helper()
1168 &s->sch, "sched", n)) in copy_data_helper()
1174 if (a->flags & DN_C_FLOW) in copy_data_helper()
1178 } else if (a->type == DN_FS) { in copy_data_helper()
1182 n = fs->fs.fs_nr; in copy_data_helper()
1213 fs->w_q = fs->fs.w_q; in config_red()
1214 fs->max_p = fs->fs.max_p; in config_red()
1217 i = fs->sched->link.bandwidth; in config_red()
1221 idle = div64((s * 3) , fs->w_q); /* s, fs->w_q scaled; idle not scaled */ in config_red()
1222 fs->lookup_step = div64(idle , V_dn_cfg.red_lookup_depth); in config_red()
1223 /* fs->lookup_step not scaled, */ in config_red()
1224 if (!fs->lookup_step) in config_red()
1225 fs->lookup_step = 1; in config_red()
1226 w0 = weight = SCALE(1) - fs->w_q; //fs->w_q scaled in config_red()
1228 for (t = fs->lookup_step; t > 1; --t) in config_red()
1230 fs->lookup_weight = (int)(weight); // scaled in config_red()
1233 fs->min_th = SCALE(fs->fs.min_th); in config_red()
1234 fs->max_th = SCALE(fs->fs.max_th); in config_red()
1236 if (fs->fs.max_th == fs->fs.min_th) in config_red()
1237 fs->c_1 = fs->max_p; in config_red()
1239 fs->c_1 = SCALE((int64_t)(fs->max_p)) / (fs->fs.max_th - fs->fs.min_th); in config_red()
1240 fs->c_2 = SCALE_MUL(fs->c_1, SCALE(fs->fs.min_th)); in config_red()
1242 if (fs->fs.flags & DN_IS_GENTLE_RED) { in config_red()
1243 fs->c_3 = (SCALE(1) - fs->max_p) / fs->fs.max_th; in config_red()
1244 fs->c_4 = SCALE(1) - 2 * fs->max_p; in config_red()
1248 free(fs->w_q_lookup, M_DUMMYNET); in config_red()
1249 fs->w_q_lookup = NULL; in config_red()
1253 fs->fs.flags &= ~DN_IS_RED; in config_red()
1254 fs->fs.flags &= ~DN_IS_GENTLE_RED; in config_red()
1257 fs->lookup_depth = V_dn_cfg.red_lookup_depth; in config_red()
1258 fs->w_q_lookup = (u_int *)malloc(fs->lookup_depth * sizeof(int), in config_red()
1260 if (fs->w_q_lookup == NULL) { in config_red()
1262 fs->fs.flags &= ~DN_IS_RED; in config_red()
1263 fs->fs.flags &= ~DN_IS_GENTLE_RED; in config_red()
1267 /* Fill the lookup table with (1 - w_q)^x */ in config_red()
1268 fs->w_q_lookup[0] = SCALE(1) - fs->w_q; in config_red()
1270 for (i = 1; i < fs->lookup_depth; i++) in config_red()
1271 fs->w_q_lookup[i] = in config_red()
1272 SCALE_MUL(fs->w_q_lookup[i - 1], fs->lookup_weight); in config_red()
1276 fs->avg_pkt_size = V_dn_cfg.red_avg_pkt_size; in config_red()
1279 fs->max_pkt_size = V_dn_cfg.red_max_pkt_size; in config_red()
1289 SLIST_FOREACH(fs, &s->fsk_list, sch_chain) { in update_red()
1290 if (fs && (fs->fs.flags & DN_IS_RED)) in update_red()
1300 fs->fs.fs_nr, s->sch.sched_nr); in fsk_attach()
1302 fs->sched = s; in fsk_attach()
1303 SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); in fsk_attach()
1304 if (s->fp->new_fsk) in fsk_attach()
1305 s->fp->new_fsk(fs); in fsk_attach()
1307 fs->fsk_mask = fs->fs.flow_mask; in fsk_attach()
1308 if (fs->sched->sch.flags & DN_HAVE_MASK) in fsk_attach()
1309 flow_id_or(&fs->sched->sch.sched_mask, &fs->fsk_mask); in fsk_attach()
1310 if (fs->qht) { in fsk_attach()
1314 * The requeue is complex -- in general we need to in fsk_attach()
1320 fs->fs.fs_nr, s->sch.sched_nr); in fsk_attach()
1321 fs->qht = NULL; in fsk_attach()
1324 if (nonzero_mask(&fs->fsk_mask)) in fsk_attach()
1325 fs->fs.flags |= DN_QHT_HASH; in fsk_attach()
1327 fs->fs.flags &= ~DN_QHT_HASH; in fsk_attach()
1330 if (fs->fs.flags & DN_IS_RED) in fsk_attach()
1341 if (s->sch.sched_nr != fs->fs.sched_nr) { in update_fs()
1343 fs->fs.fs_nr, fs->fs.sched_nr, in update_fs()
1344 s->sch.sched_nr); in update_fs()
1362 sopt_valsize = sopt->sopt_valsize; in get_aqm_parms()
1364 if (sopt->sopt_valsize < l) { in get_aqm_parms()
1365 D("bad len sopt->sopt_valsize %d len %d", in get_aqm_parms()
1366 (int) sopt->sopt_valsize , l); in get_aqm_parms()
1379 sopt->sopt_valsize = sopt_valsize; in get_aqm_parms()
1380 if (ep->oid.len < l) { in get_aqm_parms()
1385 fs = dn_ht_find(V_dn_cfg.fshash, ep->nr, 0, NULL); in get_aqm_parms()
1387 D("fs %d not found", ep->nr); in get_aqm_parms()
1392 if (fs->aqmfp && fs->aqmfp->getconfig) { in get_aqm_parms()
1393 if(fs->aqmfp->getconfig(fs, ep)) { in get_aqm_parms()
1398 ep->oid.len = l; in get_aqm_parms()
1417 sopt_valsize = sopt->sopt_valsize; in get_sched_parms()
1419 if (sopt->sopt_valsize < l) { in get_sched_parms()
1420 D("bad len sopt->sopt_valsize %d len %d", in get_sched_parms()
1421 (int) sopt->sopt_valsize , l); in get_sched_parms()
1434 sopt->sopt_valsize = sopt_valsize; in get_sched_parms()
1435 if (ep->oid.len < l) { in get_sched_parms()
1440 schk = locate_scheduler(ep->nr); in get_sched_parms()
1442 D("sched %d not found", ep->nr); in get_sched_parms()
1447 if (schk->fp && schk->fp->getconfig) { in get_sched_parms()
1448 if(schk->fp->getconfig(schk, ep)) { in get_sched_parms()
1453 ep->oid.len = l; in get_sched_parms()
1480 if (!strcmp(ep->name,"")) { in config_aqm()
1484 if (ep->oid.len < sizeof(*ep)) { in config_aqm()
1485 D("short aqm len %d", ep->oid.len); in config_aqm()
1497 if (fs->aqmcfg && fs->aqmfp && fs->aqmfp->deconfig) { in config_aqm()
1501 if (!(fs->aqmfp = find_aqm_type(0, ep->name))) { in config_aqm()
1502 D("AQM functions not found for type %s!", ep->name); in config_aqm()
1503 fs->fs.flags &= ~DN_IS_AQM; in config_aqm()
1507 fs->fs.flags |= DN_IS_AQM; in config_aqm()
1509 if (ep->oid.subtype != DN_AQM_PARAMS) { in config_aqm()
1515 if (fs->aqmfp->config) { in config_aqm()
1516 err = fs->aqmfp->config(fs, ep, ep->oid.len); in config_aqm()
1518 D("Unable to configure AQM for FS %d", fs->fs.fs_nr ); in config_aqm()
1519 fs->fs.flags &= ~DN_IS_AQM; in config_aqm()
1520 fs->aqmfp = NULL; in config_aqm()
1531 * Configuration -- to preserve backward compatibility we use
1534 * 1 .. N-1 (1)WFQ (2)WFQ (3)queue
1535 * N+1 .. 2N-1 (4)FIFO (5)FIFO (6)FIFO for sched 1..N-1
1536 * 2N+1 .. 3N-1 -- -- (7)FIFO for sched N+1..2N-1
1560 if (p->oid.len != sizeof(*p)) { in config_link()
1561 D("invalid pipe len %d", p->oid.len); in config_link()
1564 i = p->link_nr; in config_link()
1574 p->delay = (p->delay * hz) / 1000; in config_link()
1575 /* Scale burst size: bytes -> bits * hz */ in config_link()
1576 p->burst *= 8 * hz; in config_link()
1588 free(s->profile, M_DUMMYNET); in config_link()
1589 s->profile = NULL; in config_link()
1592 s->link.oid = p->oid; in config_link()
1593 s->link.link_nr = i; in config_link()
1594 s->link.delay = p->delay; in config_link()
1595 if (s->link.bandwidth != p->bandwidth) { in config_link()
1597 s->link.bandwidth = p->bandwidth; in config_link()
1600 s->link.burst = p->burst; in config_link()
1620 if (nfs->oid.len != sizeof(*nfs)) { in config_fs()
1621 D("invalid flowset len %d", nfs->oid.len); in config_fs()
1624 i = nfs->fs_nr; in config_fs()
1638 if (nfs->flags & DN_QSIZE_BYTES) { in config_fs()
1639 ipdn_bound_var(&nfs->qsize, 16384, in config_fs()
1642 ipdn_bound_var(&nfs->qsize, 50, in config_fs()
1645 if (nfs->flags & DN_HAVE_MASK) { in config_fs()
1647 ipdn_bound_var((int *)&nfs->buckets, V_dn_cfg.hash_size, in config_fs()
1650 nfs->buckets = 1; /* we only need 1 */ in config_fs()
1656 int flags = nfs->sched_nr ? DNHT_INSERT : 0; in config_fs()
1665 if (nfs->sched_nr == 0) /* reuse */ in config_fs()
1666 nfs->sched_nr = fs->fs.sched_nr; in config_fs()
1667 for (j = 0; j < sizeof(nfs->par)/sizeof(nfs->par[0]); j++) { in config_fs()
1668 if (nfs->par[j] == -1) /* reuse */ in config_fs()
1669 nfs->par[j] = fs->fs.par[j]; in config_fs()
1671 if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { in config_fs()
1680 s = locate_scheduler(nfs->sched_nr); in config_fs()
1681 config_aqm(fs, ep, s != NULL && s->siht != NULL); in config_fs()
1688 s = locate_scheduler(nfs->sched_nr); in config_fs()
1694 fs->fs.fs_nr, in config_fs()
1695 fs->fs.sched_nr, fs->sched, nfs->sched_nr, s); in config_fs()
1696 if (fs->sched) { in config_fs()
1701 fs->fs = *nfs; /* copy configuration */ in config_fs()
1703 fs->aqmfp = NULL; in config_fs()
1706 s->siht != NULL); in config_fs()
1723 * On reconfigurations (detected because s->fp is set),
1745 if (a.sch->oid.len != sizeof(*a.sch)) { in config_sched()
1746 D("bad sched len %d", a.sch->oid.len); in config_sched()
1749 i = a.sch->sched_nr; in config_sched()
1753 if (a.sch->flags & DN_HAVE_MASK) in config_sched()
1754 ipdn_bound_var((int *)&a.sch->buckets, V_dn_cfg.hash_size, in config_sched()
1759 pipe_cmd = a.sch->flags & DN_PIPE_CMD; in config_sched()
1760 a.sch->flags &= ~DN_PIPE_CMD; //XXX do it even if is not set? in config_sched()
1763 new_mask = a.sch->sched_mask; in config_sched()
1764 new_buckets = a.sch->buckets; in config_sched()
1765 new_flags = a.sch->flags; in config_sched()
1774 a.fp = find_sched_type(a.sch->oid.subtype, a.sch->name); in config_sched()
1778 } else if (a.sch->oid.subtype == 0 && !a.sch->name[0]) { in config_sched()
1782 a.fp = s->fp; in config_sched()
1794 bzero(&a.sch->sched_mask, sizeof(new_mask)); in config_sched()
1795 a.sch->buckets = 0; in config_sched()
1796 a.sch->flags &= ~DN_HAVE_MASK; in config_sched()
1798 a.sch->oid.subtype = DN_SCHED_WF2QP; in config_sched()
1803 a.sch->oid.subtype, a.sch->name); in config_sched()
1808 a.sch->oid.subtype = a.fp->type; in config_sched()
1809 bzero(a.sch->name, sizeof(a.sch->name)); in config_sched()
1810 strlcpy(a.sch->name, a.fp->name, sizeof(a.sch->name)); in config_sched()
1817 s->link = p; in config_sched()
1818 if (!pf || pf->link_nr != p.link_nr) { /* no saved value */ in config_sched()
1819 s->profile = NULL; /* XXX maybe not needed */ in config_sched()
1821 s->profile = malloc(sizeof(struct dn_profile), in config_sched()
1823 if (s->profile == NULL) { in config_sched()
1827 memcpy(s->profile, pf, sizeof(*pf)); in config_sched()
1831 if (s->fp == NULL) { in config_sched()
1832 DX(2, "sched %d new type %s", i, a.fp->name); in config_sched()
1833 } else if (s->fp != a.fp || in config_sched()
1834 bcmp(a.sch, &s->sch, sizeof(*a.sch)) ) { in config_sched()
1837 i, s->fp->name, a.fp->name); in config_sched()
1838 DX(4, " type/sub %d/%d -> %d/%d", in config_sched()
1839 s->sch.oid.type, s->sch.oid.subtype, in config_sched()
1840 a.sch->oid.type, a.sch->oid.subtype); in config_sched()
1841 if (s->link.link_nr == 0) in config_sched()
1843 p = s->link; /* preserve link */ in config_sched()
1844 if (s->profile) {/* preserve profile */ in config_sched()
1849 memcpy(pf, s->profile, sizeof(*pf)); in config_sched()
1859 DX(4, "sched %d unchanged type %s", i, a.fp->name); in config_sched()
1862 s->sch = *a.sch; in config_sched()
1863 s->fp = a.fp; in config_sched()
1864 s->cfg = arg; in config_sched()
1869 if (!(s->fp->flags & DN_MULTIQUEUE) && !s->fs) { in config_sched()
1870 s->fs = dn_ht_find(V_dn_cfg.fshash, i, 0, NULL); in config_sched()
1871 if (!s->fs) { in config_sched()
1877 s->fs = config_fs(&fs, NULL, 1 /* locked */); in config_sched()
1879 if (!s->fs) { in config_sched()
1886 if (s->fp->config) in config_sched()
1887 s->fp->config(s); in config_sched()
1894 a.sch->sched_mask = new_mask; in config_sched()
1895 a.sch->buckets = new_buckets; in config_sched()
1896 a.sch->flags = new_flags; in config_sched()
1900 /* FIFO already exist, don't touch it */ in config_sched()
1905 a.sch->sched_nr = i; in config_sched()
1906 a.sch->oid.subtype = DN_SCHED_FIFO; in config_sched()
1907 bzero(a.sch->name, sizeof(a.sch->name)); in config_sched()
1926 if (pf->oid.len < sizeof(*pf)) { in config_profile()
1927 D("short profile len %d", pf->oid.len); in config_profile()
1930 i = pf->link_nr; in config_profile()
1947 if (s->profile && (pf->samples_no == 0 || in config_profile()
1948 s->profile->oid.len < pf->oid.len)) { in config_profile()
1949 free(s->profile, M_DUMMYNET); in config_profile()
1950 s->profile = NULL; in config_profile()
1952 if (pf->samples_no == 0) in config_profile()
1958 if (s->profile == NULL) in config_profile()
1959 s->profile = malloc(pf->oid.len, in config_profile()
1961 if (s->profile == NULL) { in config_profile()
1967 olen = s->profile->oid.len; in config_profile()
1968 if (olen < pf->oid.len) in config_profile()
1969 olen = pf->oid.len; in config_profile()
1970 memcpy(s->profile, pf, pf->oid.len); in config_profile()
1971 s->profile->oid.len = olen; in config_profile()
1998 * - the first object is the command (config, delete, flush, ...)
1999 * - config_link must be issued after the corresponding config_sched
2000 * - parameters (DN_TXT) for an object must precede the object
2032 l -= o.len; in do_config()
2103 memcpy(&dn->link, (char *)p + off, sizeof(dn->link)); in do_config()
2104 err = config_link(&dn->link, arg); in do_config()
2113 memcpy(&dn->profile, (char *)p + off, in do_config()
2114 sizeof(dn->profile)); in do_config()
2115 err = config_profile(&dn->profile, arg); in do_config()
2124 memcpy(&dn->sched, (char *)p + off, in do_config()
2125 sizeof(dn->sched)); in do_config()
2126 err = config_sched(&dn->sched, arg); in do_config()
2135 memcpy(&dn->fs, (char *)p + off, sizeof(dn->fs)); in do_config()
2136 err = (NULL == config_fs(&dn->fs, arg, 0)); in do_config()
2152 int profile_size = sizeof(struct dn_profile) - in compute_space()
2160 * - ipfw pipe show in compute_space()
2167 * - ipfw sched show in compute_space()
2175 * - ipfw queue show in compute_space()
2179 switch (cmd->subtype) { in compute_space()
2181 return -1; in compute_space()
2202 a->flags = x; in compute_space()
2242 sopt_valsize = sopt->sopt_valsize; in dummynet_get()
2248 sopt->sopt_valsize = sopt_valsize; in dummynet_get()
2251 l = cmd->len; in dummynet_get()
2254 if (cmd->type == DN_SYSCTL_GET) in dummynet_get()
2265 sopt->sopt_valsize = sopt_valsize; in dummynet_get()
2272 if(cmd->subtype == DN_AQM_PARAMS) { in dummynet_get()
2276 } else if (cmd->subtype == DN_SCH_PARAMS) { in dummynet_get()
2283 if (cmd->len == sizeof(*cmd)) { /* no range, create a default */ in dummynet_get()
2285 cmd->len += 2* sizeof(uint32_t); in dummynet_get()
2287 rp[1] = DN_MAX_ID - 1; in dummynet_get()
2288 if (cmd->subtype == DN_LINK) { in dummynet_get()
2303 need = sopt_valsize - sizeof(*cmd); in dummynet_get()
2311 cmd->id = need; in dummynet_get()
2336 sopt->sopt_valsize = sopt_valsize; in dummynet_get()
2337 a.type = cmd->subtype; in dummynet_get()
2340 ((struct dn_id*)(start))->len = sizeof(struct dn_id); in dummynet_get()
2352 error = sooptcopyout(sopt, start, buf - start); in dummynet_get()
2366 if ((si->kflags & DN_ACTIVE) || si->dline.mq.head != NULL) in drain_scheduler_cb()
2369 if (si->sched->fp->flags & DN_MULTIQUEUE) { in drain_scheduler_cb()
2370 if (si->q_count == 0) in drain_scheduler_cb()
2375 if ((si+1)->ni.length == 0) in drain_scheduler_cb()
2389 if (s->sch.flags & DN_HAVE_MASK) { in drain_scheduler_sch_cb()
2390 dn_ht_scan_bucket(s->siht, &s->drain_bucket, in drain_scheduler_sch_cb()
2392 s->drain_bucket++; in drain_scheduler_sch_cb()
2394 if (s->siht) { in drain_scheduler_sch_cb()
2395 if (drain_scheduler_cb(s->siht, NULL) == DNHT_SCAN_DEL) in drain_scheduler_sch_cb()
2396 s->siht = NULL; in drain_scheduler_sch_cb()
2417 if (q->ni.length == 0) { in drain_queue_cb()
2431 if (fs->fs.flags & DN_QHT_HASH) { in drain_queue_fs_cb()
2433 dn_ht_scan_bucket(fs->qht, &fs->drain_bucket, in drain_queue_fs_cb()
2435 fs->drain_bucket++; in drain_queue_fs_cb()
2440 if (fs->qht) { in drain_queue_fs_cb()
2441 if (drain_queue_cb(fs->qht, NULL) == DNHT_SCAN_DEL) in drain_queue_fs_cb()
2442 fs->qht = NULL; in drain_queue_fs_cb()
2469 error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET); in ip_dn_ctl()
2473 /* Disallow sets in really-really secure mode. */ in ip_dn_ctl()
2474 if (sopt->sopt_dir == SOPT_SET) { in ip_dn_ctl()
2475 error = securelevel_ge(sopt->sopt_td->td_ucred, 3); in ip_dn_ctl()
2482 switch (sopt->sopt_name) { in ip_dn_ctl()
2484 D("dummynet: unknown option %d", sopt->sopt_name); in ip_dn_ctl()
2489 if (sopt->sopt_dir == SOPT_GET) { in ip_dn_ctl()
2493 l = sopt->sopt_valsize; in ip_dn_ctl()
2540 * In both we search by key and by pointer. in ip_dn_vnet_init()
2646 if (d->enqueue == NULL || d->dequeue == NULL) { in load_dn_sched()
2647 D("missing enqueue or dequeue for %s", d->name); in load_dn_sched()
2654 if (strcmp(s->name, d->name) == 0) { in load_dn_sched()
2655 D("%s already loaded", d->name); in load_dn_sched()
2662 D("dn_sched %s %sloaded", d->name, s ? "not ":""); in load_dn_sched()
2672 ND("called for %s", s->name); in unload_dn_sched()
2676 if (strcmp(s->name, r->name) != 0) in unload_dn_sched()
2678 ND("ref_count = %d", r->ref_count); in unload_dn_sched()
2679 err = (r->ref_count != 0) ? EBUSY : 0; in unload_dn_sched()
2686 D("dn_sched %s %sunloaded", s->name, err ? "not ":""); in unload_dn_sched()
2708 #define DN_MODEV_ORD (SI_ORDER_ANY - 128) /* after ipfw */
2739 if (d->enqueue == NULL || d->dequeue == NULL) { in load_dn_aqm()
2740 D("missing enqueue or dequeue for %s", d->name); in load_dn_aqm()
2748 if (strcmp(aqm->name, d->name) == 0) { in load_dn_aqm()
2749 D("%s already loaded", d->name); in load_dn_aqm()
2758 D("dn_aqm %s %sloaded", d->name, aqm ? "not ":""); in load_dn_aqm()
2762 /* Callback to clean up AQM status for queues connected to a flowset
2772 if (fs->aqmfp && fs->aqmfp->type == type) in fs_cleanup()
2784 ND("called for %s", aqm->name); in unload_dn_aqm()
2787 dn_ht_scan(V_dn_cfg.fshash, fs_cleanup, &aqm->type); in unload_dn_aqm()
2792 if (strcmp(aqm->name, r->name) != 0) in unload_dn_aqm()
2794 ND("ref_count = %d", r->ref_count); in unload_dn_aqm()
2795 err = (r->ref_count != 0 || r->cfg_ref_count != 0) ? EBUSY : 0; in unload_dn_aqm()
2804 D("%s %sunloaded", aqm->name, err ? "not ":""); in unload_dn_aqm()
2806 D("ref_count=%d, cfg_ref_count=%d", r->ref_count, r->cfg_ref_count); in unload_dn_aqm()