static struct mbuf * tcq_dequeue_cl(struct tcq_if *tif, struct tcq_class *cl, mbuf_svc_class_t sc, cqdq_op_t op) { struct ifclassq *ifq = tif->tif_ifq; struct mbuf *m; IFCQ_LOCK_ASSERT_HELD(ifq); if (cl == NULL) { cl = tcq_clh_to_clp(tif, MBUF_SCIDX(sc)); if (cl == NULL) return (NULL); } if (qempty(&cl->cl_q)) return (NULL); VERIFY(!IFCQ_IS_EMPTY(ifq)); if (op == CLASSQDQ_POLL) return (tcq_pollq(cl)); m = tcq_getq(cl); if (m != NULL) { IFCQ_DEC_LEN(ifq); IFCQ_DEC_BYTES(ifq, m_pktlen(m)); if (qempty(&cl->cl_q)) cl->cl_period++; PKTCNTR_ADD(&cl->cl_xmitcnt, 1, m_pktlen(m)); IFCQ_XMIT_ADD(ifq, 1, m_pktlen(m)); } return (m); }
int pktsched_teardown(struct ifclassq *ifq) { int error = 0; IFCQ_LOCK_ASSERT_HELD(ifq); if_qflush(ifq->ifcq_ifp, 1); VERIFY(IFCQ_IS_EMPTY(ifq)); ifq->ifcq_flags &= ~IFCQF_ENABLED; switch (ifq->ifcq_type) { case PKTSCHEDT_NONE: break; case PKTSCHEDT_TCQ: error = tcq_teardown_ifclassq(ifq); break; case PKTSCHEDT_QFQ: error = qfq_teardown_ifclassq(ifq); break; case PKTSCHEDT_FQ_CODEL: error = fq_if_teardown_ifclassq(ifq); break; default: error = ENXIO; break; } return (error); }
/* * note: CLASSQDQ_POLL returns the next packet without removing the packet * from the queue. CLASSQDQ_REMOVE is a normal dequeue operation. * CLASSQDQ_REMOVE must return the same packet if called immediately * after CLASSQDQ_POLL. */ struct mbuf * priq_dequeue(struct priq_if *pif, cqdq_op_t op) { struct ifclassq *ifq = pif->pif_ifq; struct priq_class *cl; struct mbuf *m; u_int32_t pri, len; IFCQ_LOCK_ASSERT_HELD(ifq); if (pif->pif_bitmap == 0) { /* no active class; nothing to dequeue */ return (NULL); } VERIFY(!IFCQ_IS_EMPTY(ifq)); pri = pktsched_fls(pif->pif_bitmap) - 1; /* zero based */ VERIFY(pri < PRIQ_MAXPRI); cl = pif->pif_classes[pri]; VERIFY(cl != NULL && !qempty(&cl->cl_q)); if (op == CLASSQDQ_POLL) return (priq_pollq(cl)); m = priq_getq(cl); VERIFY(m != NULL); /* qalg must be work conserving */ len = m_pktlen(m); IFCQ_DEC_LEN(ifq); IFCQ_DEC_BYTES(ifq, len); if (qempty(&cl->cl_q)) { cl->cl_period++; /* class is now inactive; indicate it as such */ pktsched_bit_clr(pri, &pif->pif_bitmap); } PKTCNTR_ADD(&cl->cl_xmitcnt, 1, len); IFCQ_XMIT_ADD(ifq, 1, len); return (m); }
/* * note: CLASSQDQ_POLL returns the next packet without removing the packet * from the queue. CLASSQDQ_REMOVE is a normal dequeue operation. * CLASSQDQ_REMOVE must return the same packet if called immediately * after CLASSQDQ_POLL. */ struct mbuf * fairq_dequeue(struct fairq_if *fif, cqdq_op_t op) { struct ifclassq *ifq = fif->fif_ifq; struct fairq_class *cl; struct fairq_class *best_cl; struct mbuf *best_m; struct mbuf *m; u_int64_t cur_time = read_machclk(); u_int32_t best_scale; u_int32_t scale; int pri; int hit_limit; IFCQ_LOCK_ASSERT_HELD(ifq); if (IFCQ_IS_EMPTY(ifq)) { /* no packet in the queue */ return (NULL); } if (fif->fif_poll_cache && op == CLASSQDQ_REMOVE) { best_cl = fif->fif_poll_cache; m = fairq_getq(best_cl, cur_time); fif->fif_poll_cache = NULL; if (m != NULL) { IFCQ_DEC_LEN(ifq); IFCQ_DEC_BYTES(ifq, m_pktlen(m)); IFCQ_XMIT_ADD(ifq, 1, m_pktlen(m)); PKTCNTR_ADD(&best_cl->cl_xmitcnt, 1, m_pktlen(m)); } } else { best_cl = NULL; best_m = NULL; best_scale = 0xFFFFFFFFU; for (pri = fif->fif_maxpri; pri >= 0; pri--) { if ((cl = fif->fif_classes[pri]) == NULL) continue; if ((cl->cl_flags & FARF_HAS_PACKETS) == 0) continue; m = fairq_pollq(cl, cur_time, &hit_limit); if (m == NULL) { cl->cl_flags &= ~FARF_HAS_PACKETS; continue; } /* * We can halt the search immediately if the queue * did not hit its bandwidth limit. */ if (hit_limit == 0) { best_cl = cl; best_m = m; break; } /* * Otherwise calculate the scale factor and select * the queue with the lowest scale factor. This * apportions any unused bandwidth weighted by * the relative bandwidth specification. */ scale = cl->cl_bw_current * 100 / cl->cl_bandwidth; if (scale < best_scale) { best_cl = cl; best_m = m; best_scale = scale; } } if (op == CLASSQDQ_POLL) { fif->fif_poll_cache = best_cl; m = best_m; } else if (best_cl != NULL) { m = fairq_getq(best_cl, cur_time); if (m != NULL) { IFCQ_DEC_LEN(ifq); IFCQ_DEC_BYTES(ifq, m_pktlen(m)); IFCQ_XMIT_ADD(ifq, 1, m_pktlen(m)); PKTCNTR_ADD(&best_cl->cl_xmitcnt, 1, m_pktlen(m)); } } else { m = NULL; } } return (m); }