Path: blob/main/sys/netpfil/ipfw/dn_sched_fq_codel.h
39482 views
/*-1* Copyright (C) 2016 Centre for Advanced Internet Architectures,2* Swinburne University of Technology, Melbourne, Australia.3* Portions of this code were made possible in part by a gift from4* The Comcast Innovation Fund.5* Implemented by Rasool Al-Saadi <[email protected]>6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* FQ_Codel Structures and helper functions31*/3233#ifndef _IP_DN_SCHED_FQ_CODEL_H34#define _IP_DN_SCHED_FQ_CODEL_H3536/* list of queues */37STAILQ_HEAD(fq_codel_list, fq_codel_flow);3839/* fq_codel parameters including codel */40struct dn_sch_fq_codel_parms {41struct dn_aqm_codel_parms ccfg; /* CoDel Parameters */42/* FQ_CODEL Parameters */43uint32_t flows_cnt; /* number of flows */44uint32_t limit; /* hard limit of fq_codel queue size*/45uint32_t quantum;46}; /* defaults */4748/* flow (sub-queue) stats */49struct flow_stats {50uint64_t tot_pkts; /* statistics counters */51uint64_t tot_bytes;52uint32_t length; /* Queue length, in packets */53uint32_t len_bytes; /* Queue length, in bytes */54uint32_t drops;55};5657/* A flow of packets (sub-queue).*/58struct fq_codel_flow {59struct mq mq; /* list of packets */60struct flow_stats stats; /* statistics */61int deficit;62int active; /* 1: flow is active (in a list) */63struct codel_status cst;64STAILQ_ENTRY(fq_codel_flow) flowchain;65};6667/* extra fq_codel scheduler configurations */68struct fq_codel_schk {69struct dn_sch_fq_codel_parms cfg;70};7172/* fq_codel scheduler instance */73struct fq_codel_si {74struct dn_sch_inst _si; /* standard scheduler instance */75struct dn_queue main_q; /* main queue is after si directly */7677struct fq_codel_flow *flows; /* array of flows (queues) */78uint32_t perturbation; /* random value */79struct fq_codel_list newflows; /* list of new queues */80struct fq_codel_list oldflows; /* list of old queues */81};8283/* Helper function to update queue&main-queue and scheduler statistics.84* negative len + drop -> drop85* negative len -> dequeue86* positive len -> enqueue87* positive len + drop -> drop during enqueue88*/89__inline static void90fq_update_stats(struct fq_codel_flow *q, struct fq_codel_si *si, int len,91int drop)92{93int inc = 0;9495if (len < 0)96inc = -1;97else if (len > 0)98inc = 1;99100if (drop) {101si->main_q.ni.drops ++;102q->stats.drops ++;103si->_si.ni.drops ++;104V_dn_cfg.io_pkt_drop ++;105}106107if (!drop || (drop && len < 0)) {108/* Update stats for the main queue */109si->main_q.ni.length += inc;110si->main_q.ni.len_bytes += len;111112/*update sub-queue stats */113q->stats.length += inc;114q->stats.len_bytes += len;115116/*update scheduler instance stats */117si->_si.ni.length += inc;118si->_si.ni.len_bytes += len;119}120121if (inc > 0) {122si->main_q.ni.tot_bytes += len;123si->main_q.ni.tot_pkts ++;124125q->stats.tot_bytes +=len;126q->stats.tot_pkts++;127128si->_si.ni.tot_bytes +=len;129si->_si.ni.tot_pkts ++;130}131132}133134/* extract the head of fq_codel sub-queue */135__inline static struct mbuf *136fq_codel_extract_head(struct fq_codel_flow *q, aqm_time_t *pkt_ts, struct fq_codel_si *si)137{138struct mbuf *m;139140next: m = q->mq.head;141if (m == NULL)142return m;143q->mq.head = m->m_nextpkt;144145fq_update_stats(q, si, -m->m_pkthdr.len, 0);146147if (si->main_q.ni.length == 0) /* queue is now idle */148si->main_q.q_time = V_dn_cfg.curr_time;149150/* extract packet timestamp*/151struct m_tag *mtag;152mtag = m_tag_locate(m, MTAG_ABI_COMPAT, DN_AQM_MTAG_TS, NULL);153if (mtag == NULL){154D("timestamp tag is not found!");155*pkt_ts = 0;156} else {157*pkt_ts = *(aqm_time_t *)(mtag + 1);158m_tag_delete(m,mtag);159}160if (m->m_pkthdr.rcvif != NULL &&161__predict_false(m_rcvif_restore(m) == NULL)) {162m_freem(m);163goto next;164}165return m;166}167168#endif169170171