dn_sched.h revision 204591
1/*
2 * Copyright (c) 2010 Riccardo Panicucci, Luigi Rizzo, Universita` di Pisa
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * The API to write a packet scheduling algorithm for dummynet.
29 *
30 * $FreeBSD: head/sys/netinet/ipfw/dn_sched.h 204591 2010-03-02 17:40:48Z luigi $
31 */
32
33#ifndef _DN_SCHED_H
34#define _DN_SCHED_H
35
36#define	DN_MULTIQUEUE	0x01
37/*
38 * Descriptor for a scheduling algorithm.
39 * Contains all function pointers for a given scheduler
40 * This is typically created when a module is loaded, and stored
41 * in a global list of schedulers.
42 */
43struct dn_alg {
44	uint32_t type;           /* the scheduler type */
45	const char *name;   /* scheduler name */
46	uint32_t flags;	/* DN_MULTIQUEUE if supports multiple queues */
47
48	/*
49	 * The following define the size of 3 optional data structures
50	 * that may need to be allocated at runtime, and are appended
51	 * to each of the base data structures: scheduler, sched.inst,
52	 * and queue. We don't have a per-flowset structure.
53	 */
54	/*    + parameters attached to the template, e.g.
55	 *	default queue sizes, weights, quantum size, and so on;
56	 */
57	size_t schk_datalen;
58
59	/*    + per-instance parameters, such as timestamps,
60	 *	containers for queues, etc;
61	 */
62	size_t si_datalen;
63
64	size_t q_datalen;	/* per-queue parameters (e.g. S,F) */
65
66	/*
67	 * Methods implemented by the scheduler:
68	 * enqueue	enqueue packet 'm' on scheduler 's', queue 'q'.
69	 *	q is NULL for !MULTIQUEUE.
70	 *	Return 0 on success, 1 on drop (packet consumed anyways).
71	 *
72	 * dequeue	Called when scheduler instance 's' can
73	 *	dequeue a packet. Return NULL if none are available.
74	 *	XXX what about non work-conserving ?
75	 *
76	 * config	called on 'sched X config ...', normally writes
77	 *	in the area of size sch_arg
78	 *
79	 * destroy	called on 'sched delete', frees everything
80	 *	in sch_arg (other parts are handled by more specific
81	 *	functions)
82	 *
83	 * new_sched    called when a new instance is created, e.g.
84	 *	to create the local queue for !MULTIQUEUE, set V or
85	 *	copy parameters for WFQ, and so on.
86	 *
87	 * free_sched	called when deleting an instance, cleans
88	 *	extra data in the per-instance area.
89	 *
90	 * new_fsk	called when a flowset is linked to a scheduler,
91	 *	e.g. to validate parameters such as weights etc.
92	 * free_fsk	when a flowset is unlinked from a scheduler.
93	 *	(probably unnecessary)
94	 *
95	 * new_queue	called to set the per-queue parameters,
96	 *	e.g. S and F, adjust sum of weights in the parent, etc.
97	 *	If the queue has packets in it, add them to the scheduler
98	 *	as well.
99	 *
100	 * free_queue	actions related to a queue removal, e.g. undo
101	 *	all the above. If the queue has data in it, also remove
102	 *	from the scheduler. This can e.g. happen during a reconfigure.
103	 */
104	int (*enqueue)(struct dn_sch_inst *, struct dn_queue *,
105		struct mbuf *);
106	struct mbuf * (*dequeue)(struct dn_sch_inst *);
107
108	int (*config)(struct dn_schk *);
109	int (*destroy)(struct dn_schk*);
110	int (*new_sched)(struct dn_sch_inst *);
111	int (*free_sched)(struct dn_sch_inst *);
112	int (*new_fsk)(struct dn_fsk *f);
113	int (*free_fsk)(struct dn_fsk *f);
114	int (*new_queue)(struct dn_queue *q);
115	int (*free_queue)(struct dn_queue *q);
116
117	/* run-time fields */
118	int ref_count;      /* XXX number of instances in the system */
119	SLIST_ENTRY(dn_alg) next; /* Next scheduler in the list */
120};
121
122/* MSVC does not support initializers so we need this ugly macro */
123#ifdef _WIN32
124#define _SI(fld)
125#else
126#define _SI(fld)        fld
127#endif
128
129/*
130 * Additionally, dummynet exports some functions and macros
131 * to be used by schedulers:
132 */
133
134void dn_free_pkts(struct mbuf *mnext);
135int dn_enqueue(struct dn_queue *q, struct mbuf* m, int drop);
136/* bound a variable between min and max */
137int ipdn_bound_var(int *v, int dflt, int lo, int hi, const char *msg);
138
139/*
140 * Extract the head of a queue, update stats. Must be the very last
141 * thing done on a dequeue as the queue itself may go away.
142 */
143static __inline struct mbuf*
144dn_dequeue(struct dn_queue *q)
145{
146	struct mbuf *m = q->mq.head;
147	if (m == NULL)
148		return NULL;
149	q->mq.head = m->m_nextpkt;
150	q->ni.length--;
151	q->ni.len_bytes -= m->m_pkthdr.len;
152	if (q->_si) {
153		q->_si->ni.length--;
154		q->_si->ni.len_bytes -= m->m_pkthdr.len;
155	}
156	if (q->ni.length == 0) /* queue is now idle */
157		q->q_time = dn_cfg.curr_time;
158	return m;
159}
160
161int dn_sched_modevent(module_t mod, int cmd, void *arg);
162
163#define DECLARE_DNSCHED_MODULE(name, dnsched)			\
164	static moduledata_t name##_mod = {			\
165		#name, dn_sched_modevent, dnsched		\
166	};							\
167	DECLARE_MODULE(name, name##_mod, 			\
168		SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 	\
169        MODULE_DEPEND(name, dummynet, 3, 3, 3);
170#endif /* _DN_SCHED_H */
171