168 lines
5.4 KiB
C
168 lines
5.4 KiB
C
|
/*-
|
||
|
* Copyright (C) 2016 Centre for Advanced Internet Architectures,
|
||
|
* Swinburne University of Technology, Melbourne, Australia.
|
||
|
* Portions of this code were made possible in part by a gift from
|
||
|
* The Comcast Innovation Fund.
|
||
|
* Implemented by Rasool Al-Saadi <ralsaadi@swin.edu.au>
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* API for writting an Active Queue Management algorithm for Dummynet
|
||
|
*
|
||
|
* $FreeBSD$
|
||
|
*/
|
||
|
|
||
|
#ifndef _IP_DN_AQM_H
|
||
|
#define _IP_DN_AQM_H
|
||
|
|
||
|
|
||
|
/* NOW is the current time in millisecond*/
|
||
|
#define NOW ((dn_cfg.curr_time * tick) / 1000)
|
||
|
|
||
|
#define AQM_UNOW (dn_cfg.curr_time * tick)
|
||
|
#define AQM_TIME_1US ((aqm_time_t)(1))
|
||
|
#define AQM_TIME_1MS ((aqm_time_t)(1000))
|
||
|
#define AQM_TIME_1S ((aqm_time_t)(AQM_TIME_1MS * 1000))
|
||
|
|
||
|
/* aqm time allows to store up to 4294 seconds */
|
||
|
typedef uint32_t aqm_time_t;
|
||
|
typedef int32_t aqm_stime_t;
|
||
|
|
||
|
#define DN_AQM_MTAG_TS 55345
|
||
|
|
||
|
/* Macro for variable bounding */
|
||
|
#define BOUND_VAR(x,l,h) (x < l? l : x > h? h : x)
|
||
|
|
||
|
/* sysctl variable to count number of droped packets */
|
||
|
extern unsigned long io_pkt_drop;
|
||
|
|
||
|
/*
|
||
|
* Structure for holding data and function pointers that together represent a
|
||
|
* AQM algorithm.
|
||
|
*/
|
||
|
struct dn_aqm {
|
||
|
#define DN_AQM_NAME_MAX 50
|
||
|
char name[DN_AQM_NAME_MAX]; /* name of AQM algorithm */
|
||
|
uint32_t type; /* AQM type number */
|
||
|
|
||
|
/* Methods implemented by AQM algorithm:
|
||
|
*
|
||
|
* enqueue enqueue packet 'm' on queue 'q'.
|
||
|
* Return 0 on success, 1 on drop.
|
||
|
*
|
||
|
* dequeue dequeue a packet from queue 'q'.
|
||
|
* Return a packet, NULL if no packet available.
|
||
|
*
|
||
|
* config configure AQM algorithm
|
||
|
* If required, this function should allocate space to store
|
||
|
* the configurations and set 'fs->aqmcfg' to point to this space.
|
||
|
* 'dn_extra_parms' includes array of parameters send
|
||
|
* from ipfw userland command.
|
||
|
* Return 0 on success, non-zero otherwise.
|
||
|
*
|
||
|
* deconfig deconfigure AQM algorithm.
|
||
|
* The allocated configuration memory space should be freed here.
|
||
|
* Return 0 on success, non-zero otherwise.
|
||
|
*
|
||
|
* init initialise AQM status variables of queue 'q'
|
||
|
* This function is used to allocate space and init AQM status for a
|
||
|
* queue and q->aqm_status to point to this space.
|
||
|
* Return 0 on success, non-zero otherwise.
|
||
|
*
|
||
|
* cleanup cleanup AQM status variables of queue 'q'
|
||
|
* The allocated memory space for AQM status should be freed here.
|
||
|
* Return 0 on success, non-zero otherwise.
|
||
|
*
|
||
|
* getconfig retrieve AQM configurations
|
||
|
* This function is used to return AQM parameters to userland
|
||
|
* command. The function should fill 'dn_extra_parms' struct with
|
||
|
* the AQM configurations using 'par' array.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
int (*enqueue)(struct dn_queue *, struct mbuf *);
|
||
|
struct mbuf * (*dequeue)(struct dn_queue *);
|
||
|
int (*config)(struct dn_fsk *, struct dn_extra_parms *ep, int);
|
||
|
int (*deconfig)(struct dn_fsk *);
|
||
|
int (*init)(struct dn_queue *);
|
||
|
int (*cleanup)(struct dn_queue *);
|
||
|
int (*getconfig)(struct dn_fsk *, struct dn_extra_parms *);
|
||
|
|
||
|
int ref_count; /*Number of queues instances in the system */
|
||
|
int cfg_ref_count; /*Number of AQM instances in the system */
|
||
|
SLIST_ENTRY (dn_aqm) next; /* Next AQM in the list */
|
||
|
};
|
||
|
|
||
|
/* Helper function to update queue and scheduler statistics.
|
||
|
* negative len + drop -> drop
|
||
|
* negative len -> dequeue
|
||
|
* positive len -> enqueue
|
||
|
* positive len + drop -> drop during enqueue
|
||
|
*/
|
||
|
__inline static void
|
||
|
update_stats(struct dn_queue *q, int len, int drop)
|
||
|
{
|
||
|
int inc = 0;
|
||
|
struct dn_flow *sni;
|
||
|
struct dn_flow *qni;
|
||
|
|
||
|
sni = &q->_si->ni;
|
||
|
qni = &q->ni;
|
||
|
|
||
|
if (len < 0)
|
||
|
inc = -1;
|
||
|
else if(len > 0)
|
||
|
inc = 1;
|
||
|
|
||
|
if (drop) {
|
||
|
qni->drops++;
|
||
|
sni->drops++;
|
||
|
io_pkt_drop++;
|
||
|
} else {
|
||
|
/*update queue stats */
|
||
|
qni->length += inc;
|
||
|
qni->len_bytes += len;
|
||
|
|
||
|
/*update scheduler instance stats */
|
||
|
sni->length += inc;
|
||
|
sni->len_bytes += len;
|
||
|
}
|
||
|
/* tot_pkts is updated in dn_enqueue function */
|
||
|
}
|
||
|
|
||
|
|
||
|
/* kernel module related function */
|
||
|
int
|
||
|
dn_aqm_modevent(module_t mod, int cmd, void *arg);
|
||
|
|
||
|
#define DECLARE_DNAQM_MODULE(name, dnaqm) \
|
||
|
static moduledata_t name##_mod = { \
|
||
|
#name, dn_aqm_modevent, dnaqm \
|
||
|
}; \
|
||
|
DECLARE_MODULE(name, name##_mod, \
|
||
|
SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); \
|
||
|
MODULE_DEPEND(name, dummynet, 3, 3, 3)
|
||
|
|
||
|
#endif
|