/* * priq_dequeue is a dequeue function to be registered to * (*altq_dequeue) in struct ifaltq. * * note: ALTDQ_POLL returns the next packet without removing the packet * from the queue. ALTDQ_REMOVE is a normal dequeue operation. * ALTDQ_REMOVE must return the same packet if called immediately * after ALTDQ_POLL. */ static struct mbuf * priq_dequeue(struct ifaltq *ifq, int op) { struct priq_if *pif = (struct priq_if *)ifq->altq_disc; struct priq_class *cl; struct mbuf *m; int pri; if (IFQ_IS_EMPTY(ifq)) /* no packet in the queue */ return (NULL); for (pri = pif->pif_maxpri; pri >= 0; pri--) { if ((cl = pif->pif_classes[pri]) != NULL && !qempty(cl->cl_q)) { if (op == ALTDQ_POLL) return (priq_pollq(cl)); m = priq_getq(cl); if (m != NULL) { IFQ_DEC_LEN(ifq); if (qempty(cl->cl_q)) cl->cl_period++; PKTCNTR_ADD(&cl->cl_xmitcnt, m_pktlen(m)); } return (m); } } return (NULL); }
/* * priq_dequeue is a dequeue function to be registered to * (*altq_dequeue) in struct ifaltq. * * note: ALTDQ_POLL returns the next packet without removing the packet * from the queue. ALTDQ_REMOVE is a normal dequeue operation. * ALTDQ_REMOVE must return the same packet if called immediately * after ALTDQ_POLL. */ static struct mbuf * priq_dequeue(struct ifaltq_subque *ifsq, struct mbuf *mpolled, int op) { struct ifaltq *ifq = ifsq->ifsq_altq; struct priq_if *pif = (struct priq_if *)ifq->altq_disc; struct priq_class *cl; struct mbuf *m; int pri; if (ifsq_get_index(ifsq) != PRIQ_SUBQ_INDEX) { /* * Race happened, the unrelated subqueue was * picked during the packet scheduler transition. */ ifsq_classic_request(ifsq, ALTRQ_PURGE, NULL); return NULL; } if (ifsq_is_empty(ifsq)) { /* no packet in the queue */ KKASSERT(mpolled == NULL); return (NULL); } crit_enter(); m = NULL; for (pri = pif->pif_maxpri; pri >= 0; pri--) { if ((cl = pif->pif_classes[pri]) != NULL && !qempty(cl->cl_q)) { if (op == ALTDQ_POLL) { m = priq_pollq(cl); break; } m = priq_getq(cl); if (m != NULL) { ifsq->ifq_len--; if (qempty(cl->cl_q)) cl->cl_period++; PKTCNTR_ADD(&cl->cl_xmitcnt, m_pktlen(m)); } break; } } crit_exit(); KKASSERT(mpolled == NULL || mpolled == m); 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 * 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); }