static int priq_class_destroy(struct priq_if *pif, struct priq_class *cl) { struct ifclassq *ifq = pif->pif_ifq; int pri; IFCQ_LOCK_ASSERT_HELD(ifq); if (!qempty(&cl->cl_q)) priq_purgeq(pif, cl, 0, NULL, NULL); VERIFY(cl->cl_pri < PRIQ_MAXPRI); VERIFY(!pktsched_bit_tst(cl->cl_pri, &pif->pif_bitmap)); pif->pif_classes[cl->cl_pri] = NULL; if (pif->pif_maxpri == cl->cl_pri) { for (pri = cl->cl_pri; pri >= 0; pri--) if (pif->pif_classes[pri] != NULL) { pif->pif_maxpri = pri; break; } if (pri < 0) pif->pif_maxpri = -1; } if (pif->pif_default == cl) pif->pif_default = NULL; if (cl->cl_qalg.ptr != NULL) { #if CLASSQ_RIO if (q_is_rio(&cl->cl_q)) rio_destroy(cl->cl_rio); #endif /* CLASSQ_RIO */ #if CLASSQ_RED if (q_is_red(&cl->cl_q)) red_destroy(cl->cl_red); #endif /* CLASSQ_RED */ #if CLASSQ_BLUE if (q_is_blue(&cl->cl_q)) blue_destroy(cl->cl_blue); #endif /* CLASSQ_BLUE */ if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL) sfb_destroy(cl->cl_sfb); cl->cl_qalg.ptr = NULL; qtype(&cl->cl_q) = Q_DROPTAIL; qstate(&cl->cl_q) = QS_RUNNING; } if (pktsched_verbose) { log(LOG_DEBUG, "%s: %s destroyed qid=%d pri=%d\n", if_name(PRIQIF_IFP(pif)), priq_style(pif), cl->cl_handle, cl->cl_pri); } zfree(priq_cl_zone, cl); return (0); }
static int priq_class_destroy(struct priq_class *cl) { struct priq_if *pif; int s, pri; s = splnet(); IFQ_LOCK(cl->cl_pif->pif_ifq); #ifdef ALTQ3_CLFIER_COMPAT /* delete filters referencing to this class */ acc_discard_filters(&cl->cl_pif->pif_classifier, cl, 0); #endif if (!qempty(cl->cl_q)) priq_purgeq(cl); pif = cl->cl_pif; pif->pif_classes[cl->cl_pri] = NULL; if (pif->pif_maxpri == cl->cl_pri) { for (pri = cl->cl_pri; pri >= 0; pri--) if (pif->pif_classes[pri] != NULL) { pif->pif_maxpri = pri; break; } if (pri < 0) pif->pif_maxpri = -1; } IFQ_UNLOCK(cl->cl_pif->pif_ifq); splx(s); if (cl->cl_red != NULL) { #ifdef ALTQ_RIO if (q_is_rio(cl->cl_q)) rio_destroy((rio_t *)cl->cl_red); #endif #ifdef ALTQ_RED if (q_is_red(cl->cl_q)) red_destroy(cl->cl_red); #endif #ifdef ALTQ_CODEL if (q_is_codel(cl->cl_q)) codel_destroy(cl->cl_codel); #endif } free(cl->cl_q, M_DEVBUF); free(cl, M_DEVBUF); return (0); }
static int priq_class_destroy(struct priq_class *cl) { struct priq_if *pif; int pri; crit_enter(); if (!qempty(cl->cl_q)) priq_purgeq(cl); pif = cl->cl_pif; pif->pif_classes[cl->cl_pri] = NULL; if (pif->pif_maxpri == cl->cl_pri) { for (pri = cl->cl_pri; pri >= 0; pri--) if (pif->pif_classes[pri] != NULL) { pif->pif_maxpri = pri; break; } if (pri < 0) pif->pif_maxpri = -1; } crit_exit(); if (cl->cl_red != NULL) { #ifdef ALTQ_RIO if (q_is_rio(cl->cl_q)) rio_destroy((rio_t *)cl->cl_red); #endif #ifdef ALTQ_RED if (q_is_red(cl->cl_q)) red_destroy(cl->cl_red); #endif } kfree(cl->cl_q, M_ALTQ); kfree(cl, M_ALTQ); return (0); }
static int fairq_class_destroy(struct fairq_if *fif, struct fairq_class *cl) { struct ifclassq *ifq = fif->fif_ifq; int pri; IFCQ_LOCK_ASSERT_HELD(ifq); if (cl->cl_head) fairq_purgeq(fif, cl, 0, NULL, NULL); fif->fif_classes[cl->cl_pri] = NULL; if (fif->fif_poll_cache == cl) fif->fif_poll_cache = NULL; if (fif->fif_maxpri == cl->cl_pri) { for (pri = cl->cl_pri; pri >= 0; pri--) if (fif->fif_classes[pri] != NULL) { fif->fif_maxpri = pri; break; } if (pri < 0) fif->fif_maxpri = -1; } if (cl->cl_qalg.ptr != NULL) { #if CLASSQ_RIO if (cl->cl_qtype == Q_RIO) rio_destroy(cl->cl_rio); #endif /* CLASSQ_RIO */ #if CLASSQ_RED if (cl->cl_qtype == Q_RED) red_destroy(cl->cl_red); #endif /* CLASSQ_RED */ #if CLASSQ_BLUE if (cl->cl_qtype == Q_BLUE) blue_destroy(cl->cl_blue); #endif /* CLASSQ_BLUE */ if (cl->cl_qtype == Q_SFB && cl->cl_sfb != NULL) sfb_destroy(cl->cl_sfb); cl->cl_qalg.ptr = NULL; cl->cl_qtype = Q_DROPTAIL; cl->cl_qstate = QS_RUNNING; } if (fif->fif_default == cl) fif->fif_default = NULL; if (pktsched_verbose) { log(LOG_DEBUG, "%s: %s destroyed qid=%d pri=%d\n", if_name(FAIRQIF_IFP(fif)), fairq_style(fif), cl->cl_handle, cl->cl_pri); } _FREE(cl->cl_buckets, M_DEVBUF); cl->cl_head = NULL; /* sanity */ cl->cl_polled = NULL; /* sanity */ cl->cl_buckets = NULL; /* sanity */ zfree(fairq_cl_zone, cl); return (0); }
static struct fairq_class * fairq_class_create(struct fairq_if *fif, int pri, u_int32_t qlimit, u_int64_t bandwidth, u_int32_t nbuckets, int flags, u_int64_t hogs_m1, u_int64_t lssc_m1, u_int64_t lssc_d, u_int64_t lssc_m2, u_int32_t qid) { #pragma unused(lssc_d, lssc_m2) struct ifnet *ifp; struct ifclassq *ifq; struct fairq_class *cl; u_int32_t i; IFCQ_LOCK_ASSERT_HELD(fif->fif_ifq); /* Sanitize flags unless internally configured */ if (fif->fif_flags & FAIRQIFF_ALTQ) flags &= FARF_USERFLAGS; #if !CLASSQ_RED if (flags & FARF_RED) { log(LOG_ERR, "%s: %s RED not available!\n", if_name(FAIRQIF_IFP(fif)), fairq_style(fif)); return (NULL); } #endif /* !CLASSQ_RED */ #if !CLASSQ_RIO if (flags & FARF_RIO) { log(LOG_ERR, "%s: %s RIO not available!\n", if_name(FAIRQIF_IFP(fif)), fairq_style(fif)); return (NULL); } #endif /* CLASSQ_RIO */ #if !CLASSQ_BLUE if (flags & FARF_BLUE) { log(LOG_ERR, "%s: %s BLUE not available!\n", if_name(FAIRQIF_IFP(fif)), fairq_style(fif)); return (NULL); } #endif /* CLASSQ_BLUE */ /* These are mutually exclusive */ if ((flags & (FARF_RED|FARF_RIO|FARF_BLUE|FARF_SFB)) && (flags & (FARF_RED|FARF_RIO|FARF_BLUE|FARF_SFB)) != FARF_RED && (flags & (FARF_RED|FARF_RIO|FARF_BLUE|FARF_SFB)) != FARF_RIO && (flags & (FARF_RED|FARF_RIO|FARF_BLUE|FARF_SFB)) != FARF_BLUE && (flags & (FARF_RED|FARF_RIO|FARF_BLUE|FARF_SFB)) != FARF_SFB) { log(LOG_ERR, "%s: %s more than one RED|RIO|BLUE|SFB\n", if_name(FAIRQIF_IFP(fif)), fairq_style(fif)); return (NULL); } if (bandwidth == 0 || (bandwidth / 8) == 0) { log(LOG_ERR, "%s: %s invalid data rate %llu\n", if_name(FAIRQIF_IFP(fif)), fairq_style(fif), bandwidth); return (NULL); } if (nbuckets == 0) nbuckets = 256; if (nbuckets > FAIRQ_MAX_BUCKETS) nbuckets = FAIRQ_MAX_BUCKETS; /* enforce power-of-2 size */ while ((nbuckets ^ (nbuckets - 1)) != ((nbuckets << 1) - 1)) ++nbuckets; ifq = fif->fif_ifq; ifp = FAIRQIF_IFP(fif); if ((cl = fif->fif_classes[pri]) != NULL) { /* modify the class instead of creating a new one */ if (cl->cl_head) fairq_purgeq(fif, cl, 0, NULL, NULL); #if CLASSQ_RIO if (cl->cl_qtype == Q_RIO) rio_destroy(cl->cl_rio); #endif /* CLASSQ_RIO */ #if CLASSQ_RED if (cl->cl_qtype == Q_RED) red_destroy(cl->cl_red); #endif /* CLASSQ_RED */ #if CLASSQ_BLUE if (cl->cl_qtype == Q_BLUE) blue_destroy(cl->cl_blue); #endif /* CLASSQ_BLUE */ if (cl->cl_qtype == Q_SFB && cl->cl_sfb != NULL) sfb_destroy(cl->cl_sfb); cl->cl_qalg.ptr = NULL; cl->cl_qtype = Q_DROPTAIL; cl->cl_qstate = QS_RUNNING; } else { cl = zalloc(fairq_cl_zone); if (cl == NULL) goto err_ret; bzero(cl, fairq_cl_size); cl->cl_nbuckets = nbuckets; cl->cl_nbucket_mask = nbuckets - 1; cl->cl_buckets = _MALLOC(sizeof (struct fairq_bucket) * cl->cl_nbuckets, M_DEVBUF, M_WAITOK|M_ZERO); if (cl->cl_buckets == NULL) goto err_buckets; cl->cl_head = NULL; } fif->fif_classes[pri] = cl; if (flags & FARF_DEFAULTCLASS) fif->fif_default = cl; if (qlimit == 0 || qlimit > IFCQ_MAXLEN(ifq)) { qlimit = IFCQ_MAXLEN(ifq); if (qlimit == 0) qlimit = DEFAULT_QLIMIT; /* use default */ } cl->cl_qlimit = qlimit; for (i = 0; i < cl->cl_nbuckets; ++i) { _qinit(&cl->cl_buckets[i].queue, Q_DROPTAIL, qlimit); } cl->cl_bandwidth = bandwidth / 8; /* cvt to bytes per second */ cl->cl_qtype = Q_DROPTAIL; cl->cl_qstate = QS_RUNNING; cl->cl_flags = flags; cl->cl_pri = pri; if (pri > fif->fif_maxpri) fif->fif_maxpri = pri; cl->cl_fif = fif; cl->cl_handle = qid; cl->cl_hogs_m1 = hogs_m1 / 8; cl->cl_lssc_m1 = lssc_m1 / 8; /* NOT YET USED */ cl->cl_bw_current = 0; if (flags & (FARF_RED|FARF_RIO|FARF_BLUE|FARF_SFB)) { #if CLASSQ_RED || CLASSQ_RIO u_int64_t ifbandwidth = ifnet_output_linkrate(ifp); int pkttime; #endif /* CLASSQ_RED || CLASSQ_RIO */ cl->cl_qflags = 0; if (flags & FARF_ECN) { if (flags & FARF_BLUE) cl->cl_qflags |= BLUEF_ECN; else if (flags & FARF_SFB) cl->cl_qflags |= SFBF_ECN; else if (flags & FARF_RED) cl->cl_qflags |= REDF_ECN; else if (flags & FARF_RIO) cl->cl_qflags |= RIOF_ECN; } if (flags & FARF_FLOWCTL) { if (flags & FARF_SFB) cl->cl_qflags |= SFBF_FLOWCTL; } if (flags & FARF_CLEARDSCP) { if (flags & FARF_RIO) cl->cl_qflags |= RIOF_CLEARDSCP; } #if CLASSQ_RED || CLASSQ_RIO /* * XXX: RED & RIO should be watching link speed and MTU * events and recompute pkttime accordingly. */ if (ifbandwidth < 8) pkttime = 1000 * 1000 * 1000; /* 1 sec */ else pkttime = (int64_t)ifp->if_mtu * 1000 * 1000 * 1000 / (ifbandwidth / 8); /* Test for exclusivity {RED,RIO,BLUE,SFB} was done above */ #if CLASSQ_RIO if (flags & FARF_RIO) { cl->cl_rio = rio_alloc(ifp, 0, NULL, cl->cl_qflags, pkttime); if (cl->cl_rio != NULL) cl->cl_qtype = Q_RIO; } #endif /* CLASSQ_RIO */ #if CLASSQ_RED if (flags & FARF_RED) { cl->cl_red = red_alloc(ifp, 0, 0, cl->cl_qlimit * 10/100, cl->cl_qlimit * 30/100, cl->cl_qflags, pkttime); if (cl->cl_red != NULL) cl->cl_qtype = Q_RED; } #endif /* CLASSQ_RED */ #endif /* CLASSQ_RED || CLASSQ_RIO */ #if CLASSQ_BLUE if (flags & FARF_BLUE) { cl->cl_blue = blue_alloc(ifp, 0, 0, cl->cl_qflags); if (cl->cl_blue != NULL) cl->cl_qtype = Q_BLUE; } #endif /* CLASSQ_BLUE */ if (flags & FARF_SFB) { if (!(cl->cl_flags & FARF_LAZY)) cl->cl_sfb = sfb_alloc(ifp, cl->cl_handle, cl->cl_qlimit, cl->cl_qflags); if (cl->cl_sfb != NULL || (cl->cl_flags & FARF_LAZY)) cl->cl_qtype = Q_SFB; } } if (pktsched_verbose) { log(LOG_DEBUG, "%s: %s created qid=%d pri=%d qlimit=%d " "flags=%b\n", if_name(ifp), fairq_style(fif), cl->cl_handle, cl->cl_pri, cl->cl_qlimit, flags, FARF_BITS); } return (cl); err_buckets: if (cl->cl_buckets != NULL) _FREE(cl->cl_buckets, M_DEVBUF); err_ret: if (cl != NULL) { if (cl->cl_qalg.ptr != NULL) { #if CLASSQ_RIO if (cl->cl_qtype == Q_RIO) rio_destroy(cl->cl_rio); #endif /* CLASSQ_RIO */ #if CLASSQ_RED if (cl->cl_qtype == Q_RED) red_destroy(cl->cl_red); #endif /* CLASSQ_RED */ #if CLASSQ_BLUE if (cl->cl_qtype == Q_BLUE) blue_destroy(cl->cl_blue); #endif /* CLASSQ_BLUE */ if (cl->cl_qtype == Q_SFB && cl->cl_sfb != NULL) sfb_destroy(cl->cl_sfb); cl->cl_qalg.ptr = NULL; cl->cl_qtype = Q_DROPTAIL; cl->cl_qstate = QS_RUNNING; } zfree(fairq_cl_zone, cl); } return (NULL); }
static struct priq_class * priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid) { struct priq_class *cl; int s; #ifndef ALTQ_RED if (flags & PRCF_RED) { #ifdef ALTQ_DEBUG printf("priq_class_create: RED not configured for PRIQ!\n"); #endif return (NULL); } #endif if ((cl = pif->pif_classes[pri]) != NULL) { /* modify the class instead of creating a new one */ s = splnet(); if (!qempty(cl->cl_q)) priq_purgeq(cl); splx(s); #ifdef ALTQ_RIO if (q_is_rio(cl->cl_q)) rio_destroy((rio_t *)cl->cl_red); #endif #ifdef ALTQ_RED if (q_is_red(cl->cl_q)) red_destroy(cl->cl_red); #endif } else { cl = malloc(sizeof(struct priq_class), M_DEVBUF, M_WAITOK|M_ZERO); if (cl == NULL) return (NULL); cl->cl_q = malloc(sizeof(class_queue_t), M_DEVBUF, M_WAITOK|M_ZERO); if (cl->cl_q == NULL) goto err_ret; } pif->pif_classes[pri] = cl; if (flags & PRCF_DEFAULTCLASS) pif->pif_default = cl; if (qlimit == 0) qlimit = 50; /* use default */ qlimit(cl->cl_q) = qlimit; qtype(cl->cl_q) = Q_DROPTAIL; qlen(cl->cl_q) = 0; cl->cl_flags = flags; cl->cl_pri = pri; if (pri > pif->pif_maxpri) pif->pif_maxpri = pri; cl->cl_pif = pif; cl->cl_handle = qid; #ifdef ALTQ_RED if (flags & (PRCF_RED|PRCF_RIO)) { int red_flags, red_pkttime; red_flags = 0; if (flags & PRCF_ECN) red_flags |= REDF_ECN; #ifdef ALTQ_RIO if (flags & PRCF_CLEARDSCP) red_flags |= RIOF_CLEARDSCP; #endif if (pif->pif_bandwidth < 8) red_pkttime = 1000 * 1000 * 1000; /* 1 sec */ else red_pkttime = (int64_t)pif->pif_ifq->altq_ifp->if_mtu * 1000 * 1000 * 1000 / (pif->pif_bandwidth / 8); #ifdef ALTQ_RIO if (flags & PRCF_RIO) { cl->cl_red = (red_t *)rio_alloc(0, NULL, red_flags, red_pkttime); if (cl->cl_red != NULL) qtype(cl->cl_q) = Q_RIO; } else #endif if (flags & PRCF_RED) { cl->cl_red = red_alloc(0, 0, qlimit(cl->cl_q) * 10/100, qlimit(cl->cl_q) * 30/100, red_flags, red_pkttime); if (cl->cl_red != NULL) qtype(cl->cl_q) = Q_RED; } } #endif /* ALTQ_RED */ return (cl); err_ret: if (cl->cl_red != NULL) { #ifdef ALTQ_RIO if (q_is_rio(cl->cl_q)) rio_destroy((rio_t *)cl->cl_red); #endif #ifdef ALTQ_RED if (q_is_red(cl->cl_q)) red_destroy(cl->cl_red); #endif } if (cl->cl_q != NULL) free(cl->cl_q, M_DEVBUF); free(cl, M_DEVBUF); return (NULL); }
void rmc_delete_class(struct rm_ifdat *ifd, struct rm_class *cl) { struct rm_class *p, *head, *previous; KKASSERT(cl->children_ == NULL); if (cl->sleeping_) callout_stop(&cl->callout_); crit_enter(); if (ifd->pollcache_ == cl) ifd->pollcache_ = NULL; /* * Free packets in the packet queue. * XXX - this may not be a desired behavior. Packets should be * re-queued. */ rmc_dropall(cl); /* * If the class has a parent, then remove the class from the * class from the parent's children chain. */ if (cl->parent_ != NULL) { head = cl->parent_->children_; p = previous = head; if (head->next_ == NULL) { KKASSERT(head == cl); cl->parent_->children_ = NULL; cl->parent_->leaf_ = 1; } else while (p != NULL) { if (p == cl) { if (cl == head) cl->parent_->children_ = cl->next_; else previous->next_ = cl->next_; cl->next_ = NULL; p = NULL; } else { previous = p; p = p->next_; } } } /* * Delete class from class priority peer list. */ if ((p = ifd->active_[cl->pri_]) != NULL) { /* * If there is more than one member of this priority * level, then look for class(cl) in the priority level. */ if (p != p->peer_) { while (p->peer_ != cl) p = p->peer_; p->peer_ = cl->peer_; if (ifd->active_[cl->pri_] == cl) ifd->active_[cl->pri_] = cl->peer_; } else { KKASSERT(p == cl); ifd->active_[cl->pri_] = NULL; } } /* * Recompute the WRR weights. */ if (ifd->wrr_) { ifd->alloc_[cl->pri_] -= cl->allotment_; ifd->num_[cl->pri_]--; rmc_wrr_set_weights(ifd); } /* * Re-compute the depth of the tree. */ #if 1 /* ALTQ */ rmc_depth_recompute(cl->parent_); #else rmc_depth_recompute(ifd->root_); #endif crit_exit(); /* * Free the class structure. */ if (cl->red_ != NULL) { #ifdef ALTQ_RIO if (q_is_rio(cl->q_)) rio_destroy((rio_t *)cl->red_); #endif #ifdef ALTQ_RED if (q_is_red(cl->q_)) red_destroy(cl->red_); #endif } kfree(cl->q_, M_ALTQ); kfree(cl, M_ALTQ); }
static struct priq_class * priq_class_create(struct priq_if *pif, int pri, u_int32_t qlimit, int flags, u_int32_t qid) { struct ifnet *ifp; struct ifclassq *ifq; struct priq_class *cl; IFCQ_LOCK_ASSERT_HELD(pif->pif_ifq); /* Sanitize flags unless internally configured */ if (pif->pif_flags & PRIQIFF_ALTQ) flags &= PRCF_USERFLAGS; #if !CLASSQ_RED if (flags & PRCF_RED) { log(LOG_ERR, "%s: %s RED not available!\n", if_name(PRIQIF_IFP(pif)), priq_style(pif)); return (NULL); } #endif /* !CLASSQ_RED */ #if !CLASSQ_RIO if (flags & PRCF_RIO) { log(LOG_ERR, "%s: %s RIO not available!\n", if_name(PRIQIF_IFP(pif)), priq_style(pif)); return (NULL); } #endif /* CLASSQ_RIO */ #if !CLASSQ_BLUE if (flags & PRCF_BLUE) { log(LOG_ERR, "%s: %s BLUE not available!\n", if_name(PRIQIF_IFP(pif)), priq_style(pif)); return (NULL); } #endif /* CLASSQ_BLUE */ /* These are mutually exclusive */ if ((flags & (PRCF_RED|PRCF_RIO|PRCF_BLUE|PRCF_SFB)) && (flags & (PRCF_RED|PRCF_RIO|PRCF_BLUE|PRCF_SFB)) != PRCF_RED && (flags & (PRCF_RED|PRCF_RIO|PRCF_BLUE|PRCF_SFB)) != PRCF_RIO && (flags & (PRCF_RED|PRCF_RIO|PRCF_BLUE|PRCF_SFB)) != PRCF_BLUE && (flags & (PRCF_RED|PRCF_RIO|PRCF_BLUE|PRCF_SFB)) != PRCF_SFB) { log(LOG_ERR, "%s: %s more than one RED|RIO|BLUE|SFB\n", if_name(PRIQIF_IFP(pif)), priq_style(pif)); return (NULL); } ifq = pif->pif_ifq; ifp = PRIQIF_IFP(pif); if ((cl = pif->pif_classes[pri]) != NULL) { /* modify the class instead of creating a new one */ if (!qempty(&cl->cl_q)) priq_purgeq(pif, cl, 0, NULL, NULL); #if CLASSQ_RIO if (q_is_rio(&cl->cl_q)) rio_destroy(cl->cl_rio); #endif /* CLASSQ_RIO */ #if CLASSQ_RED if (q_is_red(&cl->cl_q)) red_destroy(cl->cl_red); #endif /* CLASSQ_RED */ #if CLASSQ_BLUE if (q_is_blue(&cl->cl_q)) blue_destroy(cl->cl_blue); #endif /* CLASSQ_BLUE */ if (q_is_sfb(&cl->cl_q) && cl->cl_sfb != NULL) sfb_destroy(cl->cl_sfb); cl->cl_qalg.ptr = NULL; qtype(&cl->cl_q) = Q_DROPTAIL; qstate(&cl->cl_q) = QS_RUNNING; } else { cl = zalloc(priq_cl_zone); if (cl == NULL) return (NULL); bzero(cl, priq_cl_size); } pif->pif_classes[pri] = cl; if (flags & PRCF_DEFAULTCLASS) pif->pif_default = cl; if (qlimit == 0 || qlimit > IFCQ_MAXLEN(ifq)) { qlimit = IFCQ_MAXLEN(ifq); if (qlimit == 0) qlimit = DEFAULT_QLIMIT; /* use default */ } _qinit(&cl->cl_q, Q_DROPTAIL, qlimit); cl->cl_flags = flags; cl->cl_pri = pri; if (pri > pif->pif_maxpri) pif->pif_maxpri = pri; cl->cl_pif = pif; cl->cl_handle = qid; if (flags & (PRCF_RED|PRCF_RIO|PRCF_BLUE|PRCF_SFB)) { #if CLASSQ_RED || CLASSQ_RIO u_int64_t ifbandwidth = ifnet_output_linkrate(ifp); int pkttime; #endif /* CLASSQ_RED || CLASSQ_RIO */ cl->cl_qflags = 0; if (flags & PRCF_ECN) { if (flags & PRCF_BLUE) cl->cl_qflags |= BLUEF_ECN; else if (flags & PRCF_SFB) cl->cl_qflags |= SFBF_ECN; else if (flags & PRCF_RED) cl->cl_qflags |= REDF_ECN; else if (flags & PRCF_RIO) cl->cl_qflags |= RIOF_ECN; } if (flags & PRCF_FLOWCTL) { if (flags & PRCF_SFB) cl->cl_qflags |= SFBF_FLOWCTL; } if (flags & PRCF_CLEARDSCP) { if (flags & PRCF_RIO) cl->cl_qflags |= RIOF_CLEARDSCP; } #if CLASSQ_RED || CLASSQ_RIO /* * XXX: RED & RIO should be watching link speed and MTU * events and recompute pkttime accordingly. */ if (ifbandwidth < 8) pkttime = 1000 * 1000 * 1000; /* 1 sec */ else pkttime = (int64_t)ifp->if_mtu * 1000 * 1000 * 1000 / (ifbandwidth / 8); /* Test for exclusivity {RED,RIO,BLUE,SFB} was done above */ #if CLASSQ_RED if (flags & PRCF_RED) { cl->cl_red = red_alloc(ifp, 0, 0, qlimit(&cl->cl_q) * 10/100, qlimit(&cl->cl_q) * 30/100, cl->cl_qflags, pkttime); if (cl->cl_red != NULL) qtype(&cl->cl_q) = Q_RED; } #endif /* CLASSQ_RED */ #if CLASSQ_RIO if (flags & PRCF_RIO) { cl->cl_rio = rio_alloc(ifp, 0, NULL, cl->cl_qflags, pkttime); if (cl->cl_rio != NULL) qtype(&cl->cl_q) = Q_RIO; } #endif /* CLASSQ_RIO */ #endif /* CLASSQ_RED || CLASSQ_RIO */ #if CLASSQ_BLUE if (flags & PRCF_BLUE) { cl->cl_blue = blue_alloc(ifp, 0, 0, cl->cl_qflags); if (cl->cl_blue != NULL) qtype(&cl->cl_q) = Q_BLUE; } #endif /* CLASSQ_BLUE */ if (flags & PRCF_SFB) { if (!(cl->cl_flags & PRCF_LAZY)) cl->cl_sfb = sfb_alloc(ifp, cl->cl_handle, qlimit(&cl->cl_q), cl->cl_qflags); if (cl->cl_sfb != NULL || (cl->cl_flags & PRCF_LAZY)) qtype(&cl->cl_q) = Q_SFB; } } if (pktsched_verbose) { log(LOG_DEBUG, "%s: %s created qid=%d pri=%d qlimit=%d " "flags=%b\n", if_name(ifp), priq_style(pif), cl->cl_handle, cl->cl_pri, qlimit, flags, PRCF_BITS); } return (cl); }