X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3903760236c30e3b5ace7a4eefac3a269d68957c..5ba3f43ea354af8ad55bea84372a2bc834d8757c:/bsd/net/classq/classq.c diff --git a/bsd/net/classq/classq.c b/bsd/net/classq/classq.c index 67c1f44ea..35d86188f 100644 --- a/bsd/net/classq/classq.c +++ b/bsd/net/classq/classq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2016 Apple Inc. All rights reserved. + * Copyright (c) 2007-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -73,6 +73,7 @@ #include + u_int32_t classq_verbose = 0; /* more noise if greater than 1 */ SYSCTL_NODE(_net, OID_AUTO, classq, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "classq"); @@ -81,44 +82,100 @@ SYSCTL_UINT(_net_classq, OID_AUTO, verbose, CTLFLAG_RW|CTLFLAG_LOCKED, &classq_verbose, 0, "Class queue verbosity level"); void -_qinit(class_queue_t *q, int type, int lim) +_qinit(class_queue_t *q, int type, int lim, classq_pkt_type_t ptype) { - MBUFQ_INIT(&q->mbufq); + switch (ptype) { + case QP_MBUF: + MBUFQ_INIT(&qmbufq(q)); + break; + + + default: + VERIFY(0); + /* NOTREACHED */ + } + qlimit(q) = lim; qlen(q) = 0; qsize(q) = 0; qtype(q) = type; + qptype(q) = ptype; qstate(q) = QS_RUNNING; } /* add a packet at the tail of the queue */ void -_addq(class_queue_t *q, struct mbuf *m) +_addq(class_queue_t *q, void *pkt) { - MBUFQ_ENQUEUE(&q->mbufq, m); + uint32_t size = 0; + + switch (qptype(q)) { + case QP_MBUF: { + struct mbuf *m = pkt; + MBUFQ_ENQUEUE(&qmbufq(q), m); + size = m_length(m); + break; + } + + + default: + VERIFY(0); + /* NOTREACHED */ + } + qlen(q)++; VERIFY(qlen(q) != 0); - qsize(q) += m_length(m); + qsize(q) += size; } /* add one or more packets at the tail of the queue */ void -_addq_multi(class_queue_t *q, struct mbuf *m_head, struct mbuf *m_tail, +_addq_multi(class_queue_t *q, void *pkt_head, void *pkt_tail, u_int32_t cnt, u_int32_t size) { - MBUFQ_ENQUEUE_MULTI(&q->mbufq, m_head, m_tail); + switch (qptype(q)) { + case QP_MBUF: { + struct mbuf *m_head = pkt_head; + struct mbuf *m_tail = pkt_tail; + MBUFQ_ENQUEUE_MULTI(&qmbufq(q), m_head, m_tail); + break; + } + + + default: + VERIFY(0); + /* NOTREACHED */ + } + qlen(q) += cnt; qsize(q) += size; } /* get a packet at the head of the queue */ -struct mbuf * +void * _getq(class_queue_t *q) { - struct mbuf *m; + void *pkt = NULL; + uint32_t pkt_len; + + switch (qptype(q)) { + case QP_MBUF: { + struct mbuf *m; + MBUFQ_DEQUEUE(&qmbufq(q), m); + if (m != NULL) { + pkt_len = m_length(m); + pkt = m; + } + break; + } + + + default: + VERIFY(0); + /* NOTREACHED */ + } - MBUFQ_DEQUEUE(&q->mbufq, m); - if (m == NULL) { + if (pkt == NULL) { VERIFY(qlen(q) == 0); if (qsize(q) > 0) qsize(q) = 0; @@ -128,73 +185,97 @@ _getq(class_queue_t *q) qlen(q)--; /* qsize is an approximation, so adjust if necessary */ - if (((int)qsize(q) - m_length(m)) > 0) - qsize(q) -= m_length(m); + if (((int)qsize(q) - pkt_len) > 0) + qsize(q) -= pkt_len; else if (qsize(q) != 0) qsize(q) = 0; - return (m); + return (pkt); } -static struct mbuf * +static void * _getq_flow_or_scidx(class_queue_t *q, u_int32_t val, boolean_t isflowid) { - struct mbuf *m, *m_tmp; - - MBUFQ_FOREACH_SAFE(m, &q->mbufq, m_tmp) { - if ((isflowid && (val == 0 || ((m->m_flags & M_PKTHDR) && - m->m_pkthdr.pkt_flowid == val))) || - (!isflowid && - MBUF_SCIDX(mbuf_get_service_class(m)) < val)) { - /* remove it from the class queue */ - MBUFQ_REMOVE(&q->mbufq, m); - MBUFQ_NEXT(m) = NULL; - break; + void *pkt = NULL; + uint32_t pkt_len; + + switch (qptype(q)) { + case QP_MBUF: { + struct mbuf *m, *m_tmp; + + MBUFQ_FOREACH_SAFE(m, &qmbufq(q), m_tmp) { + if ((isflowid && (val == 0 || + ((m->m_flags & M_PKTHDR) && + m->m_pkthdr.pkt_flowid == val))) || + (!isflowid && + MBUF_SCIDX(mbuf_get_service_class(m)) < val)) { + /* remove it from the class queue */ + MBUFQ_REMOVE(&qmbufq(q), m); + MBUFQ_NEXT(m) = NULL; + break; + } + } + if (m != NULL) { + pkt = m; + pkt_len = m_length(m); } + break; } - if (m != NULL) { - u_int32_t l = m_length(m); + default: + VERIFY(0); + /* NOTREACHED */ + } + + if (pkt != NULL) { VERIFY(qlen(q) > 0); qlen(q)--; /* qsize is an approximation, so adjust if necessary */ - if (((int)qsize(q) - l) > 0) - qsize(q) -= l; + if (((int)qsize(q) - pkt_len) > 0) + qsize(q) -= pkt_len; else if (qsize(q) != 0) qsize(q) = 0; } - return (m); - + return (pkt); } /* get a packet of a specific flow beginning from the head of the queue */ -struct mbuf * +void * _getq_flow(class_queue_t *q, u_int32_t flow) { return (_getq_flow_or_scidx(q, flow, TRUE)); } /* Get a packet whose MBUF_SCIDX() < scidx from head of queue */ -struct mbuf * +void * _getq_scidx_lt(class_queue_t *q, u_int32_t scidx) { return (_getq_flow_or_scidx(q, scidx, FALSE)); } -/* get all packets starting from the head of the queue */ -struct mbuf * -_getq_all(class_queue_t *q, struct mbuf **last, u_int32_t *qlenp, +/* get all packets (chained) starting from the head of the queue */ +void * +_getq_all(class_queue_t *q, void **last, u_int32_t *qlenp, u_int64_t *qsizep) { - struct mbuf *m; + void *pkt = NULL; + + switch (qptype(q)) { + case QP_MBUF: + pkt = MBUFQ_FIRST(&qmbufq(q)); + if (last != NULL) + *last = MBUFQ_LAST(&qmbufq(q)); + MBUFQ_INIT(&qmbufq(q)); + break; - m = MBUFQ_FIRST(&q->mbufq); - if (last != NULL) - *last = MBUFQ_LAST(&q->mbufq); - MBUFQ_INIT(&q->mbufq); + + default: + VERIFY(0); + /* NOTREACHED */ + } if (qlenp != NULL) *qlenp = qlen(q); @@ -204,14 +285,13 @@ _getq_all(class_queue_t *q, struct mbuf **last, u_int32_t *qlenp, qlen(q) = 0; qsize(q) = 0; - return (m); + return (pkt); } -/* drop a packet at the tail of the queue */ -struct mbuf * -_getq_tail(class_queue_t *q) +static inline struct mbuf * +_getq_tail_mbuf(class_queue_t *q) { - struct mq_head *head = &q->mbufq; + struct mq_head *head = &qmbufq(q); struct mbuf *m = MBUFQ_LAST(head); if (m != NULL) { @@ -247,15 +327,36 @@ _getq_tail(class_queue_t *q) return (m); } -/* randomly select a packet in the queue */ -struct mbuf * -_getq_random(class_queue_t *q) +/* drop a packet at the tail of the queue */ +void * +_getq_tail(class_queue_t *q) +{ + void *t = NULL; + + switch (qptype(q)) { + case QP_MBUF: + t = _getq_tail_mbuf(q); + break; + + default: + VERIFY(0); + /* NOTREACHED */ + } + + return (t); +} + +static inline struct mbuf * +_getq_random_mbuf(class_queue_t *q) { - struct mq_head *head = &q->mbufq; + struct mq_head *head = &qmbufq(q); struct mbuf *m = NULL; unsigned int n; u_int32_t rnd; + /* XXX: Add support for Kernel packet when needed */ + VERIFY((qptype(q) == QP_MBUF)); + n = qlen(q); if (n == 0) { VERIFY(MBUFQ_EMPTY(head)); @@ -265,7 +366,7 @@ _getq_random(class_queue_t *q) } m = MBUFQ_FIRST(head); - read_random(&rnd, sizeof (rnd)); + read_frandom(&rnd, sizeof (rnd)); n = (rnd % n) + 1; if (n == 1) { @@ -301,11 +402,29 @@ _getq_random(class_queue_t *q) return (m); } -/* remove a packet from the queue */ -void -_removeq(class_queue_t *q, struct mbuf *m) +/* randomly select a packet in the queue */ +void * +_getq_random(class_queue_t *q) +{ + void *r = NULL; + + switch (qptype(q)) { + case QP_MBUF: + r = _getq_random_mbuf(q); + break; + + default: + VERIFY(0); + /* NOTREACHED */ + } + + return (r); +} + +static inline void +_removeq_mbuf(class_queue_t *q, struct mbuf *m) { - struct mq_head *head = &q->mbufq; + struct mq_head *head = &qmbufq(q); struct mbuf *m0, **mtail; m0 = MBUFQ_FIRST(head); @@ -339,14 +458,30 @@ _removeq(class_queue_t *q, struct mbuf *m) MBUFQ_NEXT(m) = NULL; } +/* remove a packet from the queue */ +void +_removeq(class_queue_t *q, void *pkt) +{ + switch (qptype(q)) { + case QP_MBUF: + _removeq_mbuf(q, pkt); + break; + + default: + VERIFY(0); + /* NOTREACHED */ + } +} + void _flushq(class_queue_t *q) { (void) _flushq_flow(q, 0, NULL, NULL); } -void -_flushq_flow(class_queue_t *q, u_int32_t flow, u_int32_t *cnt, u_int32_t *len) +static inline void +_flushq_flow_mbuf(class_queue_t *q, u_int32_t flow, u_int32_t *cnt, + u_int32_t *len) { MBUFQ_HEAD(mq_freeq) freeq; struct mbuf *m, *m_tmp; @@ -354,11 +489,11 @@ _flushq_flow(class_queue_t *q, u_int32_t flow, u_int32_t *cnt, u_int32_t *len) MBUFQ_INIT(&freeq); - MBUFQ_FOREACH_SAFE(m, &q->mbufq, m_tmp) { + MBUFQ_FOREACH_SAFE(m, &qmbufq(q), m_tmp) { if (flow == 0 || ((m->m_flags & M_PKTHDR) && m->m_pkthdr.pkt_flowid == flow)) { /* remove it from the class queue */ - MBUFQ_REMOVE(&q->mbufq, m); + MBUFQ_REMOVE(&qmbufq(q), m); MBUFQ_NEXT(m) = NULL; /* and add it to the free queue */ @@ -389,3 +524,17 @@ _flushq_flow(class_queue_t *q, u_int32_t flow, u_int32_t *cnt, u_int32_t *len) if (len != NULL) *len = l; } + +void +_flushq_flow(class_queue_t *q, u_int32_t flow, u_int32_t *cnt, u_int32_t *len) +{ + switch (qptype(q)) { + case QP_MBUF: + _flushq_flow_mbuf(q, flow, cnt, len); + break; + + default: + VERIFY(0); + /* NOTREACHED */ + } +}