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); }
static void qfq_purge_sc(struct qfq_if *qif, cqrq_purge_sc_t *pr) { struct ifclassq *ifq = qif->qif_ifq; u_int32_t i; IFCQ_LOCK_ASSERT_HELD(ifq); VERIFY(pr->sc == MBUF_SC_UNSPEC || MBUF_VALID_SC(pr->sc)); VERIFY(pr->flow != 0); if (pr->sc != MBUF_SC_UNSPEC) { i = MBUF_SCIDX(pr->sc); VERIFY(i < IFCQ_SC_MAX); qfq_purgeq(qif, ifq->ifcq_disc_slots[i].cl, pr->flow, &pr->packets, &pr->bytes); } else { u_int32_t cnt, len; pr->packets = 0; pr->bytes = 0; for (i = 0; i < IFCQ_SC_MAX; i++) { qfq_purgeq(qif, ifq->ifcq_disc_slots[i].cl, pr->flow, &cnt, &len); pr->packets += cnt; pr->bytes += len; } } }
errno_t mbuf_get_service_class_index(mbuf_svc_class_t sc, u_int32_t *index) { if (index == NULL || !MBUF_VALID_SC(sc)) return (EINVAL); *index = MBUF_SCIDX(sc); return (0); }
errno_t mbuf_get_traffic_class_index(mbuf_traffic_class_t tc, u_int32_t *index) { if (index == NULL || (u_int32_t)tc >= MBUF_TC_MAX) return (EINVAL); *index = MBUF_SCIDX(m_service_class_from_val(MBUF_TC2SCVAL(tc))); return (0); }
/* * tcq_dequeue_tc_ifclassq is a dequeue function to be registered to * (*ifcq_dequeue) in struct ifclass. * * 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. */ static struct mbuf * tcq_dequeue_tc_ifclassq(struct ifclassq *ifq, mbuf_svc_class_t sc, cqdq_op_t op) { u_int32_t i = MBUF_SCIDX(sc); VERIFY((u_int32_t)i < IFCQ_SC_MAX); return (tcq_dequeue_cl(ifq->ifcq_disc, ifq->ifcq_disc_slots[i].cl, sc, op)); }
static int priq_stat_sc(struct priq_if *pif, cqrq_stat_sc_t *sr) { struct ifclassq *ifq = pif->pif_ifq; struct priq_class *cl; u_int32_t i; IFCQ_LOCK_ASSERT_HELD(ifq); VERIFY(sr->sc == MBUF_SC_UNSPEC || MBUF_VALID_SC(sr->sc)); i = MBUF_SCIDX(sr->sc); VERIFY(i < IFCQ_SC_MAX); cl = ifq->ifcq_disc_slots[i].cl; sr->packets = qlen(&cl->cl_q); sr->bytes = qsize(&cl->cl_q); return (0); }
/* * priq_enqueue_ifclassq is an enqueue function to be registered to * (*ifcq_enqueue) in struct ifclassq. */ static int priq_enqueue_ifclassq(struct ifclassq *ifq, struct mbuf *m) { u_int32_t i; IFCQ_LOCK_ASSERT_HELD(ifq); if (!(m->m_flags & M_PKTHDR)) { /* should not happen */ log(LOG_ERR, "%s: packet does not have pkthdr\n", if_name(ifq->ifcq_ifp)); IFCQ_CONVERT_LOCK(ifq); m_freem(m); return (ENOBUFS); } i = MBUF_SCIDX(mbuf_get_service_class(m)); VERIFY((u_int32_t)i < IFCQ_SC_MAX); return (priq_enqueue(ifq->ifcq_disc, ifq->ifcq_disc_slots[i].cl, m, m_pftag(m))); }