|
| 1 | +/*- |
| 2 | + * Copyright (C) 2016 Centre for Advanced Internet Architectures, |
| 3 | + * Swinburne University of Technology, Melbourne, Australia. |
| 4 | + * Portions of this code were made possible in part by a gift from |
| 5 | + * The Comcast Innovation Fund. |
| 6 | + * Implemented by Rasool Al-Saadi <ralsaadi@swin.edu.au> |
| 7 | + * |
| 8 | + * Redistribution and use in source and binary forms, with or without |
| 9 | + * modification, are permitted provided that the following conditions |
| 10 | + * are met: |
| 11 | + * 1. Redistributions of source code must retain the above copyright |
| 12 | + * notice, this list of conditions and the following disclaimer. |
| 13 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | + * notice, this list of conditions and the following disclaimer in the |
| 15 | + * documentation and/or other materials provided with the distribution. |
| 16 | + * |
| 17 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 18 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 21 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | + * SUCH DAMAGE. |
| 28 | + */ |
| 29 | + |
| 30 | +/* |
| 31 | + * API for writting an Active Queue Management algorithm for Dummynet |
| 32 | + */ |
| 33 | + |
| 34 | +#ifndef _IP_DN_AQM_H |
| 35 | +#define _IP_DN_AQM_H |
| 36 | + |
| 37 | + |
| 38 | +/* NOW is the current time in millisecond*/ |
| 39 | +#define NOW ((dn_cfg.curr_time * tick) / 1000) |
| 40 | + |
| 41 | +#define AQM_UNOW (dn_cfg.curr_time * tick) |
| 42 | +#define AQM_TIME_1US ((aqm_time_t)(1)) |
| 43 | +#define AQM_TIME_1MS ((aqm_time_t)(1000)) |
| 44 | +#define AQM_TIME_1S ((aqm_time_t)(AQM_TIME_1MS * 1000)) |
| 45 | + |
| 46 | +/* aqm time allows to store up to 4294 seconds */ |
| 47 | +typedef uint32_t aqm_time_t; |
| 48 | +typedef int32_t aqm_stime_t; |
| 49 | + |
| 50 | +#define DN_AQM_MTAG_TS 55345 |
| 51 | + |
| 52 | +/* Macro for variable bounding */ |
| 53 | +#define BOUND_VAR(x,l,h) (x < l? l : x > h? h : x) |
| 54 | + |
| 55 | +/* sysctl variable to count number of droped packets */ |
| 56 | +extern unsigned long io_pkt_drop; |
| 57 | + |
| 58 | +/* |
| 59 | + * Structure for holding data and function pointers that together represent a |
| 60 | + * AQM algorithm. |
| 61 | + */ |
| 62 | + struct dn_aqm { |
| 63 | +#define DN_AQM_NAME_MAX 50 |
| 64 | + char name[DN_AQM_NAME_MAX]; /* name of AQM algorithm */ |
| 65 | + uint32_t type; /* AQM type number */ |
| 66 | + |
| 67 | + /* Methods implemented by AQM algorithm: |
| 68 | + * |
| 69 | + * enqueue enqueue packet 'm' on queue 'q'. |
| 70 | + * Return 0 on success, 1 on drop. |
| 71 | + * |
| 72 | + * dequeue dequeue a packet from queue 'q'. |
| 73 | + * Return a packet, NULL if no packet available. |
| 74 | + * |
| 75 | + * config configure AQM algorithm |
| 76 | + * If required, this function should allocate space to store |
| 77 | + * the configurations and set 'fs->aqmcfg' to point to this space. |
| 78 | + * 'dn_extra_parms' includes array of parameters send |
| 79 | + * from ipfw userland command. |
| 80 | + * Return 0 on success, non-zero otherwise. |
| 81 | + * |
| 82 | + * deconfig deconfigure AQM algorithm. |
| 83 | + * The allocated configuration memory space should be freed here. |
| 84 | + * Return 0 on success, non-zero otherwise. |
| 85 | + * |
| 86 | + * init initialise AQM status variables of queue 'q' |
| 87 | + * This function is used to allocate space and init AQM status for a |
| 88 | + * queue and q->aqm_status to point to this space. |
| 89 | + * Return 0 on success, non-zero otherwise. |
| 90 | + * |
| 91 | + * cleanup cleanup AQM status variables of queue 'q' |
| 92 | + * The allocated memory space for AQM status should be freed here. |
| 93 | + * Return 0 on success, non-zero otherwise. |
| 94 | + * |
| 95 | + * getconfig retrieve AQM configurations |
| 96 | + * This function is used to return AQM parameters to userland |
| 97 | + * command. The function should fill 'dn_extra_parms' struct with |
| 98 | + * the AQM configurations using 'par' array. |
| 99 | + * |
| 100 | + */ |
| 101 | + |
| 102 | + int (*enqueue)(struct dn_queue *, struct mbuf *); |
| 103 | + struct mbuf * (*dequeue)(struct dn_queue *); |
| 104 | + int (*config)(struct dn_fsk *, struct dn_extra_parms *ep, int); |
| 105 | + int (*deconfig)(struct dn_fsk *); |
| 106 | + int (*init)(struct dn_queue *); |
| 107 | + int (*cleanup)(struct dn_queue *); |
| 108 | + int (*getconfig)(struct dn_fsk *, struct dn_extra_parms *); |
| 109 | + |
| 110 | + int ref_count; /*Number of queues instances in the system */ |
| 111 | + int cfg_ref_count; /*Number of AQM instances in the system */ |
| 112 | + SLIST_ENTRY (dn_aqm) next; /* Next AQM in the list */ |
| 113 | +}; |
| 114 | + |
| 115 | +/* Helper function to update queue and scheduler statistics. |
| 116 | + * negative len + drop -> drop |
| 117 | + * negative len -> dequeue |
| 118 | + * positive len -> enqueue |
| 119 | + * positive len + drop -> drop during enqueue |
| 120 | + */ |
| 121 | +__inline static void |
| 122 | +update_stats(struct dn_queue *q, int len, int drop) |
| 123 | +{ |
| 124 | + int inc = 0; |
| 125 | + struct dn_flow *sni; |
| 126 | + struct dn_flow *qni; |
| 127 | + |
| 128 | + sni = &q->_si->ni; |
| 129 | + qni = &q->ni; |
| 130 | + |
| 131 | + if (len < 0) |
| 132 | + inc = -1; |
| 133 | + else if(len > 0) |
| 134 | + inc = 1; |
| 135 | + |
| 136 | + if (drop) { |
| 137 | + qni->drops++; |
| 138 | + sni->drops++; |
| 139 | + io_pkt_drop++; |
| 140 | + } else { |
| 141 | + /*update queue stats */ |
| 142 | + qni->length += inc; |
| 143 | + qni->len_bytes += len; |
| 144 | + |
| 145 | + /*update scheduler instance stats */ |
| 146 | + sni->length += inc; |
| 147 | + sni->len_bytes += len; |
| 148 | + } |
| 149 | + /* tot_pkts is updated in dn_enqueue function */ |
| 150 | +} |
| 151 | + |
| 152 | + |
| 153 | +/* kernel module related function */ |
| 154 | +int |
| 155 | +dn_aqm_modevent(module_t mod, int cmd, void *arg); |
| 156 | + |
| 157 | +#define DECLARE_DNAQM_MODULE(name, dnaqm) \ |
| 158 | + static moduledata_t name##_mod = { \ |
| 159 | + #name, dn_aqm_modevent, dnaqm \ |
| 160 | + }; \ |
| 161 | + DECLARE_MODULE(name, name##_mod, \ |
| 162 | + SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); \ |
| 163 | + MODULE_DEPEND(name, dummynet, 3, 3, 3) |
| 164 | + |
| 165 | +#endif |
0 commit comments