1300779Struckman/*- 2300779Struckman * Copyright (C) 2016 Centre for Advanced Internet Architectures, 3300779Struckman * Swinburne University of Technology, Melbourne, Australia. 4300779Struckman * Portions of this code were made possible in part by a gift from 5300779Struckman * The Comcast Innovation Fund. 6300779Struckman * Implemented by Rasool Al-Saadi <ralsaadi@swin.edu.au> 7300779Struckman * 8300779Struckman * Redistribution and use in source and binary forms, with or without 9300779Struckman * modification, are permitted provided that the following conditions 10300779Struckman * are met: 11300779Struckman * 1. Redistributions of source code must retain the above copyright 12300779Struckman * notice, this list of conditions and the following disclaimer. 13300779Struckman * 2. Redistributions in binary form must reproduce the above copyright 14300779Struckman * notice, this list of conditions and the following disclaimer in the 15300779Struckman * documentation and/or other materials provided with the distribution. 16300779Struckman * 17300779Struckman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18300779Struckman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19300779Struckman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20300779Struckman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21300779Struckman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22300779Struckman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23300779Struckman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24300779Struckman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25300779Struckman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26300779Struckman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27300779Struckman * SUCH DAMAGE. 28300779Struckman */ 29300779Struckman 30300779Struckman/* 31300779Struckman * FQ_Codel Structures and helper functions 32300779Struckman * 33300779Struckman * $FreeBSD$ 34300779Struckman */ 35300779Struckman 36300779Struckman#ifndef _IP_DN_SCHED_FQ_CODEL_H 37300779Struckman#define _IP_DN_SCHED_FQ_CODEL_H 38300779Struckman 39300779Struckman/* list of queues */ 40300779StruckmanSTAILQ_HEAD(fq_codel_list, fq_codel_flow) ; 41300779Struckman 42300779Struckman/* fq_codel parameters including codel */ 43300779Struckmanstruct dn_sch_fq_codel_parms { 44300779Struckman struct dn_aqm_codel_parms ccfg; /* CoDel Parameters */ 45300779Struckman /* FQ_CODEL Parameters */ 46300779Struckman uint32_t flows_cnt; /* number of flows */ 47300779Struckman uint32_t limit; /* hard limit of fq_codel queue size*/ 48300779Struckman uint32_t quantum; 49300779Struckman}; /* defaults */ 50300779Struckman 51300779Struckman/* flow (sub-queue) stats */ 52300779Struckmanstruct flow_stats { 53300779Struckman uint64_t tot_pkts; /* statistics counters */ 54300779Struckman uint64_t tot_bytes; 55300779Struckman uint32_t length; /* Queue length, in packets */ 56300779Struckman uint32_t len_bytes; /* Queue length, in bytes */ 57300779Struckman uint32_t drops; 58300779Struckman}; 59300779Struckman 60300779Struckman/* A flow of packets (sub-queue).*/ 61300779Struckmanstruct fq_codel_flow { 62300779Struckman struct mq mq; /* list of packets */ 63300779Struckman struct flow_stats stats; /* statistics */ 64300779Struckman int deficit; 65300779Struckman int active; /* 1: flow is active (in a list) */ 66300779Struckman struct codel_status cst; 67300779Struckman STAILQ_ENTRY(fq_codel_flow) flowchain; 68300779Struckman}; 69300779Struckman 70300779Struckman/* extra fq_codel scheduler configurations */ 71300779Struckmanstruct fq_codel_schk { 72300779Struckman struct dn_sch_fq_codel_parms cfg; 73300779Struckman}; 74300779Struckman 75300779Struckman/* fq_codel scheduler instance */ 76300779Struckmanstruct fq_codel_si { 77300779Struckman struct dn_sch_inst _si; /* standard scheduler instance */ 78300779Struckman struct dn_queue main_q; /* main queue is after si directly */ 79300779Struckman 80300779Struckman struct fq_codel_flow *flows; /* array of flows (queues) */ 81300779Struckman uint32_t perturbation; /* random value */ 82300779Struckman struct fq_codel_list newflows; /* list of new queues */ 83300779Struckman struct fq_codel_list oldflows; /* list of old queues */ 84300779Struckman}; 85300779Struckman 86300779Struckman/* Helper function to update queue&main-queue and scheduler statistics. 87300779Struckman * negative len + drop -> drop 88300779Struckman * negative len -> dequeue 89300779Struckman * positive len -> enqueue 90300779Struckman * positive len + drop -> drop during enqueue 91300779Struckman */ 92300779Struckman__inline static void 93300779Struckmanfq_update_stats(struct fq_codel_flow *q, struct fq_codel_si *si, int len, 94300779Struckman int drop) 95300779Struckman{ 96300779Struckman int inc = 0; 97300779Struckman 98300779Struckman if (len < 0) 99300779Struckman inc = -1; 100300779Struckman else if (len > 0) 101300779Struckman inc = 1; 102300779Struckman 103300779Struckman if (drop) { 104300779Struckman si->main_q.ni.drops ++; 105300779Struckman q->stats.drops ++; 106300779Struckman si->_si.ni.drops ++; 107300779Struckman io_pkt_drop ++; 108300779Struckman } 109300779Struckman 110300779Struckman if (!drop || (drop && len < 0)) { 111300779Struckman /* Update stats for the main queue */ 112300779Struckman si->main_q.ni.length += inc; 113300779Struckman si->main_q.ni.len_bytes += len; 114300779Struckman 115300779Struckman /*update sub-queue stats */ 116300779Struckman q->stats.length += inc; 117300779Struckman q->stats.len_bytes += len; 118300779Struckman 119300779Struckman /*update scheduler instance stats */ 120300779Struckman si->_si.ni.length += inc; 121300779Struckman si->_si.ni.len_bytes += len; 122300779Struckman } 123300779Struckman 124300779Struckman if (inc > 0) { 125300779Struckman si->main_q.ni.tot_bytes += len; 126300779Struckman si->main_q.ni.tot_pkts ++; 127300779Struckman 128300779Struckman q->stats.tot_bytes +=len; 129300779Struckman q->stats.tot_pkts++; 130300779Struckman 131300779Struckman si->_si.ni.tot_bytes +=len; 132300779Struckman si->_si.ni.tot_pkts ++; 133300779Struckman } 134300779Struckman 135300779Struckman} 136300779Struckman 137300779Struckman/* extract the head of fq_codel sub-queue */ 138300779Struckman__inline static struct mbuf * 139300779Struckmanfq_codel_extract_head(struct fq_codel_flow *q, aqm_time_t *pkt_ts, struct fq_codel_si *si) 140300779Struckman{ 141300779Struckman struct mbuf *m = q->mq.head; 142300779Struckman 143300779Struckman if (m == NULL) 144300779Struckman return m; 145300779Struckman q->mq.head = m->m_nextpkt; 146300779Struckman 147300779Struckman fq_update_stats(q, si, -m->m_pkthdr.len, 0); 148300779Struckman 149300779Struckman if (si->main_q.ni.length == 0) /* queue is now idle */ 150300779Struckman si->main_q.q_time = dn_cfg.curr_time; 151300779Struckman 152300779Struckman /* extract packet timestamp*/ 153300779Struckman struct m_tag *mtag; 154300779Struckman mtag = m_tag_locate(m, MTAG_ABI_COMPAT, DN_AQM_MTAG_TS, NULL); 155300779Struckman if (mtag == NULL){ 156300779Struckman D("timestamp tag is not found!"); 157300779Struckman *pkt_ts = 0; 158300779Struckman } else { 159300779Struckman *pkt_ts = *(aqm_time_t *)(mtag + 1); 160300779Struckman m_tag_delete(m,mtag); 161300779Struckman } 162300779Struckman 163300779Struckman return m; 164300779Struckman} 165300779Struckman 166300779Struckman 167300779Struckman#endif 168