1 /*        $NetBSD: altq_hfsc.h,v 1.8 2006/10/12 19:59:08 peter Exp $  */
2 /*        $KAME: altq_hfsc.h,v 1.12 2003/12/05 05:40:46 kjc Exp $     */
3 
4 /*
5  * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and
8  * its documentation is hereby granted (including for commercial or
9  * for-profit use), provided that both the copyright notice and this
10  * permission notice appear in all copies of the software, derivative
11  * works, or modified versions, and any portions thereof.
12  *
13  * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF
14  * WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON PROVIDES THIS
15  * SOFTWARE IN ITS ``AS IS'' CONDITION, AND ANY EXPRESS OR IMPLIED
16  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26  * DAMAGE.
27  *
28  * Carnegie Mellon encourages (but does not require) users of this
29  * software to return any improvements or extensions that they make,
30  * and to grant Carnegie Mellon the rights to redistribute these
31  * changes without encumbrance.
32  */
33 #ifndef _ALTQ_ALTQ_HFSC_H_
34 #define   _ALTQ_ALTQ_HFSC_H_
35 
36 #include <altq/altq.h>
37 #include <altq/altq_classq.h>
38 #include <altq/altq_red.h>
39 #include <altq/altq_rio.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 struct service_curve {
46           u_int     m1;       /* slope of the first segment in bits/sec */
47           u_int     d;        /* the x-projection of the first segment in msec */
48           u_int     m2;       /* slope of the second segment in bits/sec */
49 };
50 
51 /* special class handles */
52 #define   HFSC_NULLCLASS_HANDLE         0
53 #define   HFSC_MAX_CLASSES    64
54 
55 /* hfsc class flags */
56 #define   HFCF_RED            0x0001    /* use RED */
57 #define   HFCF_ECN            0x0002  /* use RED/ECN */
58 #define   HFCF_RIO            0x0004  /* use RIO */
59 #define   HFCF_CLEARDSCP                0x0010  /* clear diffserv codepoint */
60 #define   HFCF_DEFAULTCLASS   0x1000    /* default class */
61 
62 /* service curve types */
63 #define   HFSC_REALTIMESC               1
64 #define   HFSC_LINKSHARINGSC  2
65 #define   HFSC_UPPERLIMITSC   4
66 #define   HFSC_DEFAULTSC                (HFSC_REALTIMESC|HFSC_LINKSHARINGSC)
67 
68 struct hfsc_classstats {
69           u_int                         class_id;
70           u_int32_t           class_handle;
71           struct service_curve          rsc;
72           struct service_curve          fsc;
73           struct service_curve          usc;      /* upper limit service curve */
74 
75           u_int64_t           total;    /* total work in bytes */
76           u_int64_t           cumul;    /* cumulative work in bytes
77                                                      done by real-time criteria */
78           u_int64_t           d;                  /* deadline */
79           u_int64_t           e;                  /* eligible time */
80           u_int64_t           vt;                 /* virtual time */
81           u_int64_t           f;                  /* fit time for upper-limit */
82 
83           /* info helpful for debugging */
84           u_int64_t           initvt;             /* init virtual time */
85           u_int64_t           vtoff;              /* cl_vt_ipoff */
86           u_int64_t           cvtmax;             /* cl_maxvt */
87           u_int64_t           myf;                /* cl_myf */
88           u_int64_t           cfmin;              /* cl_mincf */
89           u_int64_t           cvtmin;             /* cl_mincvt */
90           u_int64_t           myfadj;             /* cl_myfadj */
91           u_int64_t           vtadj;              /* cl_vtadj */
92           u_int64_t           cur_time;
93           u_int32_t           machclk_freq;
94 
95           u_int                         qlength;
96           u_int                         qlimit;
97           struct pktcntr                xmit_cnt;
98           struct pktcntr                drop_cnt;
99           u_int                         period;
100 
101           u_int                         vtperiod; /* vt period sequence no */
102           u_int                         parentperiod;       /* parent's vt period seqno */
103           int                           nactive;  /* number of active children */
104 
105           /* red and rio related info */
106           int                           qtype;
107           struct redstats               red[3];
108 };
109 
110 #ifdef ALTQ3_COMPAT
111 struct hfsc_interface {
112           char      hfsc_ifname[IFNAMSIZ];  /* interface name (e.g., fxp0) */
113 };
114 
115 struct hfsc_attach {
116           struct hfsc_interface         iface;
117           u_int                         bandwidth;  /* link bandwidth in bits/sec */
118 };
119 
120 struct hfsc_add_class {
121           struct hfsc_interface         iface;
122           u_int32_t           parent_handle;
123           struct service_curve          service_curve;
124           int                           qlimit;
125           int                           flags;
126 
127           u_int32_t           class_handle;  /* return value */
128 };
129 
130 struct hfsc_delete_class {
131           struct hfsc_interface         iface;
132           u_int32_t           class_handle;
133 };
134 
135 struct hfsc_modify_class {
136           struct hfsc_interface         iface;
137           u_int32_t           class_handle;
138           struct service_curve          service_curve;
139           int                           sctype;
140 };
141 
142 struct hfsc_add_filter {
143           struct hfsc_interface         iface;
144           u_int32_t           class_handle;
145           struct flow_filter  filter;
146 
147           u_long                        filter_handle;  /* return value */
148 };
149 
150 struct hfsc_delete_filter {
151           struct hfsc_interface         iface;
152           u_long                        filter_handle;
153 };
154 
155 struct hfsc_class_stats {
156           struct hfsc_interface         iface;
157           int                           nskip;              /* skip # of classes */
158           int                           nclasses; /* # of class stats (WR) */
159           u_int64_t           cur_time; /* current time */
160           u_int32_t           machclk_freq;       /* machine clock frequency */
161           u_int                         hif_classes;        /* # of classes in the tree */
162           u_int                         hif_packets;        /* # of packets in the tree */
163           struct hfsc_classstats        *stats;             /* pointer to stats array */
164 };
165 
166 #define   HFSC_IF_ATTACH                _IOW('Q', 1, struct hfsc_attach)
167 #define   HFSC_IF_DETACH                _IOW('Q', 2, struct hfsc_interface)
168 #define   HFSC_ENABLE                   _IOW('Q', 3, struct hfsc_interface)
169 #define   HFSC_DISABLE                  _IOW('Q', 4, struct hfsc_interface)
170 #define   HFSC_CLEAR_HIERARCHY          _IOW('Q', 5, struct hfsc_interface)
171 #define   HFSC_ADD_CLASS                _IOWR('Q', 7, struct hfsc_add_class)
172 #define   HFSC_DEL_CLASS                _IOW('Q', 8, struct hfsc_delete_class)
173 #define   HFSC_MOD_CLASS                _IOW('Q', 9, struct hfsc_modify_class)
174 #define   HFSC_ADD_FILTER               _IOWR('Q', 10, struct hfsc_add_filter)
175 #define   HFSC_DEL_FILTER               _IOW('Q', 11, struct hfsc_delete_filter)
176 #define   HFSC_GETSTATS                 _IOWR('Q', 12, struct hfsc_class_stats)
177 #endif /* ALTQ3_COMPAT */
178 
179 #ifdef _KERNEL
180 /*
181  * kernel internal service curve representation
182  *        coordinates are given by 64 bit unsigned integers.
183  *        x-axis: unit is clock count.  for the intel x86 architecture,
184  *                  the raw Pentium TSC (Timestamp Counter) value is used.
185  *                  virtual time is also calculated in this time scale.
186  *        y-axis: unit is byte.
187  *
188  *        the service curve parameters are converted to the internal
189  *        representation.
190  *        the slope values are scaled to avoid overflow.
191  *        the inverse slope values as well as the y-projection of the 1st
192  *        segment are kept in order to to avoid 64-bit divide operations
193  *        that are expensive on 32-bit architectures.
194  *
195  *  note: Intel Pentium TSC never wraps around in several thousands of years.
196  *        x-axis doesn't wrap around for 1089 years with 1GHz clock.
197  *      y-axis doesn't wrap around for 4358 years with 1Gbps bandwidth.
198  */
199 
200 /* kernel internal representation of a service curve */
201 struct internal_sc {
202           u_int64_t sm1;      /* scaled slope of the 1st segment */
203           u_int64_t ism1;     /* scaled inverse-slope of the 1st segment */
204           u_int64_t dx;       /* the x-projection of the 1st segment */
205           u_int64_t dy;       /* the y-projection of the 1st segment */
206           u_int64_t sm2;      /* scaled slope of the 2nd segment */
207           u_int64_t ism2;     /* scaled inverse-slope of the 2nd segment */
208 };
209 
210 /* runtime service curve */
211 struct runtime_sc {
212           u_int64_t x;        /* current starting position on x-axis */
213           u_int64_t y;        /* current starting position on x-axis */
214           u_int64_t sm1;      /* scaled slope of the 1st segment */
215           u_int64_t ism1;     /* scaled inverse-slope of the 1st segment */
216           u_int64_t dx;       /* the x-projection of the 1st segment */
217           u_int64_t dy;       /* the y-projection of the 1st segment */
218           u_int64_t sm2;      /* scaled slope of the 2nd segment */
219           u_int64_t ism2;     /* scaled inverse-slope of the 2nd segment */
220 };
221 
222 /* for TAILQ based ellist and actlist implementation */
223 struct hfsc_class;
224 typedef TAILQ_HEAD(_eligible, hfsc_class) ellist_t;
225 typedef TAILQ_ENTRY(hfsc_class) elentry_t;
226 typedef TAILQ_HEAD(_active, hfsc_class) actlist_t;
227 typedef TAILQ_ENTRY(hfsc_class) actentry_t;
228 #define   ellist_first(s)               TAILQ_FIRST(s)
229 #define   actlist_first(s)    TAILQ_FIRST(s)
230 #define   actlist_last(s)               TAILQ_LAST(s, _active)
231 
232 struct hfsc_class {
233           u_int               cl_id;              /* class id (just for debug) */
234           u_int32_t cl_handle;          /* class handle */
235           struct hfsc_if      *cl_hif;  /* back pointer to struct hfsc_if */
236           int                 cl_flags; /* misc flags */
237 
238           struct hfsc_class *cl_parent; /* parent class */
239           struct hfsc_class *cl_siblings;         /* sibling classes */
240           struct hfsc_class *cl_children;         /* child classes */
241 
242           class_queue_t       *cl_q;              /* class queue structure */
243           struct red          *cl_red;  /* RED state */
244           struct altq_pktattr *cl_pktattr; /* saved header used by ECN */
245 
246           u_int64_t cl_total; /* total work in bytes */
247           u_int64_t cl_cumul; /* cumulative work in bytes
248                                                      done by real-time criteria */
249           u_int64_t cl_d;               /* deadline */
250           u_int64_t cl_e;               /* eligible time */
251           u_int64_t cl_vt;              /* virtual time */
252           u_int64_t cl_f;               /* time when this class will fit for
253                                                      link-sharing, max(myf, cfmin) */
254           u_int64_t cl_myf;             /* my fit-time (as calculated from this
255                                                      class's own upperlimit curve) */
256           u_int64_t cl_myfadj;          /* my fit-time adjustment
257                                                      (to cancel history dependence) */
258           u_int64_t cl_cfmin; /* earliest children's fit-time (used
259                                                      with cl_myf to obtain cl_f) */
260           u_int64_t cl_cvtmin;          /* minimal virtual time among the
261                                                      children fit for link-sharing
262                                                      (monotonic within a period) */
263           u_int64_t cl_vtadj; /* intra-period cumulative vt
264                                                      adjustment */
265           u_int64_t cl_vtoff; /* inter-period cumulative vt offset */
266           u_int64_t cl_cvtmax;          /* max child's vt in the last period */
267 
268           u_int64_t cl_initvt;          /* init virtual time (for debugging) */
269 
270           struct internal_sc *cl_rsc;   /* internal real-time service curve */
271           struct internal_sc *cl_fsc;   /* internal fair service curve */
272           struct internal_sc *cl_usc;   /* internal upperlimit service curve */
273           struct runtime_sc  cl_deadline;         /* deadline curve */
274           struct runtime_sc  cl_eligible;         /* eligible curve */
275           struct runtime_sc  cl_virtual;          /* virtual curve */
276           struct runtime_sc  cl_ulimit; /* upperlimit curve */
277 
278           u_int               cl_vtperiod;        /* vt period sequence no */
279           u_int               cl_parentperiod;  /* parent's vt period seqno */
280           int                 cl_nactive;         /* number of active children */
281           actlist_t *cl_actc; /* active children list */
282 
283           actentry_t          cl_actlist;         /* active children list entry */
284           elentry_t cl_ellist;          /* eligible list entry */
285 
286           struct {
287                     struct pktcntr      xmit_cnt;
288                     struct pktcntr      drop_cnt;
289                     u_int period;
290           } cl_stats;
291 };
292 
293 /*
294  * hfsc interface state
295  */
296 struct hfsc_if {
297           struct hfsc_if                *hif_next;          /* interface state list */
298           struct ifaltq                 *hif_ifq; /* backpointer to ifaltq */
299           struct hfsc_class   *hif_rootclass;               /* root class */
300           struct hfsc_class   *hif_defaultclass;  /* default class */
301           struct hfsc_class   *hif_class_tbl[HFSC_MAX_CLASSES];
302           struct hfsc_class   *hif_pollcache;     /* cache for poll operation */
303 
304           u_int     hif_classes;                            /* # of classes in the tree */
305           u_int     hif_packets;                            /* # of packets in the tree */
306           u_int     hif_classid;                            /* class id sequence number */
307 
308           ellist_t *hif_eligible;                           /* eligible list */
309 
310 #ifdef ALTQ3_CLFIER_COMPAT
311           struct acc_classifier         hif_classifier;
312 #endif
313 };
314 
315 #endif /* _KERNEL */
316 
317 #ifdef __cplusplus
318 }
319 #endif
320 
321 #endif /* _ALTQ_ALTQ_HFSC_H_ */
322