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); }
int main() { uint8_t ec; int rc; // Create IP connection IPConnection ipcon; ipcon_create(&ipcon); // Create device object RED red; red_create(&red, UID, &ipcon); // Connect to brickd rc = ipcon_connect(&ipcon, HOST, PORT); if (rc < 0) { printf("ipcon_connect -> rc %d\n", rc); return -1; } uint16_t sid; if (allocate_string(&red, "blubb", &sid)) { return -1; } uint16_t pid; rc = red_define_program(&red, sid, &ec, &pid); if (rc < 0) { printf("red_define_program -> rc %d\n", rc); goto cleanup2; } if (ec != 0) { printf("red_define_program -> ec %u\n", ec); goto cleanup2; } printf("red_define_program -> pid %u\n", pid); rc = red_set_program_schedule(&red, pid, RED_PROGRAM_START_CONDITION_NOW, 0, 12345, RED_PROGRAM_REPEAT_MODE_SELECTION, 0, (1ULL << 59) | 1, (1ULL << 59) | 1, (1 << 23) | 1, (1 << 30) | 1, (1 << 11) | 1, (1 << 6) | 1, &ec); if (rc < 0) { printf("red_set_program_schedule -> rc %d\n", rc); goto cleanup2; } if (ec != 0) { printf("red_set_program_schedule -> ec %u\n", ec); goto cleanup2; } uint16_t pdsid; rc = red_get_program_directory(&red, pid, &ec, &pdsid); if (rc < 0) { printf("red_get_program_directory -> rc %d\n", rc); goto cleanup1; } if (ec != 0) { printf("red_get_program_directory -> ec %u\n", ec); goto cleanup1; } printf("red_get_program_directory -> pdsid %u\n", pdsid); char buffer[STRING_MAX_GET_CHUNK_BUFFER_LENGTH + 1]; rc = red_get_string_chunk(&red, pdsid, 0, &ec, buffer); if (rc < 0) { printf("red_get_string_chunk -> rc %d\n", rc); goto cleanup1; } if (ec != 0) { printf("red_get_string_chunk -> ec %u\n", ec); goto cleanup1; } buffer[STRING_MAX_GET_CHUNK_BUFFER_LENGTH] = '\0'; printf("red_get_string_chunk '%s'\n", buffer); rc = red_undefine_program(&red, pid, &ec); if (rc < 0) { printf("red_undefine_program -> rc %d\n", rc); goto cleanup0; } if (ec != 0) { printf("red_undefine_program -> ec %u\n", ec); goto cleanup0; } cleanup0: release_object(&red, pdsid, "string"); cleanup1: release_object(&red, pid, "program"); cleanup2: release_object(&red, sid, "string"); red_destroy(&red); ipcon_destroy(&ipcon); return 0; }
/* * red support routines */ red_t * red_alloc(struct ifnet *ifp, int weight, int inv_pmax, int th_min, int th_max, int flags, int pkttime) { red_t *rp; int w, i; int npkts_per_sec; VERIFY(ifp != NULL); rp = zalloc(red_zone); if (rp == NULL) return (NULL); bzero(rp, red_size); rp->red_avg = 0; rp->red_idle = 1; if (weight == 0) rp->red_weight = W_WEIGHT; else rp->red_weight = weight; if (inv_pmax == 0) rp->red_inv_pmax = default_inv_pmax; else rp->red_inv_pmax = inv_pmax; if (th_min == 0) rp->red_thmin = default_th_min; else rp->red_thmin = th_min; if (th_max == 0) rp->red_thmax = default_th_max; else rp->red_thmax = th_max; rp->red_ifp = ifp; rp->red_flags = (flags & REDF_USERFLAGS); #if !PF_ECN if (rp->red_flags & REDF_ECN) { rp->red_flags &= ~REDF_ECN; log(LOG_ERR, "%s: RED ECN not available; ignoring " "REDF_ECN flag!\n", if_name(ifp)); } #endif /* !PF_ECN */ if (pkttime == 0) /* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */ rp->red_pkttime = 800; else rp->red_pkttime = pkttime; if (weight == 0) { /* when the link is very slow, adjust red parameters */ npkts_per_sec = 1000000 / rp->red_pkttime; if (npkts_per_sec < 50) { /* up to about 400Kbps */ rp->red_weight = W_WEIGHT_2; } else if (npkts_per_sec < 300) { /* up to about 2.4Mbps */ rp->red_weight = W_WEIGHT_1; } } /* calculate wshift. weight must be power of 2 */ w = rp->red_weight; for (i = 0; w > 1; i++) w = w >> 1; rp->red_wshift = i; w = 1 << rp->red_wshift; if (w != rp->red_weight) { printf("invalid weight value %d for red! use %d\n", rp->red_weight, w); rp->red_weight = w; } /* * thmin_s and thmax_s are scaled versions of th_min and th_max * to be compared with avg. */ rp->red_thmin_s = rp->red_thmin << (rp->red_wshift + FP_SHIFT); rp->red_thmax_s = rp->red_thmax << (rp->red_wshift + FP_SHIFT); /* * precompute probability denominator * probd = (2 * (TH_MAX-TH_MIN) / pmax) in fixed-point */ rp->red_probd = (2 * (rp->red_thmax - rp->red_thmin) * rp->red_inv_pmax) << FP_SHIFT; /* allocate weight table */ rp->red_wtab = wtab_alloc(rp->red_weight); if (rp->red_wtab == NULL) { red_destroy(rp); return (NULL); } microuptime(&rp->red_last); return (rp); }
int main() { uint8_t ec; int rc; // Create IP connection IPConnection ipcon; ipcon_create(&ipcon); // Create device object red_create(&red, UID, &ipcon); // Connect to brickd rc = ipcon_connect(&ipcon, HOST, PORT); if (rc < 0) { printf("ipcon_connect -> rc %d\n", rc); return -1; } uint16_t session_id; if (create_session(&red, 30, &session_id) < 0) { return -1; } uint16_t lid; rc = red_allocate_list(&red, 20, session_id, &ec, &lid); if (rc < 0) { printf("red_allocate_list -> rc %d\n", rc); return -1; } if (ec != 0) { printf("red_allocate_list -> ec %u\n", ec); return -1; } printf("red_allocate_list -> lid %u\n", lid); int i; for (i = 0; i < 30; ++i) { uint16_t sid; if (allocate_string(&red, "A123456789B123456789C123456789D123456789", session_id, &sid) < 0) { goto cleanup; } rc = red_append_to_list(&red, lid, sid, &ec); if (rc < 0) { printf("red_append_to_list -> rc %d\n", rc); } if (ec != 0) { printf("red_append_to_list -> ec %u\n", ec); } release_object(&red, sid, session_id, "string"); } uint16_t length; rc = red_get_list_length(&red, lid, &ec, &length); if (rc < 0) { printf("red_get_list_length -> rc %d\n", rc); } if (ec != 0) { printf("red_get_list_length -> ec %u\n", ec); } printf("red_get_list_length -> length %u\n", length); rc = red_remove_from_list(&red, lid, 5, &ec); if (rc < 0) { printf("red_remove_from_list -> rc %d\n", rc); } if (ec != 0) { printf("red_remove_from_list -> ec %u\n", ec); } rc = red_get_list_length(&red, lid, &ec, &length); if (rc < 0) { printf("red_get_list_length -> rc %d\n", rc); } if (ec != 0) { printf("red_get_list_length -> ec %u\n", ec); } printf("red_get_list_length -> length %u\n", length); cleanup: release_object(&red, lid, session_id, "list"); expire_session(&red, session_id); red_destroy(&red); ipcon_destroy(&ipcon); return 0; }
int main() { uint8_t ec; int rc; // Create IP connection IPConnection ipcon; ipcon_create(&ipcon); // Create device object RED red; red_create(&red, UID, &ipcon); // Connect to brickd rc = ipcon_connect(&ipcon, HOST, PORT); if (rc < 0) { printf("ipcon_connect -> rc %d\n", rc); return -1; } uint16_t sid; if (allocate_string(&red, "/lib/", &sid)) { return -1; } uint16_t did; rc = red_open_directory(&red, sid, &ec, &did); if (rc < 0) { printf("red_open_directory -> rc %d\n", rc); goto cleanup; } if (ec != 0) { printf("red_open_directory -> ec %u\n", ec); goto cleanup; } printf("red_open_directory -> did %u\n", did); uint64_t st = microseconds(); while (1) { uint16_t nid; uint8_t type; rc = red_get_next_directory_entry(&red, did, &ec, &nid, &type); if (rc < 0) { printf("red_get_next_directory_entry -> rc %d\n", rc); break; } if (ec != 0) { printf("red_get_next_directory_entry -> ec %u\n", ec); break; } char buffer[STRING_MAX_GET_CHUNK_BUFFER_LENGTH + 1]; rc = red_get_string_chunk(&red, nid, 0, &ec, buffer); if (rc < 0) { printf("red_get_string_chunk -> rc %d\n", rc); break; } if (ec != 0) { printf("red_get_string_chunk -> ec %u\n", ec); break; } buffer[STRING_MAX_GET_CHUNK_BUFFER_LENGTH] = '\0'; printf("* %s", buffer); if (type == RED_FILE_TYPE_SYMLINK) { uint16_t tid; rc = red_lookup_symlink_target(&red, nid, true, &ec, &tid); if (rc < 0) { printf("red_get_symlink_target -> rc %d\n", rc); break; } if (ec != 0) { printf("red_get_symlink_target -> ec %u\n", ec); break; } rc = red_get_string_chunk(&red, tid, 0, &ec, buffer); if (rc < 0) { printf("red_get_string_chunk -> rc %d\n", rc); break; } if (ec != 0) { printf("red_get_string_chunk -> ec %u\n", ec); break; } buffer[63] = '\0'; printf(" ==> %s", buffer); release_object(&red, tid, "string"); } printf("\n"); /*uint8_t type; uint16_t permissions; uint32_t user_id; uint32_t group_id; uint64_t length; uint64_t access_time; uint64_t modification_time; uint64_t status_change_time; rc = red_lookup_file_info(&red, nid, true, &ec, &type, &permissions, &user_id, &group_id, &length, &access_time, &modification_time, &status_change_time); if (rc < 0) { printf("red_get_file_info -> rc %d\n", rc); } if (ec != 0) { printf("red_get_file_info -> ec %u\n", ec); } printf("%u %o %u %u %lu %lu %lu %lu\n", type, permissions, user_id, group_id, length, access_time, modification_time, status_change_time);*/ release_object(&red, nid, "string"); } uint64_t et = microseconds(); float dur = (et - st) / 1000000.0; printf("red_get_next_directory_entry in %f sec\n", dur); cleanup: release_object(&red, did, "directory"); release_object(&red, sid, "string"); red_destroy(&red); ipcon_destroy(&ipcon); return 0; }
int main() { uint8_t ec; int rc; // Create IP connection IPConnection ipcon; ipcon_create(&ipcon); // Create device object RED red; red_create(&red, UID, &ipcon); // Connect to brickd rc = ipcon_connect(&ipcon, HOST, PORT); if (rc < 0) { printf("ipcon_connect -> rc %d\n", rc); return -1; } uint16_t session_id; if (create_session(&red, 5, &session_id) < 0) { return -1; } uint16_t sid; rc = red_allocate_string(&red, 20, "", session_id, &ec, &sid); if (rc < 0) { printf("red_acquire_string -> rc %d\n", rc); } if (ec != 0) { printf("red_acquire_string -> ec %u\n", ec); } printf("red_acquire_string -> sid %u\n", sid); rc = red_set_string_chunk(&red, sid, 0, "A123456789B123456789C123456789D123456789", &ec); if (rc < 0) { printf("red_set_string_chunk -> rc %d\n", rc); } if (ec != 0) { printf("red_set_string_chunk -> ec %u\n", ec); } rc = red_set_string_chunk(&red, sid, 40, "E123456789F123456789G123456789H123456789", &ec); if (rc < 0) { printf("red_set_string_chunk -> rc %d\n", rc); } if (ec != 0) { printf("red_set_string_chunk -> ec %u\n", ec); } uint32_t length; rc = red_get_string_length(&red, sid, &ec, &length); if (rc < 0) { printf("red_get_string_length -> rc %d\n", rc); } if (ec != 0) { printf("red_get_string_length -> ec %u\n", ec); } printf("red_get_string_length -> length %u\n", length); char buffer[63 + 1]; rc = red_get_string_chunk(&red, sid, 20, &ec, buffer); if (rc < 0) { printf("red_get_string_chunk -> rc %d\n", rc); } if (ec != 0) { printf("red_get_string_chunk -> ec %u\n", ec); } buffer[63] = '\0'; printf("red_get_string_chunk -> buffer '%s'\n", buffer); #if 1 release_object(&red, sid, session_id, "string"); expire_session(&red, session_id); #else int i; for (i = 0; i < 5; ++i) { rc = red_keep_session_alive(&red, session_id, 5, &ec); if (rc < 0) { printf("red_keep_session_alive -> rc %d\n", rc); } if (ec != 0) { printf("red_keep_session_alive -> ec %u\n", ec); } sleep(2); } #endif red_destroy(&red); ipcon_destroy(&ipcon); return 0; }