Sun Jan 4 18:41:36 2009 UTC ()
add braces for symmetry


(pooka)
diff -r1.27 -r1.28 src/sys/altq/altq_subr.c

cvs diff -r1.27 -r1.28 src/sys/altq/altq_subr.c (switch to unified diff)

--- src/sys/altq/altq_subr.c 2008/11/25 23:10:43 1.27
+++ src/sys/altq/altq_subr.c 2009/01/04 18:41:36 1.28
@@ -1,1337 +1,1337 @@ @@ -1,1337 +1,1337 @@
1/* $NetBSD: altq_subr.c,v 1.27 2008/11/25 23:10:43 tsutsui Exp $ */ 1/* $NetBSD: altq_subr.c,v 1.28 2009/01/04 18:41:36 pooka Exp $ */
2/* $KAME: altq_subr.c,v 1.24 2005/04/13 03:44:25 suz Exp $ */ 2/* $KAME: altq_subr.c,v 1.24 2005/04/13 03:44:25 suz Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1997-2003 5 * Copyright (C) 1997-2003
6 * Sony Computer Science Laboratories Inc. All rights reserved. 6 * Sony Computer Science Laboratories Inc. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND 17 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE 20 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE. 27 * SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: altq_subr.c,v 1.27 2008/11/25 23:10:43 tsutsui Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: altq_subr.c,v 1.28 2009/01/04 18:41:36 pooka Exp $");
32 32
33#ifdef _KERNEL_OPT 33#ifdef _KERNEL_OPT
34#include "opt_altq.h" 34#include "opt_altq.h"
35#include "opt_inet.h" 35#include "opt_inet.h"
36#include "pf.h" 36#include "pf.h"
37#endif 37#endif
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/malloc.h> 40#include <sys/malloc.h>
41#include <sys/mbuf.h> 41#include <sys/mbuf.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43#include <sys/proc.h> 43#include <sys/proc.h>
44#include <sys/socket.h> 44#include <sys/socket.h>
45#include <sys/socketvar.h> 45#include <sys/socketvar.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/errno.h> 47#include <sys/errno.h>
48#include <sys/syslog.h> 48#include <sys/syslog.h>
49#include <sys/sysctl.h> 49#include <sys/sysctl.h>
50#include <sys/queue.h> 50#include <sys/queue.h>
51 51
52#include <net/if.h> 52#include <net/if.h>
53#include <net/if_dl.h> 53#include <net/if_dl.h>
54#include <net/if_types.h> 54#include <net/if_types.h>
55 55
56#include <netinet/in.h> 56#include <netinet/in.h>
57#include <netinet/in_systm.h> 57#include <netinet/in_systm.h>
58#include <netinet/ip.h> 58#include <netinet/ip.h>
59#ifdef INET6 59#ifdef INET6
60#include <netinet/ip6.h> 60#include <netinet/ip6.h>
61#endif 61#endif
62#include <netinet/tcp.h> 62#include <netinet/tcp.h>
63#include <netinet/udp.h> 63#include <netinet/udp.h>
64 64
65#if NPF > 0 65#if NPF > 0
66#include <net/pfvar.h> 66#include <net/pfvar.h>
67#endif 67#endif
68#include <altq/altq.h> 68#include <altq/altq.h>
69#ifdef ALTQ3_COMPAT 69#ifdef ALTQ3_COMPAT
70#include <altq/altq_conf.h> 70#include <altq/altq_conf.h>
71#endif 71#endif
72 72
73/* 73/*
74 * internal function prototypes 74 * internal function prototypes
75 */ 75 */
76static void tbr_timeout(void *); 76static void tbr_timeout(void *);
77int (*altq_input)(struct mbuf *, int) = NULL; 77int (*altq_input)(struct mbuf *, int) = NULL;
78static int tbr_timer = 0; /* token bucket regulator timer */ 78static int tbr_timer = 0; /* token bucket regulator timer */
79static struct callout tbr_callout; 79static struct callout tbr_callout;
80 80
81#ifdef ALTQ3_CLFIER_COMPAT 81#ifdef ALTQ3_CLFIER_COMPAT
82static int extract_ports4(struct mbuf *, struct ip *, struct flowinfo_in *); 82static int extract_ports4(struct mbuf *, struct ip *, struct flowinfo_in *);
83#ifdef INET6 83#ifdef INET6
84static int extract_ports6(struct mbuf *, struct ip6_hdr *, 84static int extract_ports6(struct mbuf *, struct ip6_hdr *,
85 struct flowinfo_in6 *); 85 struct flowinfo_in6 *);
86#endif 86#endif
87static int apply_filter4(u_int32_t, struct flow_filter *, 87static int apply_filter4(u_int32_t, struct flow_filter *,
88 struct flowinfo_in *); 88 struct flowinfo_in *);
89static int apply_ppfilter4(u_int32_t, struct flow_filter *, 89static int apply_ppfilter4(u_int32_t, struct flow_filter *,
90 struct flowinfo_in *); 90 struct flowinfo_in *);
91#ifdef INET6 91#ifdef INET6
92static int apply_filter6(u_int32_t, struct flow_filter6 *, 92static int apply_filter6(u_int32_t, struct flow_filter6 *,
93 struct flowinfo_in6 *); 93 struct flowinfo_in6 *);
94#endif 94#endif
95static int apply_tosfilter4(u_int32_t, struct flow_filter *, 95static int apply_tosfilter4(u_int32_t, struct flow_filter *,
96 struct flowinfo_in *); 96 struct flowinfo_in *);
97static u_long get_filt_handle(struct acc_classifier *, int); 97static u_long get_filt_handle(struct acc_classifier *, int);
98static struct acc_filter *filth_to_filtp(struct acc_classifier *, u_long); 98static struct acc_filter *filth_to_filtp(struct acc_classifier *, u_long);
99static u_int32_t filt2fibmask(struct flow_filter *); 99static u_int32_t filt2fibmask(struct flow_filter *);
100 100
101static void ip4f_cache(struct ip *, struct flowinfo_in *); 101static void ip4f_cache(struct ip *, struct flowinfo_in *);
102static int ip4f_lookup(struct ip *, struct flowinfo_in *); 102static int ip4f_lookup(struct ip *, struct flowinfo_in *);
103static int ip4f_init(void); 103static int ip4f_init(void);
104static struct ip4_frag *ip4f_alloc(void); 104static struct ip4_frag *ip4f_alloc(void);
105static void ip4f_free(struct ip4_frag *); 105static void ip4f_free(struct ip4_frag *);
106#endif /* ALTQ3_CLFIER_COMPAT */ 106#endif /* ALTQ3_CLFIER_COMPAT */
107 107
108/* 108/*
109 * alternate queueing support routines 109 * alternate queueing support routines
110 */ 110 */
111 111
112/* look up the queue state by the interface name and the queueing type. */ 112/* look up the queue state by the interface name and the queueing type. */
113void * 113void *
114altq_lookup(char *name, int type) 114altq_lookup(char *name, int type)
115{ 115{
116 struct ifnet *ifp; 116 struct ifnet *ifp;
117 117
118 if ((ifp = ifunit(name)) != NULL) { 118 if ((ifp = ifunit(name)) != NULL) {
119 if (type != ALTQT_NONE && ifp->if_snd.altq_type == type) 119 if (type != ALTQT_NONE && ifp->if_snd.altq_type == type)
120 return (ifp->if_snd.altq_disc); 120 return (ifp->if_snd.altq_disc);
121 } 121 }
122 122
123 return NULL; 123 return NULL;
124} 124}
125 125
126int 126int
127altq_attach(struct ifaltq *ifq, int type, void *discipline, 127altq_attach(struct ifaltq *ifq, int type, void *discipline,
128 int (*enqueue)(struct ifaltq *, struct mbuf *, struct altq_pktattr *), 128 int (*enqueue)(struct ifaltq *, struct mbuf *, struct altq_pktattr *),
129 struct mbuf *(*dequeue)(struct ifaltq *, int), 129 struct mbuf *(*dequeue)(struct ifaltq *, int),
130 int (*request)(struct ifaltq *, int, void *), 130 int (*request)(struct ifaltq *, int, void *),
131 void *clfier, void *(*classify)(void *, struct mbuf *, int)) 131 void *clfier, void *(*classify)(void *, struct mbuf *, int))
132{ 132{
133 if (!ALTQ_IS_READY(ifq)) 133 if (!ALTQ_IS_READY(ifq))
134 return ENXIO; 134 return ENXIO;
135 135
136#ifdef ALTQ3_COMPAT 136#ifdef ALTQ3_COMPAT
137 /* 137 /*
138 * pfaltq can override the existing discipline, but altq3 cannot. 138 * pfaltq can override the existing discipline, but altq3 cannot.
139 * check these if clfier is not NULL (which implies altq3). 139 * check these if clfier is not NULL (which implies altq3).
140 */ 140 */
141 if (clfier != NULL) { 141 if (clfier != NULL) {
142 if (ALTQ_IS_ENABLED(ifq)) 142 if (ALTQ_IS_ENABLED(ifq))
143 return EBUSY; 143 return EBUSY;
144 if (ALTQ_IS_ATTACHED(ifq)) 144 if (ALTQ_IS_ATTACHED(ifq))
145 return EEXIST; 145 return EEXIST;
146 } 146 }
147#endif 147#endif
148 ifq->altq_type = type; 148 ifq->altq_type = type;
149 ifq->altq_disc = discipline; 149 ifq->altq_disc = discipline;
150 ifq->altq_enqueue = enqueue; 150 ifq->altq_enqueue = enqueue;
151 ifq->altq_dequeue = dequeue; 151 ifq->altq_dequeue = dequeue;
152 ifq->altq_request = request; 152 ifq->altq_request = request;
153 ifq->altq_clfier = clfier; 153 ifq->altq_clfier = clfier;
154 ifq->altq_classify = classify; 154 ifq->altq_classify = classify;
155 ifq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED); 155 ifq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED);
156#ifdef ALTQ3_COMPAT 156#ifdef ALTQ3_COMPAT
157#ifdef ALTQ_KLD 157#ifdef ALTQ_KLD
158 altq_module_incref(type); 158 altq_module_incref(type);
159#endif 159#endif
160#endif 160#endif
161 return 0; 161 return 0;
162} 162}
163 163
164int 164int
165altq_detach(struct ifaltq *ifq) 165altq_detach(struct ifaltq *ifq)
166{ 166{
167 if (!ALTQ_IS_READY(ifq)) 167 if (!ALTQ_IS_READY(ifq))
168 return ENXIO; 168 return ENXIO;
169 if (ALTQ_IS_ENABLED(ifq)) 169 if (ALTQ_IS_ENABLED(ifq))
170 return EBUSY; 170 return EBUSY;
171 if (!ALTQ_IS_ATTACHED(ifq)) 171 if (!ALTQ_IS_ATTACHED(ifq))
172 return (0); 172 return (0);
173#ifdef ALTQ3_COMPAT 173#ifdef ALTQ3_COMPAT
174#ifdef ALTQ_KLD 174#ifdef ALTQ_KLD
175 altq_module_declref(ifq->altq_type); 175 altq_module_declref(ifq->altq_type);
176#endif 176#endif
177#endif 177#endif
178 178
179 ifq->altq_type = ALTQT_NONE; 179 ifq->altq_type = ALTQT_NONE;
180 ifq->altq_disc = NULL; 180 ifq->altq_disc = NULL;
181 ifq->altq_enqueue = NULL; 181 ifq->altq_enqueue = NULL;
182 ifq->altq_dequeue = NULL; 182 ifq->altq_dequeue = NULL;
183 ifq->altq_request = NULL; 183 ifq->altq_request = NULL;
184 ifq->altq_clfier = NULL; 184 ifq->altq_clfier = NULL;
185 ifq->altq_classify = NULL; 185 ifq->altq_classify = NULL;
186 ifq->altq_flags &= ALTQF_CANTCHANGE; 186 ifq->altq_flags &= ALTQF_CANTCHANGE;
187 return 0; 187 return 0;
188} 188}
189 189
190int 190int
191altq_enable(struct ifaltq *ifq) 191altq_enable(struct ifaltq *ifq)
192{ 192{
193 int s; 193 int s;
194 194
195 if (!ALTQ_IS_READY(ifq)) 195 if (!ALTQ_IS_READY(ifq))
196 return ENXIO; 196 return ENXIO;
197 if (ALTQ_IS_ENABLED(ifq)) 197 if (ALTQ_IS_ENABLED(ifq))
198 return 0; 198 return 0;
199 199
200 s = splnet(); 200 s = splnet();
201 IFQ_PURGE(ifq); 201 IFQ_PURGE(ifq);
202 ASSERT(ifq->ifq_len == 0); 202 ASSERT(ifq->ifq_len == 0);
203 ifq->altq_flags |= ALTQF_ENABLED; 203 ifq->altq_flags |= ALTQF_ENABLED;
204 if (ifq->altq_clfier != NULL) 204 if (ifq->altq_clfier != NULL)
205 ifq->altq_flags |= ALTQF_CLASSIFY; 205 ifq->altq_flags |= ALTQF_CLASSIFY;
206 splx(s); 206 splx(s);
207 207
208 return 0; 208 return 0;
209} 209}
210 210
211int 211int
212altq_disable(struct ifaltq *ifq) 212altq_disable(struct ifaltq *ifq)
213{ 213{
214 int s; 214 int s;
215 215
216 if (!ALTQ_IS_ENABLED(ifq)) 216 if (!ALTQ_IS_ENABLED(ifq))
217 return 0; 217 return 0;
218 218
219 s = splnet(); 219 s = splnet();
220 IFQ_PURGE(ifq); 220 IFQ_PURGE(ifq);
221 ASSERT(ifq->ifq_len == 0); 221 ASSERT(ifq->ifq_len == 0);
222 ifq->altq_flags &= ~(ALTQF_ENABLED|ALTQF_CLASSIFY); 222 ifq->altq_flags &= ~(ALTQF_ENABLED|ALTQF_CLASSIFY);
223 splx(s); 223 splx(s);
224 return 0; 224 return 0;
225} 225}
226 226
227#ifdef ALTQ_DEBUG 227#ifdef ALTQ_DEBUG
228void 228void
229altq_assert(const char *file, int line, const char *failedexpr) 229altq_assert(const char *file, int line, const char *failedexpr)
230{ 230{
231 (void)printf("altq assertion \"%s\" failed: file \"%s\", line %d\n", 231 (void)printf("altq assertion \"%s\" failed: file \"%s\", line %d\n",
232 failedexpr, file, line); 232 failedexpr, file, line);
233 panic("altq assertion"); 233 panic("altq assertion");
234 /* NOTREACHED */ 234 /* NOTREACHED */
235} 235}
236#endif 236#endif
237 237
238/* 238/*
239 * internal representation of token bucket parameters 239 * internal representation of token bucket parameters
240 * rate: byte_per_unittime << 32 240 * rate: byte_per_unittime << 32
241 * (((bits_per_sec) / 8) << 32) / machclk_freq 241 * (((bits_per_sec) / 8) << 32) / machclk_freq
242 * depth: byte << 32 242 * depth: byte << 32
243 * 243 *
244 */ 244 */
245#define TBR_SHIFT 32 245#define TBR_SHIFT 32
246#define TBR_SCALE(x) ((int64_t)(x) << TBR_SHIFT) 246#define TBR_SCALE(x) ((int64_t)(x) << TBR_SHIFT)
247#define TBR_UNSCALE(x) ((x) >> TBR_SHIFT) 247#define TBR_UNSCALE(x) ((x) >> TBR_SHIFT)
248 248
249struct mbuf * 249struct mbuf *
250tbr_dequeue(struct ifaltq *ifq, int op) 250tbr_dequeue(struct ifaltq *ifq, int op)
251{ 251{
252 struct tb_regulator *tbr; 252 struct tb_regulator *tbr;
253 struct mbuf *m; 253 struct mbuf *m;
254 int64_t interval; 254 int64_t interval;
255 u_int64_t now; 255 u_int64_t now;
256 256
257 tbr = ifq->altq_tbr; 257 tbr = ifq->altq_tbr;
258 if (op == ALTDQ_REMOVE && tbr->tbr_lastop == ALTDQ_POLL) { 258 if (op == ALTDQ_REMOVE && tbr->tbr_lastop == ALTDQ_POLL) {
259 /* if this is a remove after poll, bypass tbr check */ 259 /* if this is a remove after poll, bypass tbr check */
260 } else { 260 } else {
261 /* update token only when it is negative */ 261 /* update token only when it is negative */
262 if (tbr->tbr_token <= 0) { 262 if (tbr->tbr_token <= 0) {
263 now = read_machclk(); 263 now = read_machclk();
264 interval = now - tbr->tbr_last; 264 interval = now - tbr->tbr_last;
265 if (interval >= tbr->tbr_filluptime) 265 if (interval >= tbr->tbr_filluptime)
266 tbr->tbr_token = tbr->tbr_depth; 266 tbr->tbr_token = tbr->tbr_depth;
267 else { 267 else {
268 tbr->tbr_token += interval * tbr->tbr_rate; 268 tbr->tbr_token += interval * tbr->tbr_rate;
269 if (tbr->tbr_token > tbr->tbr_depth) 269 if (tbr->tbr_token > tbr->tbr_depth)
270 tbr->tbr_token = tbr->tbr_depth; 270 tbr->tbr_token = tbr->tbr_depth;
271 } 271 }
272 tbr->tbr_last = now; 272 tbr->tbr_last = now;
273 } 273 }
274 /* if token is still negative, don't allow dequeue */ 274 /* if token is still negative, don't allow dequeue */
275 if (tbr->tbr_token <= 0) 275 if (tbr->tbr_token <= 0)
276 return (NULL); 276 return (NULL);
277 } 277 }
278 278
279 if (ALTQ_IS_ENABLED(ifq)) 279 if (ALTQ_IS_ENABLED(ifq))
280 m = (*ifq->altq_dequeue)(ifq, op); 280 m = (*ifq->altq_dequeue)(ifq, op);
281 else { 281 else {
282 if (op == ALTDQ_POLL) 282 if (op == ALTDQ_POLL)
283 IF_POLL(ifq, m); 283 IF_POLL(ifq, m);
284 else 284 else
285 IF_DEQUEUE(ifq, m); 285 IF_DEQUEUE(ifq, m);
286 } 286 }
287 287
288 if (m != NULL && op == ALTDQ_REMOVE) 288 if (m != NULL && op == ALTDQ_REMOVE)
289 tbr->tbr_token -= TBR_SCALE(m_pktlen(m)); 289 tbr->tbr_token -= TBR_SCALE(m_pktlen(m));
290 tbr->tbr_lastop = op; 290 tbr->tbr_lastop = op;
291 return (m); 291 return (m);
292} 292}
293 293
294/* 294/*
295 * set a token bucket regulator. 295 * set a token bucket regulator.
296 * if the specified rate is zero, the token bucket regulator is deleted. 296 * if the specified rate is zero, the token bucket regulator is deleted.
297 */ 297 */
298int 298int
299tbr_set(struct ifaltq *ifq, struct tb_profile *profile) 299tbr_set(struct ifaltq *ifq, struct tb_profile *profile)
300{ 300{
301 struct tb_regulator *tbr, *otbr; 301 struct tb_regulator *tbr, *otbr;
302 302
303 if (machclk_freq == 0) 303 if (machclk_freq == 0)
304 init_machclk(); 304 init_machclk();
305 if (machclk_freq == 0) { 305 if (machclk_freq == 0) {
306 printf("tbr_set: no CPU clock available!\n"); 306 printf("tbr_set: no CPU clock available!\n");
307 return (ENXIO); 307 return (ENXIO);
308 } 308 }
309 309
310 if (profile->rate == 0) { 310 if (profile->rate == 0) {
311 /* delete this tbr */ 311 /* delete this tbr */
312 if ((tbr = ifq->altq_tbr) == NULL) 312 if ((tbr = ifq->altq_tbr) == NULL)
313 return (ENOENT); 313 return (ENOENT);
314 ifq->altq_tbr = NULL; 314 ifq->altq_tbr = NULL;
315 free(tbr, M_DEVBUF); 315 free(tbr, M_DEVBUF);
316 return (0); 316 return (0);
317 } 317 }
318 318
319 tbr = malloc(sizeof(struct tb_regulator), M_DEVBUF, M_WAITOK|M_ZERO); 319 tbr = malloc(sizeof(struct tb_regulator), M_DEVBUF, M_WAITOK|M_ZERO);
320 if (tbr == NULL) 320 if (tbr == NULL)
321 return (ENOMEM); 321 return (ENOMEM);
322 322
323 tbr->tbr_rate = TBR_SCALE(profile->rate / 8) / machclk_freq; 323 tbr->tbr_rate = TBR_SCALE(profile->rate / 8) / machclk_freq;
324 tbr->tbr_depth = TBR_SCALE(profile->depth); 324 tbr->tbr_depth = TBR_SCALE(profile->depth);
325 if (tbr->tbr_rate > 0) 325 if (tbr->tbr_rate > 0)
326 tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate; 326 tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate;
327 else 327 else
328 tbr->tbr_filluptime = 0xffffffffffffffffLL; 328 tbr->tbr_filluptime = 0xffffffffffffffffLL;
329 tbr->tbr_token = tbr->tbr_depth; 329 tbr->tbr_token = tbr->tbr_depth;
330 tbr->tbr_last = read_machclk(); 330 tbr->tbr_last = read_machclk();
331 tbr->tbr_lastop = ALTDQ_REMOVE; 331 tbr->tbr_lastop = ALTDQ_REMOVE;
332 332
333 otbr = ifq->altq_tbr; 333 otbr = ifq->altq_tbr;
334 ifq->altq_tbr = tbr; /* set the new tbr */ 334 ifq->altq_tbr = tbr; /* set the new tbr */
335 335
336 if (otbr != NULL) 336 if (otbr != NULL) {
337 free(otbr, M_DEVBUF); 337 free(otbr, M_DEVBUF);
338 else { 338 } else {
339 if (tbr_timer == 0) { 339 if (tbr_timer == 0) {
340 CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0); 340 CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0);
341 tbr_timer = 1; 341 tbr_timer = 1;
342 } 342 }
343 } 343 }
344 return (0); 344 return (0);
345} 345}
346 346
347/* 347/*
348 * tbr_timeout goes through the interface list, and kicks the drivers 348 * tbr_timeout goes through the interface list, and kicks the drivers
349 * if necessary. 349 * if necessary.
350 */ 350 */
351static void 351static void
352tbr_timeout(void *arg) 352tbr_timeout(void *arg)
353{ 353{
354 struct ifnet *ifp; 354 struct ifnet *ifp;
355 int active, s; 355 int active, s;
356 356
357 active = 0; 357 active = 0;
358 s = splnet(); 358 s = splnet();
359 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) { 359 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
360 if (!TBR_IS_ENABLED(&ifp->if_snd)) 360 if (!TBR_IS_ENABLED(&ifp->if_snd))
361 continue; 361 continue;
362 active++; 362 active++;
363 if (!IFQ_IS_EMPTY(&ifp->if_snd) && ifp->if_start != NULL) 363 if (!IFQ_IS_EMPTY(&ifp->if_snd) && ifp->if_start != NULL)
364 (*ifp->if_start)(ifp); 364 (*ifp->if_start)(ifp);
365 } 365 }
366 splx(s); 366 splx(s);
367 if (active > 0) 367 if (active > 0)
368 CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0); 368 CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0);
369 else 369 else
370 tbr_timer = 0; /* don't need tbr_timer anymore */ 370 tbr_timer = 0; /* don't need tbr_timer anymore */
371} 371}
372 372
373/* 373/*
374 * get token bucket regulator profile 374 * get token bucket regulator profile
375 */ 375 */
376int 376int
377tbr_get(struct ifaltq *ifq, struct tb_profile *profile) 377tbr_get(struct ifaltq *ifq, struct tb_profile *profile)
378{ 378{
379 struct tb_regulator *tbr; 379 struct tb_regulator *tbr;
380 380
381 if ((tbr = ifq->altq_tbr) == NULL) { 381 if ((tbr = ifq->altq_tbr) == NULL) {
382 profile->rate = 0; 382 profile->rate = 0;
383 profile->depth = 0; 383 profile->depth = 0;
384 } else { 384 } else {
385 profile->rate = 385 profile->rate =
386 (u_int)TBR_UNSCALE(tbr->tbr_rate * 8 * machclk_freq); 386 (u_int)TBR_UNSCALE(tbr->tbr_rate * 8 * machclk_freq);
387 profile->depth = (u_int)TBR_UNSCALE(tbr->tbr_depth); 387 profile->depth = (u_int)TBR_UNSCALE(tbr->tbr_depth);
388 } 388 }
389 return (0); 389 return (0);
390} 390}
391 391
392#if NPF > 0 392#if NPF > 0
393/* 393/*
394 * attach a discipline to the interface. if one already exists, it is 394 * attach a discipline to the interface. if one already exists, it is
395 * overridden. 395 * overridden.
396 */ 396 */
397int 397int
398altq_pfattach(struct pf_altq *a) 398altq_pfattach(struct pf_altq *a)
399{ 399{
400 int error = 0; 400 int error = 0;
401 401
402 switch (a->scheduler) { 402 switch (a->scheduler) {
403 case ALTQT_NONE: 403 case ALTQT_NONE:
404 break; 404 break;
405#ifdef ALTQ_CBQ 405#ifdef ALTQ_CBQ
406 case ALTQT_CBQ: 406 case ALTQT_CBQ:
407 error = cbq_pfattach(a); 407 error = cbq_pfattach(a);
408 break; 408 break;
409#endif 409#endif
410#ifdef ALTQ_PRIQ 410#ifdef ALTQ_PRIQ
411 case ALTQT_PRIQ: 411 case ALTQT_PRIQ:
412 error = priq_pfattach(a); 412 error = priq_pfattach(a);
413 break; 413 break;
414#endif 414#endif
415#ifdef ALTQ_HFSC 415#ifdef ALTQ_HFSC
416 case ALTQT_HFSC: 416 case ALTQT_HFSC:
417 error = hfsc_pfattach(a); 417 error = hfsc_pfattach(a);
418 break; 418 break;
419#endif 419#endif
420 default: 420 default:
421 error = ENXIO; 421 error = ENXIO;
422 } 422 }
423 423
424 return (error); 424 return (error);
425} 425}
426 426
427/* 427/*
428 * detach a discipline from the interface. 428 * detach a discipline from the interface.
429 * it is possible that the discipline was already overridden by another 429 * it is possible that the discipline was already overridden by another
430 * discipline. 430 * discipline.
431 */ 431 */
432int 432int
433altq_pfdetach(struct pf_altq *a) 433altq_pfdetach(struct pf_altq *a)
434{ 434{
435 struct ifnet *ifp; 435 struct ifnet *ifp;
436 int s, error = 0; 436 int s, error = 0;
437 437
438 if ((ifp = ifunit(a->ifname)) == NULL) 438 if ((ifp = ifunit(a->ifname)) == NULL)
439 return (EINVAL); 439 return (EINVAL);
440 440
441 /* if this discipline is no longer referenced, just return */ 441 /* if this discipline is no longer referenced, just return */
442 if (a->altq_disc == NULL || a->altq_disc != ifp->if_snd.altq_disc) 442 if (a->altq_disc == NULL || a->altq_disc != ifp->if_snd.altq_disc)
443 return (0); 443 return (0);
444 444
445 s = splnet(); 445 s = splnet();
446 if (ALTQ_IS_ENABLED(&ifp->if_snd)) 446 if (ALTQ_IS_ENABLED(&ifp->if_snd))
447 error = altq_disable(&ifp->if_snd); 447 error = altq_disable(&ifp->if_snd);
448 if (error == 0) 448 if (error == 0)
449 error = altq_detach(&ifp->if_snd); 449 error = altq_detach(&ifp->if_snd);
450 splx(s); 450 splx(s);
451 451
452 return (error); 452 return (error);
453} 453}
454 454
455/* 455/*
456 * add a discipline or a queue 456 * add a discipline or a queue
457 */ 457 */
458int 458int
459altq_add(struct pf_altq *a) 459altq_add(struct pf_altq *a)
460{ 460{
461 int error = 0; 461 int error = 0;
462 462
463 if (a->qname[0] != 0) 463 if (a->qname[0] != 0)
464 return (altq_add_queue(a)); 464 return (altq_add_queue(a));
465 465
466 if (machclk_freq == 0) 466 if (machclk_freq == 0)
467 init_machclk(); 467 init_machclk();
468 if (machclk_freq == 0) 468 if (machclk_freq == 0)
469 panic("altq_add: no CPU clock"); 469 panic("altq_add: no CPU clock");
470 470
471 switch (a->scheduler) { 471 switch (a->scheduler) {
472#ifdef ALTQ_CBQ 472#ifdef ALTQ_CBQ
473 case ALTQT_CBQ: 473 case ALTQT_CBQ:
474 error = cbq_add_altq(a); 474 error = cbq_add_altq(a);
475 break; 475 break;
476#endif 476#endif
477#ifdef ALTQ_PRIQ 477#ifdef ALTQ_PRIQ
478 case ALTQT_PRIQ: 478 case ALTQT_PRIQ:
479 error = priq_add_altq(a); 479 error = priq_add_altq(a);
480 break; 480 break;
481#endif 481#endif
482#ifdef ALTQ_HFSC 482#ifdef ALTQ_HFSC
483 case ALTQT_HFSC: 483 case ALTQT_HFSC:
484 error = hfsc_add_altq(a); 484 error = hfsc_add_altq(a);
485 break; 485 break;
486#endif 486#endif
487 default: 487 default:
488 error = ENXIO; 488 error = ENXIO;
489 } 489 }
490 490
491 return (error); 491 return (error);
492} 492}
493 493
494/* 494/*
495 * remove a discipline or a queue 495 * remove a discipline or a queue
496 */ 496 */
497int 497int
498altq_remove(struct pf_altq *a) 498altq_remove(struct pf_altq *a)
499{ 499{
500 int error = 0; 500 int error = 0;
501 501
502 if (a->qname[0] != 0) 502 if (a->qname[0] != 0)
503 return (altq_remove_queue(a)); 503 return (altq_remove_queue(a));
504 504
505 switch (a->scheduler) { 505 switch (a->scheduler) {
506#ifdef ALTQ_CBQ 506#ifdef ALTQ_CBQ
507 case ALTQT_CBQ: 507 case ALTQT_CBQ:
508 error = cbq_remove_altq(a); 508 error = cbq_remove_altq(a);
509 break; 509 break;
510#endif 510#endif
511#ifdef ALTQ_PRIQ 511#ifdef ALTQ_PRIQ
512 case ALTQT_PRIQ: 512 case ALTQT_PRIQ:
513 error = priq_remove_altq(a); 513 error = priq_remove_altq(a);
514 break; 514 break;
515#endif 515#endif
516#ifdef ALTQ_HFSC 516#ifdef ALTQ_HFSC
517 case ALTQT_HFSC: 517 case ALTQT_HFSC:
518 error = hfsc_remove_altq(a); 518 error = hfsc_remove_altq(a);
519 break; 519 break;
520#endif 520#endif
521 default: 521 default:
522 error = ENXIO; 522 error = ENXIO;
523 } 523 }
524 524
525 return (error); 525 return (error);
526} 526}
527 527
528/* 528/*
529 * add a queue to the discipline 529 * add a queue to the discipline
530 */ 530 */
531int 531int
532altq_add_queue(struct pf_altq *a) 532altq_add_queue(struct pf_altq *a)
533{ 533{
534 int error = 0; 534 int error = 0;
535 535
536 switch (a->scheduler) { 536 switch (a->scheduler) {
537#ifdef ALTQ_CBQ 537#ifdef ALTQ_CBQ
538 case ALTQT_CBQ: 538 case ALTQT_CBQ:
539 error = cbq_add_queue(a); 539 error = cbq_add_queue(a);
540 break; 540 break;
541#endif 541#endif
542#ifdef ALTQ_PRIQ 542#ifdef ALTQ_PRIQ
543 case ALTQT_PRIQ: 543 case ALTQT_PRIQ:
544 error = priq_add_queue(a); 544 error = priq_add_queue(a);
545 break; 545 break;
546#endif 546#endif
547#ifdef ALTQ_HFSC 547#ifdef ALTQ_HFSC
548 case ALTQT_HFSC: 548 case ALTQT_HFSC:
549 error = hfsc_add_queue(a); 549 error = hfsc_add_queue(a);
550 break; 550 break;
551#endif 551#endif
552 default: 552 default:
553 error = ENXIO; 553 error = ENXIO;
554 } 554 }
555 555
556 return (error); 556 return (error);
557} 557}
558 558
559/* 559/*
560 * remove a queue from the discipline 560 * remove a queue from the discipline
561 */ 561 */
562int 562int
563altq_remove_queue(struct pf_altq *a) 563altq_remove_queue(struct pf_altq *a)
564{ 564{
565 int error = 0; 565 int error = 0;
566 566
567 switch (a->scheduler) { 567 switch (a->scheduler) {
568#ifdef ALTQ_CBQ 568#ifdef ALTQ_CBQ
569 case ALTQT_CBQ: 569 case ALTQT_CBQ:
570 error = cbq_remove_queue(a); 570 error = cbq_remove_queue(a);
571 break; 571 break;
572#endif 572#endif
573#ifdef ALTQ_PRIQ 573#ifdef ALTQ_PRIQ
574 case ALTQT_PRIQ: 574 case ALTQT_PRIQ:
575 error = priq_remove_queue(a); 575 error = priq_remove_queue(a);
576 break; 576 break;
577#endif 577#endif
578#ifdef ALTQ_HFSC 578#ifdef ALTQ_HFSC
579 case ALTQT_HFSC: 579 case ALTQT_HFSC:
580 error = hfsc_remove_queue(a); 580 error = hfsc_remove_queue(a);
581 break; 581 break;
582#endif 582#endif
583 default: 583 default:
584 error = ENXIO; 584 error = ENXIO;
585 } 585 }
586 586
587 return (error); 587 return (error);
588} 588}
589 589
590/* 590/*
591 * get queue statistics 591 * get queue statistics
592 */ 592 */
593int 593int
594altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes) 594altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
595{ 595{
596 int error = 0; 596 int error = 0;
597 597
598 switch (a->scheduler) { 598 switch (a->scheduler) {
599#ifdef ALTQ_CBQ 599#ifdef ALTQ_CBQ
600 case ALTQT_CBQ: 600 case ALTQT_CBQ:
601 error = cbq_getqstats(a, ubuf, nbytes); 601 error = cbq_getqstats(a, ubuf, nbytes);
602 break; 602 break;
603#endif 603#endif
604#ifdef ALTQ_PRIQ 604#ifdef ALTQ_PRIQ
605 case ALTQT_PRIQ: 605 case ALTQT_PRIQ:
606 error = priq_getqstats(a, ubuf, nbytes); 606 error = priq_getqstats(a, ubuf, nbytes);
607 break; 607 break;
608#endif 608#endif
609#ifdef ALTQ_HFSC 609#ifdef ALTQ_HFSC
610 case ALTQT_HFSC: 610 case ALTQT_HFSC:
611 error = hfsc_getqstats(a, ubuf, nbytes); 611 error = hfsc_getqstats(a, ubuf, nbytes);
612 break; 612 break;
613#endif 613#endif
614 default: 614 default:
615 error = ENXIO; 615 error = ENXIO;
616 } 616 }
617 617
618 return (error); 618 return (error);
619} 619}
620#endif /* NPF > 0 */ 620#endif /* NPF > 0 */
621 621
622/* 622/*
623 * read and write diffserv field in IPv4 or IPv6 header 623 * read and write diffserv field in IPv4 or IPv6 header
624 */ 624 */
625u_int8_t 625u_int8_t
626read_dsfield(struct mbuf *m, struct altq_pktattr *pktattr) 626read_dsfield(struct mbuf *m, struct altq_pktattr *pktattr)
627{ 627{
628 struct mbuf *m0; 628 struct mbuf *m0;
629 u_int8_t ds_field = 0; 629 u_int8_t ds_field = 0;
630 630
631 if (pktattr == NULL || 631 if (pktattr == NULL ||
632 (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6)) 632 (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
633 return ((u_int8_t)0); 633 return ((u_int8_t)0);
634 634
635 /* verify that pattr_hdr is within the mbuf data */ 635 /* verify that pattr_hdr is within the mbuf data */
636 for (m0 = m; m0 != NULL; m0 = m0->m_next) 636 for (m0 = m; m0 != NULL; m0 = m0->m_next)
637 if (((char *)pktattr->pattr_hdr >= m0->m_data) && 637 if (((char *)pktattr->pattr_hdr >= m0->m_data) &&
638 ((char *)pktattr->pattr_hdr < m0->m_data + m0->m_len)) 638 ((char *)pktattr->pattr_hdr < m0->m_data + m0->m_len))
639 break; 639 break;
640 if (m0 == NULL) { 640 if (m0 == NULL) {
641 /* ick, pattr_hdr is stale */ 641 /* ick, pattr_hdr is stale */
642 pktattr->pattr_af = AF_UNSPEC; 642 pktattr->pattr_af = AF_UNSPEC;
643#ifdef ALTQ_DEBUG 643#ifdef ALTQ_DEBUG
644 printf("read_dsfield: can't locate header!\n"); 644 printf("read_dsfield: can't locate header!\n");
645#endif 645#endif
646 return ((u_int8_t)0); 646 return ((u_int8_t)0);
647 } 647 }
648 648
649 if (pktattr->pattr_af == AF_INET) { 649 if (pktattr->pattr_af == AF_INET) {
650 struct ip *ip = (struct ip *)pktattr->pattr_hdr; 650 struct ip *ip = (struct ip *)pktattr->pattr_hdr;
651 651
652 if (ip->ip_v != 4) 652 if (ip->ip_v != 4)
653 return ((u_int8_t)0); /* version mismatch! */ 653 return ((u_int8_t)0); /* version mismatch! */
654 ds_field = ip->ip_tos; 654 ds_field = ip->ip_tos;
655 } 655 }
656#ifdef INET6 656#ifdef INET6
657 else if (pktattr->pattr_af == AF_INET6) { 657 else if (pktattr->pattr_af == AF_INET6) {
658 struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr; 658 struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
659 u_int32_t flowlabel; 659 u_int32_t flowlabel;
660 660
661 flowlabel = ntohl(ip6->ip6_flow); 661 flowlabel = ntohl(ip6->ip6_flow);
662 if ((flowlabel >> 28) != 6) 662 if ((flowlabel >> 28) != 6)
663 return ((u_int8_t)0); /* version mismatch! */ 663 return ((u_int8_t)0); /* version mismatch! */
664 ds_field = (flowlabel >> 20) & 0xff; 664 ds_field = (flowlabel >> 20) & 0xff;
665 } 665 }
666#endif 666#endif
667 return (ds_field); 667 return (ds_field);
668} 668}
669 669
670void 670void
671write_dsfield(struct mbuf *m, struct altq_pktattr *pktattr, u_int8_t dsfield) 671write_dsfield(struct mbuf *m, struct altq_pktattr *pktattr, u_int8_t dsfield)
672{ 672{
673 struct mbuf *m0; 673 struct mbuf *m0;
674 674
675 if (pktattr == NULL || 675 if (pktattr == NULL ||
676 (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6)) 676 (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
677 return; 677 return;
678 678
679 /* verify that pattr_hdr is within the mbuf data */ 679 /* verify that pattr_hdr is within the mbuf data */
680 for (m0 = m; m0 != NULL; m0 = m0->m_next) 680 for (m0 = m; m0 != NULL; m0 = m0->m_next)
681 if (((char *)pktattr->pattr_hdr >= m0->m_data) && 681 if (((char *)pktattr->pattr_hdr >= m0->m_data) &&
682 ((char *)pktattr->pattr_hdr < m0->m_data + m0->m_len)) 682 ((char *)pktattr->pattr_hdr < m0->m_data + m0->m_len))
683 break; 683 break;
684 if (m0 == NULL) { 684 if (m0 == NULL) {
685 /* ick, pattr_hdr is stale */ 685 /* ick, pattr_hdr is stale */
686 pktattr->pattr_af = AF_UNSPEC; 686 pktattr->pattr_af = AF_UNSPEC;
687#ifdef ALTQ_DEBUG 687#ifdef ALTQ_DEBUG
688 printf("write_dsfield: can't locate header!\n"); 688 printf("write_dsfield: can't locate header!\n");
689#endif 689#endif
690 return; 690 return;
691 } 691 }
692 692
693 if (pktattr->pattr_af == AF_INET) { 693 if (pktattr->pattr_af == AF_INET) {
694 struct ip *ip = (struct ip *)pktattr->pattr_hdr; 694 struct ip *ip = (struct ip *)pktattr->pattr_hdr;
695 u_int8_t old; 695 u_int8_t old;
696 int32_t sum; 696 int32_t sum;
697 697
698 if (ip->ip_v != 4) 698 if (ip->ip_v != 4)
699 return; /* version mismatch! */ 699 return; /* version mismatch! */
700 old = ip->ip_tos; 700 old = ip->ip_tos;
701 dsfield |= old & 3; /* leave CU bits */ 701 dsfield |= old & 3; /* leave CU bits */
702 if (old == dsfield) 702 if (old == dsfield)
703 return; 703 return;
704 ip->ip_tos = dsfield; 704 ip->ip_tos = dsfield;
705 /* 705 /*
706 * update checksum (from RFC1624) 706 * update checksum (from RFC1624)
707 * HC' = ~(~HC + ~m + m') 707 * HC' = ~(~HC + ~m + m')
708 */ 708 */
709 sum = ~ntohs(ip->ip_sum) & 0xffff; 709 sum = ~ntohs(ip->ip_sum) & 0xffff;
710 sum += 0xff00 + (~old & 0xff) + dsfield; 710 sum += 0xff00 + (~old & 0xff) + dsfield;
711 sum = (sum >> 16) + (sum & 0xffff); 711 sum = (sum >> 16) + (sum & 0xffff);
712 sum += (sum >> 16); /* add carry */ 712 sum += (sum >> 16); /* add carry */
713 713
714 ip->ip_sum = htons(~sum & 0xffff); 714 ip->ip_sum = htons(~sum & 0xffff);
715 } 715 }
716#ifdef INET6 716#ifdef INET6
717 else if (pktattr->pattr_af == AF_INET6) { 717 else if (pktattr->pattr_af == AF_INET6) {
718 struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr; 718 struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
719 u_int32_t flowlabel; 719 u_int32_t flowlabel;
720 720
721 flowlabel = ntohl(ip6->ip6_flow); 721 flowlabel = ntohl(ip6->ip6_flow);
722 if ((flowlabel >> 28) != 6) 722 if ((flowlabel >> 28) != 6)
723 return; /* version mismatch! */ 723 return; /* version mismatch! */
724 flowlabel = (flowlabel & 0xf03fffff) | (dsfield << 20); 724 flowlabel = (flowlabel & 0xf03fffff) | (dsfield << 20);
725 ip6->ip6_flow = htonl(flowlabel); 725 ip6->ip6_flow = htonl(flowlabel);
726 } 726 }
727#endif 727#endif
728 return; 728 return;
729} 729}
730 730
731#define BINTIME_SHIFT 2 731#define BINTIME_SHIFT 2
732 732
733u_int32_t machclk_freq = 0; 733u_int32_t machclk_freq = 0;
734u_int32_t machclk_per_tick = 0; 734u_int32_t machclk_per_tick = 0;
735 735
736void 736void
737init_machclk(void) 737init_machclk(void)
738{ 738{
739 739
740 callout_init(&tbr_callout, 0); 740 callout_init(&tbr_callout, 0);
741 741
742 /* 742 /*
743 * Always emulate 1GiHz counter using bintime(9) 743 * Always emulate 1GiHz counter using bintime(9)
744 * since it has enough resolution via timecounter(9). 744 * since it has enough resolution via timecounter(9).
745 * Using machine dependent cpu_counter() is not MP safe 745 * Using machine dependent cpu_counter() is not MP safe
746 * and it won't work even on UP with Speedstep etc. 746 * and it won't work even on UP with Speedstep etc.
747 */ 747 */
748 machclk_freq = 1024 * 1024 * 1024; /* 2^30 to emulate ~1GHz */ 748 machclk_freq = 1024 * 1024 * 1024; /* 2^30 to emulate ~1GHz */
749 machclk_per_tick = machclk_freq / hz; 749 machclk_per_tick = machclk_freq / hz;
750#ifdef ALTQ_DEBUG 750#ifdef ALTQ_DEBUG
751 printf("altq: emulate %uHz CPU clock\n", machclk_freq); 751 printf("altq: emulate %uHz CPU clock\n", machclk_freq);
752#endif 752#endif
753} 753}
754 754
755u_int64_t 755u_int64_t
756read_machclk(void) 756read_machclk(void)
757{ 757{
758 struct bintime bt; 758 struct bintime bt;
759 u_int64_t val; 759 u_int64_t val;
760 760
761 binuptime(&bt); 761 binuptime(&bt);
762 val = (((u_int64_t)bt.sec << 32) + (bt.frac >> 32)) >> BINTIME_SHIFT; 762 val = (((u_int64_t)bt.sec << 32) + (bt.frac >> 32)) >> BINTIME_SHIFT;
763 return (val); 763 return (val);
764} 764}
765 765
766#ifdef ALTQ3_CLFIER_COMPAT 766#ifdef ALTQ3_CLFIER_COMPAT
767 767
768#ifndef IPPROTO_ESP 768#ifndef IPPROTO_ESP
769#define IPPROTO_ESP 50 /* encapsulating security payload */ 769#define IPPROTO_ESP 50 /* encapsulating security payload */
770#endif 770#endif
771#ifndef IPPROTO_AH 771#ifndef IPPROTO_AH
772#define IPPROTO_AH 51 /* authentication header */ 772#define IPPROTO_AH 51 /* authentication header */
773#endif 773#endif
774 774
775/* 775/*
776 * extract flow information from a given packet. 776 * extract flow information from a given packet.
777 * filt_mask shows flowinfo fields required. 777 * filt_mask shows flowinfo fields required.
778 * we assume the ip header is in one mbuf, and addresses and ports are 778 * we assume the ip header is in one mbuf, and addresses and ports are
779 * in network byte order. 779 * in network byte order.
780 */ 780 */
781int 781int
782altq_extractflow(struct mbuf *m, int af, struct flowinfo *flow, 782altq_extractflow(struct mbuf *m, int af, struct flowinfo *flow,
783 u_int32_t filt_bmask) 783 u_int32_t filt_bmask)
784{ 784{
785 785
786 switch (af) { 786 switch (af) {
787 case PF_INET: { 787 case PF_INET: {
788 struct flowinfo_in *fin; 788 struct flowinfo_in *fin;
789 struct ip *ip; 789 struct ip *ip;
790 790
791 ip = mtod(m, struct ip *); 791 ip = mtod(m, struct ip *);
792 792
793 if (ip->ip_v != 4) 793 if (ip->ip_v != 4)
794 break; 794 break;
795 795
796 fin = (struct flowinfo_in *)flow; 796 fin = (struct flowinfo_in *)flow;
797 fin->fi_len = sizeof(struct flowinfo_in); 797 fin->fi_len = sizeof(struct flowinfo_in);
798 fin->fi_family = AF_INET; 798 fin->fi_family = AF_INET;
799 799
800 fin->fi_proto = ip->ip_p; 800 fin->fi_proto = ip->ip_p;
801 fin->fi_tos = ip->ip_tos; 801 fin->fi_tos = ip->ip_tos;
802 802
803 fin->fi_src.s_addr = ip->ip_src.s_addr; 803 fin->fi_src.s_addr = ip->ip_src.s_addr;
804 fin->fi_dst.s_addr = ip->ip_dst.s_addr; 804 fin->fi_dst.s_addr = ip->ip_dst.s_addr;
805 805
806 if (filt_bmask & FIMB4_PORTS) 806 if (filt_bmask & FIMB4_PORTS)
807 /* if port info is required, extract port numbers */ 807 /* if port info is required, extract port numbers */
808 extract_ports4(m, ip, fin); 808 extract_ports4(m, ip, fin);
809 else { 809 else {
810 fin->fi_sport = 0; 810 fin->fi_sport = 0;
811 fin->fi_dport = 0; 811 fin->fi_dport = 0;
812 fin->fi_gpi = 0; 812 fin->fi_gpi = 0;
813 } 813 }
814 return (1); 814 return (1);
815 } 815 }
816 816
817#ifdef INET6 817#ifdef INET6
818 case PF_INET6: { 818 case PF_INET6: {
819 struct flowinfo_in6 *fin6; 819 struct flowinfo_in6 *fin6;
820 struct ip6_hdr *ip6; 820 struct ip6_hdr *ip6;
821 821
822 ip6 = mtod(m, struct ip6_hdr *); 822 ip6 = mtod(m, struct ip6_hdr *);
823 /* should we check the ip version? */ 823 /* should we check the ip version? */
824 824
825 fin6 = (struct flowinfo_in6 *)flow; 825 fin6 = (struct flowinfo_in6 *)flow;
826 fin6->fi6_len = sizeof(struct flowinfo_in6); 826 fin6->fi6_len = sizeof(struct flowinfo_in6);
827 fin6->fi6_family = AF_INET6; 827 fin6->fi6_family = AF_INET6;
828 828
829 fin6->fi6_proto = ip6->ip6_nxt; 829 fin6->fi6_proto = ip6->ip6_nxt;
830 fin6->fi6_tclass = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 830 fin6->fi6_tclass = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
831 831
832 fin6->fi6_flowlabel = ip6->ip6_flow & htonl(0x000fffff); 832 fin6->fi6_flowlabel = ip6->ip6_flow & htonl(0x000fffff);
833 fin6->fi6_src = ip6->ip6_src; 833 fin6->fi6_src = ip6->ip6_src;
834 fin6->fi6_dst = ip6->ip6_dst; 834 fin6->fi6_dst = ip6->ip6_dst;
835 835
836 if ((filt_bmask & FIMB6_PORTS) || 836 if ((filt_bmask & FIMB6_PORTS) ||
837 ((filt_bmask & FIMB6_PROTO) 837 ((filt_bmask & FIMB6_PROTO)
838 && ip6->ip6_nxt > IPPROTO_IPV6)) 838 && ip6->ip6_nxt > IPPROTO_IPV6))
839 /* 839 /*
840 * if port info is required, or proto is required 840 * if port info is required, or proto is required
841 * but there are option headers, extract port 841 * but there are option headers, extract port
842 * and protocol numbers. 842 * and protocol numbers.
843 */ 843 */
844 extract_ports6(m, ip6, fin6); 844 extract_ports6(m, ip6, fin6);
845 else { 845 else {
846 fin6->fi6_sport = 0; 846 fin6->fi6_sport = 0;
847 fin6->fi6_dport = 0; 847 fin6->fi6_dport = 0;
848 fin6->fi6_gpi = 0; 848 fin6->fi6_gpi = 0;
849 } 849 }
850 return (1); 850 return (1);
851 } 851 }
852#endif /* INET6 */ 852#endif /* INET6 */
853 853
854 default: 854 default:
855 break; 855 break;
856 } 856 }
857 857
858 /* failed */ 858 /* failed */
859 flow->fi_len = sizeof(struct flowinfo); 859 flow->fi_len = sizeof(struct flowinfo);
860 flow->fi_family = AF_UNSPEC; 860 flow->fi_family = AF_UNSPEC;
861 return (0); 861 return (0);
862} 862}
863 863
864/* 864/*
865 * helper routine to extract port numbers 865 * helper routine to extract port numbers
866 */ 866 */
867/* structure for ipsec and ipv6 option header template */ 867/* structure for ipsec and ipv6 option header template */
868struct _opt6 { 868struct _opt6 {
869 u_int8_t opt6_nxt; /* next header */ 869 u_int8_t opt6_nxt; /* next header */
870 u_int8_t opt6_hlen; /* header extension length */ 870 u_int8_t opt6_hlen; /* header extension length */
871 u_int16_t _pad; 871 u_int16_t _pad;
872 u_int32_t ah_spi; /* security parameter index 872 u_int32_t ah_spi; /* security parameter index
873 for authentication header */ 873 for authentication header */
874}; 874};
875 875
876/* 876/*
877 * extract port numbers from a ipv4 packet. 877 * extract port numbers from a ipv4 packet.
878 */ 878 */
879static int 879static int
880extract_ports4(struct mbuf *m, struct ip *ip, struct flowinfo_in *fin) 880extract_ports4(struct mbuf *m, struct ip *ip, struct flowinfo_in *fin)
881{ 881{
882 struct mbuf *m0; 882 struct mbuf *m0;
883 u_short ip_off; 883 u_short ip_off;
884 u_int8_t proto; 884 u_int8_t proto;
885 int off; 885 int off;
886 886
887 fin->fi_sport = 0; 887 fin->fi_sport = 0;
888 fin->fi_dport = 0; 888 fin->fi_dport = 0;
889 fin->fi_gpi = 0; 889 fin->fi_gpi = 0;
890 890
891 ip_off = ntohs(ip->ip_off); 891 ip_off = ntohs(ip->ip_off);
892 /* if it is a fragment, try cached fragment info */ 892 /* if it is a fragment, try cached fragment info */
893 if (ip_off & IP_OFFMASK) { 893 if (ip_off & IP_OFFMASK) {
894 ip4f_lookup(ip, fin); 894 ip4f_lookup(ip, fin);
895 return (1); 895 return (1);
896 } 896 }
897 897
898 /* locate the mbuf containing the protocol header */ 898 /* locate the mbuf containing the protocol header */
899 for (m0 = m; m0 != NULL; m0 = m0->m_next) 899 for (m0 = m; m0 != NULL; m0 = m0->m_next)
900 if (((char *)ip >= m0->m_data) && 900 if (((char *)ip >= m0->m_data) &&
901 ((char *)ip < m0->m_data + m0->m_len)) 901 ((char *)ip < m0->m_data + m0->m_len))
902 break; 902 break;
903 if (m0 == NULL) { 903 if (m0 == NULL) {
904#ifdef ALTQ_DEBUG 904#ifdef ALTQ_DEBUG
905 printf("extract_ports4: can't locate header! ip=%p\n", ip); 905 printf("extract_ports4: can't locate header! ip=%p\n", ip);
906#endif 906#endif
907 return (0); 907 return (0);
908 } 908 }
909 off = ((char *)ip - m0->m_data) + (ip->ip_hl << 2); 909 off = ((char *)ip - m0->m_data) + (ip->ip_hl << 2);
910 proto = ip->ip_p; 910 proto = ip->ip_p;
911 911
912#ifdef ALTQ_IPSEC 912#ifdef ALTQ_IPSEC
913 again: 913 again:
914#endif 914#endif
915 while (off >= m0->m_len) { 915 while (off >= m0->m_len) {
916 off -= m0->m_len; 916 off -= m0->m_len;
917 m0 = m0->m_next; 917 m0 = m0->m_next;
918 if (m0 == NULL) 918 if (m0 == NULL)
919 return (0); /* bogus ip_hl! */ 919 return (0); /* bogus ip_hl! */
920 } 920 }
921 if (m0->m_len < off + 4) 921 if (m0->m_len < off + 4)
922 return (0); 922 return (0);
923 923
924 switch (proto) { 924 switch (proto) {
925 case IPPROTO_TCP: 925 case IPPROTO_TCP:
926 case IPPROTO_UDP: { 926 case IPPROTO_UDP: {
927 struct udphdr *udp; 927 struct udphdr *udp;
928 928
929 udp = (struct udphdr *)(mtod(m0, char *) + off); 929 udp = (struct udphdr *)(mtod(m0, char *) + off);
930 fin->fi_sport = udp->uh_sport; 930 fin->fi_sport = udp->uh_sport;
931 fin->fi_dport = udp->uh_dport; 931 fin->fi_dport = udp->uh_dport;
932 fin->fi_proto = proto; 932 fin->fi_proto = proto;
933 } 933 }
934 break; 934 break;
935 935
936#ifdef ALTQ_IPSEC 936#ifdef ALTQ_IPSEC
937 case IPPROTO_ESP: 937 case IPPROTO_ESP:
938 if (fin->fi_gpi == 0){ 938 if (fin->fi_gpi == 0){
939 u_int32_t *gpi; 939 u_int32_t *gpi;
940 940
941 gpi = (u_int32_t *)(mtod(m0, char *) + off); 941 gpi = (u_int32_t *)(mtod(m0, char *) + off);
942 fin->fi_gpi = *gpi; 942 fin->fi_gpi = *gpi;
943 } 943 }
944 fin->fi_proto = proto; 944 fin->fi_proto = proto;
945 break; 945 break;
946 946
947 case IPPROTO_AH: { 947 case IPPROTO_AH: {
948 /* get next header and header length */ 948 /* get next header and header length */
949 struct _opt6 *opt6; 949 struct _opt6 *opt6;
950 950
951 opt6 = (struct _opt6 *)(mtod(m0, char *) + off); 951 opt6 = (struct _opt6 *)(mtod(m0, char *) + off);
952 proto = opt6->opt6_nxt; 952 proto = opt6->opt6_nxt;
953 off += 8 + (opt6->opt6_hlen * 4); 953 off += 8 + (opt6->opt6_hlen * 4);
954 if (fin->fi_gpi == 0 && m0->m_len >= off + 8) 954 if (fin->fi_gpi == 0 && m0->m_len >= off + 8)
955 fin->fi_gpi = opt6->ah_spi; 955 fin->fi_gpi = opt6->ah_spi;
956 } 956 }
957 /* goto the next header */ 957 /* goto the next header */
958 goto again; 958 goto again;
959#endif /* ALTQ_IPSEC */ 959#endif /* ALTQ_IPSEC */
960 960
961 default: 961 default:
962 fin->fi_proto = proto; 962 fin->fi_proto = proto;
963 return (0); 963 return (0);
964 } 964 }
965 965
966 /* if this is a first fragment, cache it. */ 966 /* if this is a first fragment, cache it. */
967 if (ip_off & IP_MF) 967 if (ip_off & IP_MF)
968 ip4f_cache(ip, fin); 968 ip4f_cache(ip, fin);
969 969
970 return (1); 970 return (1);
971} 971}
972 972
973#ifdef INET6 973#ifdef INET6
974static int 974static int
975extract_ports6(struct mbuf *m, struct ip6_hdr *ip6, struct flowinfo_in6 *fin6) 975extract_ports6(struct mbuf *m, struct ip6_hdr *ip6, struct flowinfo_in6 *fin6)
976{ 976{
977 struct mbuf *m0; 977 struct mbuf *m0;
978 int off; 978 int off;
979 u_int8_t proto; 979 u_int8_t proto;
980 980
981 fin6->fi6_gpi = 0; 981 fin6->fi6_gpi = 0;
982 fin6->fi6_sport = 0; 982 fin6->fi6_sport = 0;
983 fin6->fi6_dport = 0; 983 fin6->fi6_dport = 0;
984 984
985 /* locate the mbuf containing the protocol header */ 985 /* locate the mbuf containing the protocol header */
986 for (m0 = m; m0 != NULL; m0 = m0->m_next) 986 for (m0 = m; m0 != NULL; m0 = m0->m_next)
987 if (((char *)ip6 >= m0->m_data) && 987 if (((char *)ip6 >= m0->m_data) &&
988 ((char *)ip6 < m0->m_data + m0->m_len)) 988 ((char *)ip6 < m0->m_data + m0->m_len))
989 break; 989 break;
990 if (m0 == NULL) { 990 if (m0 == NULL) {
991#ifdef ALTQ_DEBUG 991#ifdef ALTQ_DEBUG
992 printf("extract_ports6: can't locate header! ip6=%p\n", ip6); 992 printf("extract_ports6: can't locate header! ip6=%p\n", ip6);
993#endif 993#endif
994 return (0); 994 return (0);
995 } 995 }
996 off = ((char *)ip6 - m0->m_data) + sizeof(struct ip6_hdr); 996 off = ((char *)ip6 - m0->m_data) + sizeof(struct ip6_hdr);
997 997
998 proto = ip6->ip6_nxt; 998 proto = ip6->ip6_nxt;
999 do { 999 do {
1000 while (off >= m0->m_len) { 1000 while (off >= m0->m_len) {
1001 off -= m0->m_len; 1001 off -= m0->m_len;
1002 m0 = m0->m_next; 1002 m0 = m0->m_next;
1003 if (m0 == NULL) 1003 if (m0 == NULL)
1004 return (0); 1004 return (0);
1005 } 1005 }
1006 if (m0->m_len < off + 4) 1006 if (m0->m_len < off + 4)
1007 return (0); 1007 return (0);
1008 1008
1009 switch (proto) { 1009 switch (proto) {
1010 case IPPROTO_TCP: 1010 case IPPROTO_TCP:
1011 case IPPROTO_UDP: { 1011 case IPPROTO_UDP: {
1012 struct udphdr *udp; 1012 struct udphdr *udp;
1013 1013
1014 udp = (struct udphdr *)(mtod(m0, char *) + off); 1014 udp = (struct udphdr *)(mtod(m0, char *) + off);
1015 fin6->fi6_sport = udp->uh_sport; 1015 fin6->fi6_sport = udp->uh_sport;
1016 fin6->fi6_dport = udp->uh_dport; 1016 fin6->fi6_dport = udp->uh_dport;
1017 fin6->fi6_proto = proto; 1017 fin6->fi6_proto = proto;
1018 } 1018 }
1019 return (1); 1019 return (1);
1020 1020
1021 case IPPROTO_ESP: 1021 case IPPROTO_ESP:
1022 if (fin6->fi6_gpi == 0) { 1022 if (fin6->fi6_gpi == 0) {
1023 u_int32_t *gpi; 1023 u_int32_t *gpi;
1024 1024
1025 gpi = (u_int32_t *)(mtod(m0, char *) + off); 1025 gpi = (u_int32_t *)(mtod(m0, char *) + off);
1026 fin6->fi6_gpi = *gpi; 1026 fin6->fi6_gpi = *gpi;
1027 } 1027 }
1028 fin6->fi6_proto = proto; 1028 fin6->fi6_proto = proto;
1029 return (1); 1029 return (1);
1030 1030
1031 case IPPROTO_AH: { 1031 case IPPROTO_AH: {
1032 /* get next header and header length */ 1032 /* get next header and header length */
1033 struct _opt6 *opt6; 1033 struct _opt6 *opt6;
1034 1034
1035 opt6 = (struct _opt6 *)(mtod(m0, char *) + off); 1035 opt6 = (struct _opt6 *)(mtod(m0, char *) + off);
1036 if (fin6->fi6_gpi == 0 && m0->m_len >= off + 8) 1036 if (fin6->fi6_gpi == 0 && m0->m_len >= off + 8)
1037 fin6->fi6_gpi = opt6->ah_spi; 1037 fin6->fi6_gpi = opt6->ah_spi;
1038 proto = opt6->opt6_nxt; 1038 proto = opt6->opt6_nxt;
1039 off += 8 + (opt6->opt6_hlen * 4); 1039 off += 8 + (opt6->opt6_hlen * 4);
1040 /* goto the next header */ 1040 /* goto the next header */
1041 break; 1041 break;
1042 } 1042 }
1043 1043
1044 case IPPROTO_HOPOPTS: 1044 case IPPROTO_HOPOPTS:
1045 case IPPROTO_ROUTING: 1045 case IPPROTO_ROUTING:
1046 case IPPROTO_DSTOPTS: { 1046 case IPPROTO_DSTOPTS: {
1047 /* get next header and header length */ 1047 /* get next header and header length */
1048 struct _opt6 *opt6; 1048 struct _opt6 *opt6;
1049 1049
1050 opt6 = (struct _opt6 *)(mtod(m0, char *) + off); 1050 opt6 = (struct _opt6 *)(mtod(m0, char *) + off);
1051 proto = opt6->opt6_nxt; 1051 proto = opt6->opt6_nxt;
1052 off += (opt6->opt6_hlen + 1) * 8; 1052 off += (opt6->opt6_hlen + 1) * 8;
1053 /* goto the next header */ 1053 /* goto the next header */
1054 break; 1054 break;
1055 } 1055 }
1056 1056
1057 case IPPROTO_FRAGMENT: 1057 case IPPROTO_FRAGMENT:
1058 /* ipv6 fragmentations are not supported yet */ 1058 /* ipv6 fragmentations are not supported yet */
1059 default: 1059 default:
1060 fin6->fi6_proto = proto; 1060 fin6->fi6_proto = proto;
1061 return (0); 1061 return (0);
1062 } 1062 }
1063 } while (1); 1063 } while (1);
1064 /*NOTREACHED*/ 1064 /*NOTREACHED*/
1065} 1065}
1066#endif /* INET6 */ 1066#endif /* INET6 */
1067 1067
1068/* 1068/*
1069 * altq common classifier 1069 * altq common classifier
1070 */ 1070 */
1071int 1071int
1072acc_add_filter(struct acc_classifier *classifier, struct flow_filter *filter, 1072acc_add_filter(struct acc_classifier *classifier, struct flow_filter *filter,
1073 void *class, u_long *phandle) 1073 void *class, u_long *phandle)
1074{ 1074{
1075 struct acc_filter *afp, *prev, *tmp; 1075 struct acc_filter *afp, *prev, *tmp;
1076 int i, s; 1076 int i, s;
1077 1077
1078#ifdef INET6 1078#ifdef INET6
1079 if (filter->ff_flow.fi_family != AF_INET && 1079 if (filter->ff_flow.fi_family != AF_INET &&
1080 filter->ff_flow.fi_family != AF_INET6) 1080 filter->ff_flow.fi_family != AF_INET6)
1081 return (EINVAL); 1081 return (EINVAL);
1082#else 1082#else
1083 if (filter->ff_flow.fi_family != AF_INET) 1083 if (filter->ff_flow.fi_family != AF_INET)
1084 return (EINVAL); 1084 return (EINVAL);
1085#endif 1085#endif
1086 1086
1087 afp = malloc(sizeof(struct acc_filter), M_DEVBUF, M_WAITOK|M_ZERO); 1087 afp = malloc(sizeof(struct acc_filter), M_DEVBUF, M_WAITOK|M_ZERO);
1088 if (afp == NULL) 1088 if (afp == NULL)
1089 return (ENOMEM); 1089 return (ENOMEM);
1090 1090
1091 afp->f_filter = *filter; 1091 afp->f_filter = *filter;
1092 afp->f_class = class; 1092 afp->f_class = class;
1093 1093
1094 i = ACC_WILDCARD_INDEX; 1094 i = ACC_WILDCARD_INDEX;
1095 if (filter->ff_flow.fi_family == AF_INET) { 1095 if (filter->ff_flow.fi_family == AF_INET) {
1096 struct flow_filter *filter4 = &afp->f_filter; 1096 struct flow_filter *filter4 = &afp->f_filter;
1097 1097
1098 /* 1098 /*
1099 * if address is 0, it's a wildcard. if address mask 1099 * if address is 0, it's a wildcard. if address mask
1100 * isn't set, use full mask. 1100 * isn't set, use full mask.
1101 */ 1101 */
1102 if (filter4->ff_flow.fi_dst.s_addr == 0) 1102 if (filter4->ff_flow.fi_dst.s_addr == 0)
1103 filter4->ff_mask.mask_dst.s_addr = 0; 1103 filter4->ff_mask.mask_dst.s_addr = 0;
1104 else if (filter4->ff_mask.mask_dst.s_addr == 0) 1104 else if (filter4->ff_mask.mask_dst.s_addr == 0)
1105 filter4->ff_mask.mask_dst.s_addr = 0xffffffff; 1105 filter4->ff_mask.mask_dst.s_addr = 0xffffffff;
1106 if (filter4->ff_flow.fi_src.s_addr == 0) 1106 if (filter4->ff_flow.fi_src.s_addr == 0)
1107 filter4->ff_mask.mask_src.s_addr = 0; 1107 filter4->ff_mask.mask_src.s_addr = 0;
1108 else if (filter4->ff_mask.mask_src.s_addr == 0) 1108 else if (filter4->ff_mask.mask_src.s_addr == 0)
1109 filter4->ff_mask.mask_src.s_addr = 0xffffffff; 1109 filter4->ff_mask.mask_src.s_addr = 0xffffffff;
1110 1110
1111 /* clear extra bits in addresses */ 1111 /* clear extra bits in addresses */
1112 filter4->ff_flow.fi_dst.s_addr &= 1112 filter4->ff_flow.fi_dst.s_addr &=
1113 filter4->ff_mask.mask_dst.s_addr; 1113 filter4->ff_mask.mask_dst.s_addr;
1114 filter4->ff_flow.fi_src.s_addr &= 1114 filter4->ff_flow.fi_src.s_addr &=
1115 filter4->ff_mask.mask_src.s_addr; 1115 filter4->ff_mask.mask_src.s_addr;
1116 1116
1117 /* 1117 /*
1118 * if dst address is a wildcard, use hash-entry 1118 * if dst address is a wildcard, use hash-entry
1119 * ACC_WILDCARD_INDEX. 1119 * ACC_WILDCARD_INDEX.
1120 */ 1120 */
1121 if (filter4->ff_mask.mask_dst.s_addr != 0xffffffff) 1121 if (filter4->ff_mask.mask_dst.s_addr != 0xffffffff)
1122 i = ACC_WILDCARD_INDEX; 1122 i = ACC_WILDCARD_INDEX;
1123 else 1123 else
1124 i = ACC_GET_HASH_INDEX(filter4->ff_flow.fi_dst.s_addr); 1124 i = ACC_GET_HASH_INDEX(filter4->ff_flow.fi_dst.s_addr);
1125 } 1125 }
1126#ifdef INET6 1126#ifdef INET6
1127 else if (filter->ff_flow.fi_family == AF_INET6) { 1127 else if (filter->ff_flow.fi_family == AF_INET6) {
1128 struct flow_filter6 *filter6 = 1128 struct flow_filter6 *filter6 =
1129 (struct flow_filter6 *)&afp->f_filter; 1129 (struct flow_filter6 *)&afp->f_filter;
1130#ifndef IN6MASK0 /* taken from kame ipv6 */ 1130#ifndef IN6MASK0 /* taken from kame ipv6 */
1131#define IN6MASK0 {{{ 0, 0, 0, 0 }}} 1131#define IN6MASK0 {{{ 0, 0, 0, 0 }}}
1132#define IN6MASK128 {{{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }}} 1132#define IN6MASK128 {{{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }}}
1133 const struct in6_addr in6mask0 = IN6MASK0; 1133 const struct in6_addr in6mask0 = IN6MASK0;
1134 const struct in6_addr in6mask128 = IN6MASK128; 1134 const struct in6_addr in6mask128 = IN6MASK128;
1135#endif 1135#endif
1136 1136
1137 if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_dst)) 1137 if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_dst))
1138 filter6->ff_mask6.mask6_dst = in6mask0; 1138 filter6->ff_mask6.mask6_dst = in6mask0;
1139 else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_dst)) 1139 else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_dst))
1140 filter6->ff_mask6.mask6_dst = in6mask128; 1140 filter6->ff_mask6.mask6_dst = in6mask128;
1141 if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_src)) 1141 if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_src))
1142 filter6->ff_mask6.mask6_src = in6mask0; 1142 filter6->ff_mask6.mask6_src = in6mask0;
1143 else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_src)) 1143 else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_src))
1144 filter6->ff_mask6.mask6_src = in6mask128; 1144 filter6->ff_mask6.mask6_src = in6mask128;
1145 1145
1146 /* clear extra bits in addresses */ 1146 /* clear extra bits in addresses */
1147 for (i = 0; i < 16; i++) 1147 for (i = 0; i < 16; i++)
1148 filter6->ff_flow6.fi6_dst.s6_addr[i] &= 1148 filter6->ff_flow6.fi6_dst.s6_addr[i] &=
1149 filter6->ff_mask6.mask6_dst.s6_addr[i]; 1149 filter6->ff_mask6.mask6_dst.s6_addr[i];
1150 for (i = 0; i < 16; i++) 1150 for (i = 0; i < 16; i++)
1151 filter6->ff_flow6.fi6_src.s6_addr[i] &= 1151 filter6->ff_flow6.fi6_src.s6_addr[i] &=
1152 filter6->ff_mask6.mask6_src.s6_addr[i]; 1152 filter6->ff_mask6.mask6_src.s6_addr[i];
1153 1153
1154 if (filter6->ff_flow6.fi6_flowlabel == 0) 1154 if (filter6->ff_flow6.fi6_flowlabel == 0)
1155 i = ACC_WILDCARD_INDEX; 1155 i = ACC_WILDCARD_INDEX;
1156 else 1156 else
1157 i = ACC_GET_HASH_INDEX(filter6->ff_flow6.fi6_flowlabel); 1157 i = ACC_GET_HASH_INDEX(filter6->ff_flow6.fi6_flowlabel);
1158 } 1158 }
1159#endif /* INET6 */ 1159#endif /* INET6 */
1160 1160
1161 afp->f_handle = get_filt_handle(classifier, i); 1161 afp->f_handle = get_filt_handle(classifier, i);
1162 1162
1163 /* update filter bitmask */ 1163 /* update filter bitmask */
1164 afp->f_fbmask = filt2fibmask(filter); 1164 afp->f_fbmask = filt2fibmask(filter);
1165 classifier->acc_fbmask |= afp->f_fbmask; 1165 classifier->acc_fbmask |= afp->f_fbmask;
1166 1166
1167 /* 1167 /*
1168 * add this filter to the filter list. 1168 * add this filter to the filter list.
1169 * filters are ordered from the highest rule number. 1169 * filters are ordered from the highest rule number.
1170 */ 1170 */
1171 s = splnet(); 1171 s = splnet();
1172 prev = NULL; 1172 prev = NULL;
1173 LIST_FOREACH(tmp, &classifier->acc_filters[i], f_chain) { 1173 LIST_FOREACH(tmp, &classifier->acc_filters[i], f_chain) {
1174 if (tmp->f_filter.ff_ruleno > afp->f_filter.ff_ruleno) 1174 if (tmp->f_filter.ff_ruleno > afp->f_filter.ff_ruleno)
1175 prev = tmp; 1175 prev = tmp;
1176 else 1176 else
1177 break; 1177 break;
1178 } 1178 }
1179 if (prev == NULL) 1179 if (prev == NULL)
1180 LIST_INSERT_HEAD(&classifier->acc_filters[i], afp, f_chain); 1180 LIST_INSERT_HEAD(&classifier->acc_filters[i], afp, f_chain);
1181 else 1181 else
1182 LIST_INSERT_AFTER(prev, afp, f_chain); 1182 LIST_INSERT_AFTER(prev, afp, f_chain);
1183 splx(s); 1183 splx(s);
1184 1184
1185 *phandle = afp->f_handle; 1185 *phandle = afp->f_handle;
1186 return (0); 1186 return (0);
1187} 1187}
1188 1188
1189int 1189int
1190acc_delete_filter(struct acc_classifier *classifier, u_long handle) 1190acc_delete_filter(struct acc_classifier *classifier, u_long handle)
1191{ 1191{
1192 struct acc_filter *afp; 1192 struct acc_filter *afp;
1193 int s; 1193 int s;
1194 1194
1195 if ((afp = filth_to_filtp(classifier, handle)) == NULL) 1195 if ((afp = filth_to_filtp(classifier, handle)) == NULL)
1196 return (EINVAL); 1196 return (EINVAL);
1197 1197
1198 s = splnet(); 1198 s = splnet();
1199 LIST_REMOVE(afp, f_chain); 1199 LIST_REMOVE(afp, f_chain);
1200 splx(s); 1200 splx(s);
1201 1201
1202 free(afp, M_DEVBUF); 1202 free(afp, M_DEVBUF);
1203 1203
1204 /* todo: update filt_bmask */ 1204 /* todo: update filt_bmask */
1205 1205
1206 return (0); 1206 return (0);
1207} 1207}
1208 1208
1209/* 1209/*
1210 * delete filters referencing to the specified class. 1210 * delete filters referencing to the specified class.
1211 * if the all flag is not 0, delete all the filters. 1211 * if the all flag is not 0, delete all the filters.
1212 */ 1212 */
1213int 1213int
1214acc_discard_filters(struct acc_classifier *classifier, void *class, int all) 1214acc_discard_filters(struct acc_classifier *classifier, void *class, int all)
1215{ 1215{
1216 struct acc_filter *afp; 1216 struct acc_filter *afp;
1217 int i, s; 1217 int i, s;
1218 1218
1219 s = splnet(); 1219 s = splnet();
1220 for (i = 0; i < ACC_FILTER_TABLESIZE; i++) { 1220 for (i = 0; i < ACC_FILTER_TABLESIZE; i++) {
1221 do { 1221 do {
1222 LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain) 1222 LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
1223 if (all || afp->f_class == class) { 1223 if (all || afp->f_class == class) {
1224 LIST_REMOVE(afp, f_chain); 1224 LIST_REMOVE(afp, f_chain);
1225 free(afp, M_DEVBUF); 1225 free(afp, M_DEVBUF);
1226 /* start again from the head */ 1226 /* start again from the head */
1227 break; 1227 break;
1228 } 1228 }
1229 } while (afp != NULL); 1229 } while (afp != NULL);
1230 } 1230 }
1231 splx(s); 1231 splx(s);
1232 1232
1233 if (all) 1233 if (all)
1234 classifier->acc_fbmask = 0; 1234 classifier->acc_fbmask = 0;
1235 1235
1236 return (0); 1236 return (0);
1237} 1237}
1238 1238
1239void * 1239void *
1240acc_classify(void *clfier, struct mbuf *m, int af) 1240acc_classify(void *clfier, struct mbuf *m, int af)
1241{ 1241{
1242 struct acc_classifier *classifier; 1242 struct acc_classifier *classifier;
1243 struct flowinfo flow; 1243 struct flowinfo flow;
1244 struct acc_filter *afp; 1244 struct acc_filter *afp;
1245 int i; 1245 int i;
1246 1246
1247 classifier = (struct acc_classifier *)clfier; 1247 classifier = (struct acc_classifier *)clfier;
1248 altq_extractflow(m, af, &flow, classifier->acc_fbmask); 1248 altq_extractflow(m, af, &flow, classifier->acc_fbmask);
1249 1249
1250 if (flow.fi_family == AF_INET) { 1250 if (flow.fi_family == AF_INET) {
1251 struct flowinfo_in *fp = (struct flowinfo_in *)&flow; 1251 struct flowinfo_in *fp = (struct flowinfo_in *)&flow;
1252 1252
1253 if ((classifier->acc_fbmask & FIMB4_ALL) == FIMB4_TOS) { 1253 if ((classifier->acc_fbmask & FIMB4_ALL) == FIMB4_TOS) {
1254 /* only tos is used */ 1254 /* only tos is used */
1255 LIST_FOREACH(afp, 1255 LIST_FOREACH(afp,
1256 &classifier->acc_filters[ACC_WILDCARD_INDEX], 1256 &classifier->acc_filters[ACC_WILDCARD_INDEX],
1257 f_chain) 1257 f_chain)
1258 if (apply_tosfilter4(afp->f_fbmask, 1258 if (apply_tosfilter4(afp->f_fbmask,
1259 &afp->f_filter, fp)) 1259 &afp->f_filter, fp))
1260 /* filter matched */ 1260 /* filter matched */
1261 return (afp->f_class); 1261 return (afp->f_class);
1262 } else if ((classifier->acc_fbmask & 1262 } else if ((classifier->acc_fbmask &
1263 (~(FIMB4_PROTO|FIMB4_SPORT|FIMB4_DPORT) & FIMB4_ALL)) 1263 (~(FIMB4_PROTO|FIMB4_SPORT|FIMB4_DPORT) & FIMB4_ALL))
1264 == 0) { 1264 == 0) {
1265 /* only proto and ports are used */ 1265 /* only proto and ports are used */
1266 LIST_FOREACH(afp, 1266 LIST_FOREACH(afp,
1267 &classifier->acc_filters[ACC_WILDCARD_INDEX], 1267 &classifier->acc_filters[ACC_WILDCARD_INDEX],
1268 f_chain) 1268 f_chain)
1269 if (apply_ppfilter4(afp->f_fbmask, 1269 if (apply_ppfilter4(afp->f_fbmask,
1270 &afp->f_filter, fp)) 1270 &afp->f_filter, fp))
1271 /* filter matched */ 1271 /* filter matched */
1272 return (afp->f_class); 1272 return (afp->f_class);
1273 } else { 1273 } else {
1274 /* get the filter hash entry from its dest address */ 1274 /* get the filter hash entry from its dest address */
1275 i = ACC_GET_HASH_INDEX(fp->fi_dst.s_addr); 1275 i = ACC_GET_HASH_INDEX(fp->fi_dst.s_addr);
1276 do { 1276 do {
1277 /* 1277 /*
1278 * go through this loop twice. first for dst 1278 * go through this loop twice. first for dst
1279 * hash, second for wildcards. 1279 * hash, second for wildcards.
1280 */ 1280 */
1281 LIST_FOREACH(afp, &classifier->acc_filters[i], 1281 LIST_FOREACH(afp, &classifier->acc_filters[i],
1282 f_chain) 1282 f_chain)
1283 if (apply_filter4(afp->f_fbmask, 1283 if (apply_filter4(afp->f_fbmask,
1284 &afp->f_filter, fp)) 1284 &afp->f_filter, fp))
1285 /* filter matched */ 1285 /* filter matched */
1286 return (afp->f_class); 1286 return (afp->f_class);
1287 1287
1288 /* 1288 /*
1289 * check again for filters with a dst addr 1289 * check again for filters with a dst addr
1290 * wildcard. 1290 * wildcard.
1291 * (daddr == 0 || dmask != 0xffffffff). 1291 * (daddr == 0 || dmask != 0xffffffff).
1292 */ 1292 */
1293 if (i != ACC_WILDCARD_INDEX) 1293 if (i != ACC_WILDCARD_INDEX)
1294 i = ACC_WILDCARD_INDEX; 1294 i = ACC_WILDCARD_INDEX;
1295 else 1295 else
1296 break; 1296 break;
1297 } while (1); 1297 } while (1);
1298 } 1298 }
1299 } 1299 }
1300#ifdef INET6 1300#ifdef INET6
1301 else if (flow.fi_family == AF_INET6) { 1301 else if (flow.fi_family == AF_INET6) {
1302 struct flowinfo_in6 *fp6 = (struct flowinfo_in6 *)&flow; 1302 struct flowinfo_in6 *fp6 = (struct flowinfo_in6 *)&flow;
1303 1303
1304 /* get the filter hash entry from its flow ID */ 1304 /* get the filter hash entry from its flow ID */
1305 if (fp6->fi6_flowlabel != 0) 1305 if (fp6->fi6_flowlabel != 0)
1306 i = ACC_GET_HASH_INDEX(fp6->fi6_flowlabel); 1306 i = ACC_GET_HASH_INDEX(fp6->fi6_flowlabel);
1307 else 1307 else
1308 /* flowlable can be zero */ 1308 /* flowlable can be zero */
1309 i = ACC_WILDCARD_INDEX; 1309 i = ACC_WILDCARD_INDEX;
1310 1310
1311 /* go through this loop twice. first for flow hash, second 1311 /* go through this loop twice. first for flow hash, second
1312 for wildcards. */ 1312 for wildcards. */
1313 do { 1313 do {
1314 LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain) 1314 LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
1315 if (apply_filter6(afp->f_fbmask, 1315 if (apply_filter6(afp->f_fbmask,
1316 (struct flow_filter6 *)&afp->f_filter, 1316 (struct flow_filter6 *)&afp->f_filter,
1317 fp6)) 1317 fp6))
1318 /* filter matched */ 1318 /* filter matched */
1319 return (afp->f_class); 1319 return (afp->f_class);
1320 1320
1321 /* 1321 /*
1322 * check again for filters with a wildcard. 1322 * check again for filters with a wildcard.
1323 */ 1323 */
1324 if (i != ACC_WILDCARD_INDEX) 1324 if (i != ACC_WILDCARD_INDEX)
1325 i = ACC_WILDCARD_INDEX; 1325 i = ACC_WILDCARD_INDEX;
1326 else 1326 else
1327 break; 1327 break;
1328 } while (1); 1328 } while (1);
1329 } 1329 }
1330#endif /* INET6 */ 1330#endif /* INET6 */
1331 1331
1332 /* no filter matched */ 1332 /* no filter matched */
1333 return (NULL); 1333 return (NULL);
1334} 1334}
1335 1335
1336static int 1336static int
1337apply_filter4(u_int32_t fbmask, struct flow_filter *filt, 1337apply_filter4(u_int32_t fbmask, struct flow_filter *filt,