xref: /trueos/sys/contrib/altq/altq/altq_subr.c (revision f937dcf2bd0584087acec5d8dc92dd5dba177113)
1 /*	$FreeBSD$	*/
2 /*	$KAME: altq_subr.c,v 1.21 2003/11/06 06:32:53 kjc Exp $	*/
3 
4 /*
5  * Copyright (C) 1997-2003
6  *	Sony Computer Science Laboratories Inc.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #if defined(__FreeBSD__) || defined(__NetBSD__)
31 #include "opt_altq.h"
32 #include "opt_inet.h"
33 #ifdef __FreeBSD__
34 #include "opt_inet6.h"
35 #endif
36 #endif /* __FreeBSD__ || __NetBSD__ */
37 
38 #include <sys/param.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/kernel.h>
46 #include <sys/errno.h>
47 #include <sys/syslog.h>
48 #include <sys/sysctl.h>
49 #include <sys/queue.h>
50 
51 #include <net/if.h>
52 #include <net/if_var.h>
53 #include <net/if_dl.h>
54 #include <net/if_types.h>
55 #ifdef __FreeBSD__
56 #include <net/vnet.h>
57 #endif
58 
59 #include <netinet/in.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
62 #ifdef INET6
63 #include <netinet/ip6.h>
64 #endif
65 #include <netinet/tcp.h>
66 #include <netinet/udp.h>
67 
68 #include <netpfil/pf/pf.h>
69 #include <netpfil/pf/pf_altq.h>
70 #include <altq/altq.h>
71 #ifdef ALTQ3_COMPAT
72 #include <altq/altq_conf.h>
73 #endif
74 
75 /* machine dependent clock related includes */
76 #ifdef __FreeBSD__
77 #include <sys/bus.h>
78 #include <sys/cpu.h>
79 #include <sys/eventhandler.h>
80 #include <machine/clock.h>
81 #endif
82 #if defined(__amd64__) || defined(__i386__)
83 #include <machine/cpufunc.h>		/* for pentium tsc */
84 #include <machine/specialreg.h>		/* for CPUID_TSC */
85 #ifdef __FreeBSD__
86 #include <machine/md_var.h>		/* for cpu_feature */
87 #elif defined(__NetBSD__) || defined(__OpenBSD__)
88 #include <machine/cpu.h>		/* for cpu_feature */
89 #endif
90 #endif /* __amd64 || __i386__ */
91 
92 /*
93  * internal function prototypes
94  */
95 static void	tbr_timeout(void *);
96 int (*altq_input)(struct mbuf *, int) = NULL;
97 static struct mbuf *tbr_dequeue(struct ifaltq *, int);
98 static int tbr_timer = 0;	/* token bucket regulator timer */
99 #if !defined(__FreeBSD__) || (__FreeBSD_version < 600000)
100 static struct callout tbr_callout = CALLOUT_INITIALIZER;
101 #else
102 static struct callout tbr_callout;
103 #endif
104 
105 #ifdef ALTQ3_CLFIER_COMPAT
106 static int 	extract_ports4(struct mbuf *, struct ip *, struct flowinfo_in *);
107 #ifdef INET6
108 static int 	extract_ports6(struct mbuf *, struct ip6_hdr *,
109 			       struct flowinfo_in6 *);
110 #endif
111 static int	apply_filter4(u_int32_t, struct flow_filter *,
112 			      struct flowinfo_in *);
113 static int	apply_ppfilter4(u_int32_t, struct flow_filter *,
114 				struct flowinfo_in *);
115 #ifdef INET6
116 static int	apply_filter6(u_int32_t, struct flow_filter6 *,
117 			      struct flowinfo_in6 *);
118 #endif
119 static int	apply_tosfilter4(u_int32_t, struct flow_filter *,
120 				 struct flowinfo_in *);
121 static u_long	get_filt_handle(struct acc_classifier *, int);
122 static struct acc_filter *filth_to_filtp(struct acc_classifier *, u_long);
123 static u_int32_t filt2fibmask(struct flow_filter *);
124 
125 static void 	ip4f_cache(struct ip *, struct flowinfo_in *);
126 static int 	ip4f_lookup(struct ip *, struct flowinfo_in *);
127 static int 	ip4f_init(void);
128 static struct ip4_frag	*ip4f_alloc(void);
129 static void 	ip4f_free(struct ip4_frag *);
130 #endif /* ALTQ3_CLFIER_COMPAT */
131 
132 /*
133  * alternate queueing support routines
134  */
135 
136 /* look up the queue state by the interface name and the queueing type. */
137 void *
altq_lookup(name,type)138 altq_lookup(name, type)
139 	char *name;
140 	int type;
141 {
142 	struct ifnet *ifp;
143 
144 	if ((ifp = ifunit(name)) != NULL) {
145 		/* read if_snd unlocked */
146 		if (type != ALTQT_NONE && ifp->if_snd.altq_type == type)
147 			return (ifp->if_snd.altq_disc);
148 	}
149 
150 	return NULL;
151 }
152 
153 int
altq_attach(ifq,type,discipline,enqueue,dequeue,request,clfier,classify)154 altq_attach(ifq, type, discipline, enqueue, dequeue, request, clfier, classify)
155 	struct ifaltq *ifq;
156 	int type;
157 	void *discipline;
158 	int (*enqueue)(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
159 	struct mbuf *(*dequeue)(struct ifaltq *, int);
160 	int (*request)(struct ifaltq *, int, void *);
161 	void *clfier;
162 	void *(*classify)(void *, struct mbuf *, int);
163 {
164 	IFQ_LOCK(ifq);
165 	if (!ALTQ_IS_READY(ifq)) {
166 		IFQ_UNLOCK(ifq);
167 		return ENXIO;
168 	}
169 
170 #ifdef ALTQ3_COMPAT
171 	/*
172 	 * pfaltq can override the existing discipline, but altq3 cannot.
173 	 * check these if clfier is not NULL (which implies altq3).
174 	 */
175 	if (clfier != NULL) {
176 		if (ALTQ_IS_ENABLED(ifq)) {
177 			IFQ_UNLOCK(ifq);
178 			return EBUSY;
179 		}
180 		if (ALTQ_IS_ATTACHED(ifq)) {
181 			IFQ_UNLOCK(ifq);
182 			return EEXIST;
183 		}
184 	}
185 #endif
186 	ifq->altq_type     = type;
187 	ifq->altq_disc     = discipline;
188 	ifq->altq_enqueue  = enqueue;
189 	ifq->altq_dequeue  = dequeue;
190 	ifq->altq_request  = request;
191 	ifq->altq_clfier   = clfier;
192 	ifq->altq_classify = classify;
193 	ifq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED);
194 #ifdef ALTQ3_COMPAT
195 #ifdef ALTQ_KLD
196 	altq_module_incref(type);
197 #endif
198 #endif
199 	IFQ_UNLOCK(ifq);
200 	return 0;
201 }
202 
203 int
altq_detach(ifq)204 altq_detach(ifq)
205 	struct ifaltq *ifq;
206 {
207 	IFQ_LOCK(ifq);
208 
209 	if (!ALTQ_IS_READY(ifq)) {
210 		IFQ_UNLOCK(ifq);
211 		return ENXIO;
212 	}
213 	if (ALTQ_IS_ENABLED(ifq)) {
214 		IFQ_UNLOCK(ifq);
215 		return EBUSY;
216 	}
217 	if (!ALTQ_IS_ATTACHED(ifq)) {
218 		IFQ_UNLOCK(ifq);
219 		return (0);
220 	}
221 #ifdef ALTQ3_COMPAT
222 #ifdef ALTQ_KLD
223 	altq_module_declref(ifq->altq_type);
224 #endif
225 #endif
226 
227 	ifq->altq_type     = ALTQT_NONE;
228 	ifq->altq_disc     = NULL;
229 	ifq->altq_enqueue  = NULL;
230 	ifq->altq_dequeue  = NULL;
231 	ifq->altq_request  = NULL;
232 	ifq->altq_clfier   = NULL;
233 	ifq->altq_classify = NULL;
234 	ifq->altq_flags &= ALTQF_CANTCHANGE;
235 
236 	IFQ_UNLOCK(ifq);
237 	return 0;
238 }
239 
240 int
altq_enable(ifq)241 altq_enable(ifq)
242 	struct ifaltq *ifq;
243 {
244 	int s;
245 
246 	IFQ_LOCK(ifq);
247 
248 	if (!ALTQ_IS_READY(ifq)) {
249 		IFQ_UNLOCK(ifq);
250 		return ENXIO;
251 	}
252 	if (ALTQ_IS_ENABLED(ifq)) {
253 		IFQ_UNLOCK(ifq);
254 		return 0;
255 	}
256 
257 #ifdef __NetBSD__
258 	s = splnet();
259 #else
260 	s = splimp();
261 #endif
262 	IFQ_PURGE_NOLOCK(ifq);
263 	ASSERT(ifq->ifq_len == 0);
264 	ifq->ifq_drv_maxlen = 0;		/* disable bulk dequeue */
265 	ifq->altq_flags |= ALTQF_ENABLED;
266 	if (ifq->altq_clfier != NULL)
267 		ifq->altq_flags |= ALTQF_CLASSIFY;
268 	splx(s);
269 
270 	IFQ_UNLOCK(ifq);
271 	return 0;
272 }
273 
274 int
altq_disable(ifq)275 altq_disable(ifq)
276 	struct ifaltq *ifq;
277 {
278 	int s;
279 
280 	IFQ_LOCK(ifq);
281 	if (!ALTQ_IS_ENABLED(ifq)) {
282 		IFQ_UNLOCK(ifq);
283 		return 0;
284 	}
285 
286 #ifdef __NetBSD__
287 	s = splnet();
288 #else
289 	s = splimp();
290 #endif
291 	IFQ_PURGE_NOLOCK(ifq);
292 	ASSERT(ifq->ifq_len == 0);
293 	ifq->altq_flags &= ~(ALTQF_ENABLED|ALTQF_CLASSIFY);
294 	splx(s);
295 
296 	IFQ_UNLOCK(ifq);
297 	return 0;
298 }
299 
300 #ifdef ALTQ_DEBUG
301 void
altq_assert(file,line,failedexpr)302 altq_assert(file, line, failedexpr)
303 	const char *file, *failedexpr;
304 	int line;
305 {
306 	(void)printf("altq assertion \"%s\" failed: file \"%s\", line %d\n",
307 		     failedexpr, file, line);
308 	panic("altq assertion");
309 	/* NOTREACHED */
310 }
311 #endif
312 
313 /*
314  * internal representation of token bucket parameters
315  *	rate:	byte_per_unittime << 32
316  *		(((bits_per_sec) / 8) << 32) / machclk_freq
317  *	depth:	byte << 32
318  *
319  */
320 #define	TBR_SHIFT	32
321 #define	TBR_SCALE(x)	((int64_t)(x) << TBR_SHIFT)
322 #define	TBR_UNSCALE(x)	((x) >> TBR_SHIFT)
323 
324 static struct mbuf *
tbr_dequeue(ifq,op)325 tbr_dequeue(ifq, op)
326 	struct ifaltq *ifq;
327 	int op;
328 {
329 	struct tb_regulator *tbr;
330 	struct mbuf *m;
331 	int64_t interval;
332 	u_int64_t now;
333 
334 	IFQ_LOCK_ASSERT(ifq);
335 	tbr = ifq->altq_tbr;
336 	if (op == ALTDQ_REMOVE && tbr->tbr_lastop == ALTDQ_POLL) {
337 		/* if this is a remove after poll, bypass tbr check */
338 	} else {
339 		/* update token only when it is negative */
340 		if (tbr->tbr_token <= 0) {
341 			now = read_machclk();
342 			interval = now - tbr->tbr_last;
343 			if (interval >= tbr->tbr_filluptime)
344 				tbr->tbr_token = tbr->tbr_depth;
345 			else {
346 				tbr->tbr_token += interval * tbr->tbr_rate;
347 				if (tbr->tbr_token > tbr->tbr_depth)
348 					tbr->tbr_token = tbr->tbr_depth;
349 			}
350 			tbr->tbr_last = now;
351 		}
352 		/* if token is still negative, don't allow dequeue */
353 		if (tbr->tbr_token <= 0)
354 			return (NULL);
355 	}
356 
357 	if (ALTQ_IS_ENABLED(ifq))
358 		m = (*ifq->altq_dequeue)(ifq, op);
359 	else {
360 		if (op == ALTDQ_POLL)
361 			_IF_POLL(ifq, m);
362 		else
363 			_IF_DEQUEUE(ifq, m);
364 	}
365 
366 	if (m != NULL && op == ALTDQ_REMOVE)
367 		tbr->tbr_token -= TBR_SCALE(m_pktlen(m));
368 	tbr->tbr_lastop = op;
369 	return (m);
370 }
371 
372 /*
373  * set a token bucket regulator.
374  * if the specified rate is zero, the token bucket regulator is deleted.
375  */
376 int
tbr_set(ifq,profile)377 tbr_set(ifq, profile)
378 	struct ifaltq *ifq;
379 	struct tb_profile *profile;
380 {
381 	struct tb_regulator *tbr, *otbr;
382 
383 	if (tbr_dequeue_ptr == NULL)
384 		tbr_dequeue_ptr = tbr_dequeue;
385 
386 	if (machclk_freq == 0)
387 		init_machclk();
388 	if (machclk_freq == 0) {
389 		printf("tbr_set: no cpu clock available!\n");
390 		return (ENXIO);
391 	}
392 
393 	IFQ_LOCK(ifq);
394 	if (profile->rate == 0) {
395 		/* delete this tbr */
396 		if ((tbr = ifq->altq_tbr) == NULL) {
397 			IFQ_UNLOCK(ifq);
398 			return (ENOENT);
399 		}
400 		ifq->altq_tbr = NULL;
401 		free(tbr, M_DEVBUF);
402 		IFQ_UNLOCK(ifq);
403 		return (0);
404 	}
405 
406 	tbr = malloc(sizeof(struct tb_regulator), M_DEVBUF, M_NOWAIT | M_ZERO);
407 	if (tbr == NULL) {
408 		IFQ_UNLOCK(ifq);
409 		return (ENOMEM);
410 	}
411 
412 	tbr->tbr_rate = TBR_SCALE(profile->rate / 8) / machclk_freq;
413 	tbr->tbr_depth = TBR_SCALE(profile->depth);
414 	if (tbr->tbr_rate > 0)
415 		tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate;
416 	else
417 		tbr->tbr_filluptime = 0xffffffffffffffffLL;
418 	tbr->tbr_token = tbr->tbr_depth;
419 	tbr->tbr_last = read_machclk();
420 	tbr->tbr_lastop = ALTDQ_REMOVE;
421 
422 	otbr = ifq->altq_tbr;
423 	ifq->altq_tbr = tbr;	/* set the new tbr */
424 
425 	if (otbr != NULL)
426 		free(otbr, M_DEVBUF);
427 	else {
428 		if (tbr_timer == 0) {
429 			CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0);
430 			tbr_timer = 1;
431 		}
432 	}
433 	IFQ_UNLOCK(ifq);
434 	return (0);
435 }
436 
437 /*
438  * tbr_timeout goes through the interface list, and kicks the drivers
439  * if necessary.
440  *
441  * MPSAFE
442  */
443 static void
tbr_timeout(arg)444 tbr_timeout(arg)
445 	void *arg;
446 {
447 #ifdef __FreeBSD__
448 	VNET_ITERATOR_DECL(vnet_iter);
449 #endif
450 	struct ifnet *ifp;
451 	int active, s;
452 
453 	active = 0;
454 #ifdef __NetBSD__
455 	s = splnet();
456 #else
457 	s = splimp();
458 #endif
459 #ifdef __FreeBSD__
460 	IFNET_RLOCK_NOSLEEP();
461 	VNET_LIST_RLOCK_NOSLEEP();
462 	VNET_FOREACH(vnet_iter) {
463 		CURVNET_SET(vnet_iter);
464 #endif
465 		for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
466 		    ifp = TAILQ_NEXT(ifp, if_list)) {
467 			/* read from if_snd unlocked */
468 			if (!TBR_IS_ENABLED(&ifp->if_snd))
469 				continue;
470 			active++;
471 			if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
472 			    ifp->if_start != NULL)
473 				(*ifp->if_start)(ifp);
474 		}
475 #ifdef __FreeBSD__
476 		CURVNET_RESTORE();
477 	}
478 	VNET_LIST_RUNLOCK_NOSLEEP();
479 	IFNET_RUNLOCK_NOSLEEP();
480 #endif
481 	splx(s);
482 	if (active > 0)
483 		CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0);
484 	else
485 		tbr_timer = 0;	/* don't need tbr_timer anymore */
486 }
487 
488 /*
489  * get token bucket regulator profile
490  */
491 int
tbr_get(ifq,profile)492 tbr_get(ifq, profile)
493 	struct ifaltq *ifq;
494 	struct tb_profile *profile;
495 {
496 	struct tb_regulator *tbr;
497 
498 	IFQ_LOCK(ifq);
499 	if ((tbr = ifq->altq_tbr) == NULL) {
500 		profile->rate = 0;
501 		profile->depth = 0;
502 	} else {
503 		profile->rate =
504 		    (u_int)TBR_UNSCALE(tbr->tbr_rate * 8 * machclk_freq);
505 		profile->depth = (u_int)TBR_UNSCALE(tbr->tbr_depth);
506 	}
507 	IFQ_UNLOCK(ifq);
508 	return (0);
509 }
510 
511 /*
512  * attach a discipline to the interface.  if one already exists, it is
513  * overridden.
514  * Locking is done in the discipline specific attach functions. Basically
515  * they call back to altq_attach which takes care of the attach and locking.
516  */
517 int
altq_pfattach(struct pf_altq * a)518 altq_pfattach(struct pf_altq *a)
519 {
520 	int error = 0;
521 
522 	switch (a->scheduler) {
523 	case ALTQT_NONE:
524 		break;
525 #ifdef ALTQ_CBQ
526 	case ALTQT_CBQ:
527 		error = cbq_pfattach(a);
528 		break;
529 #endif
530 #ifdef ALTQ_PRIQ
531 	case ALTQT_PRIQ:
532 		error = priq_pfattach(a);
533 		break;
534 #endif
535 #ifdef ALTQ_HFSC
536 	case ALTQT_HFSC:
537 		error = hfsc_pfattach(a);
538 		break;
539 #endif
540 	default:
541 		error = ENXIO;
542 	}
543 
544 	return (error);
545 }
546 
547 /*
548  * detach a discipline from the interface.
549  * it is possible that the discipline was already overridden by another
550  * discipline.
551  */
552 int
altq_pfdetach(struct pf_altq * a)553 altq_pfdetach(struct pf_altq *a)
554 {
555 	struct ifnet *ifp;
556 	int s, error = 0;
557 
558 	if ((ifp = ifunit(a->ifname)) == NULL)
559 		return (EINVAL);
560 
561 	/* if this discipline is no longer referenced, just return */
562 	/* read unlocked from if_snd */
563 	if (a->altq_disc == NULL || a->altq_disc != ifp->if_snd.altq_disc)
564 		return (0);
565 
566 #ifdef __NetBSD__
567 	s = splnet();
568 #else
569 	s = splimp();
570 #endif
571 	/* read unlocked from if_snd, _disable and _detach take care */
572 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
573 		error = altq_disable(&ifp->if_snd);
574 	if (error == 0)
575 		error = altq_detach(&ifp->if_snd);
576 	splx(s);
577 
578 	return (error);
579 }
580 
581 /*
582  * add a discipline or a queue
583  * Locking is done in the discipline specific functions with regards to
584  * malloc with WAITOK, also it is not yet clear which lock to use.
585  */
586 int
altq_add(struct pf_altq * a)587 altq_add(struct pf_altq *a)
588 {
589 	int error = 0;
590 
591 	if (a->qname[0] != 0)
592 		return (altq_add_queue(a));
593 
594 	if (machclk_freq == 0)
595 		init_machclk();
596 	if (machclk_freq == 0)
597 		panic("altq_add: no cpu clock");
598 
599 	switch (a->scheduler) {
600 #ifdef ALTQ_CBQ
601 	case ALTQT_CBQ:
602 		error = cbq_add_altq(a);
603 		break;
604 #endif
605 #ifdef ALTQ_PRIQ
606 	case ALTQT_PRIQ:
607 		error = priq_add_altq(a);
608 		break;
609 #endif
610 #ifdef ALTQ_HFSC
611 	case ALTQT_HFSC:
612 		error = hfsc_add_altq(a);
613 		break;
614 #endif
615 	default:
616 		error = ENXIO;
617 	}
618 
619 	return (error);
620 }
621 
622 /*
623  * remove a discipline or a queue
624  * It is yet unclear what lock to use to protect this operation, the
625  * discipline specific functions will determine and grab it
626  */
627 int
altq_remove(struct pf_altq * a)628 altq_remove(struct pf_altq *a)
629 {
630 	int error = 0;
631 
632 	if (a->qname[0] != 0)
633 		return (altq_remove_queue(a));
634 
635 	switch (a->scheduler) {
636 #ifdef ALTQ_CBQ
637 	case ALTQT_CBQ:
638 		error = cbq_remove_altq(a);
639 		break;
640 #endif
641 #ifdef ALTQ_PRIQ
642 	case ALTQT_PRIQ:
643 		error = priq_remove_altq(a);
644 		break;
645 #endif
646 #ifdef ALTQ_HFSC
647 	case ALTQT_HFSC:
648 		error = hfsc_remove_altq(a);
649 		break;
650 #endif
651 	default:
652 		error = ENXIO;
653 	}
654 
655 	return (error);
656 }
657 
658 /*
659  * add a queue to the discipline
660  * It is yet unclear what lock to use to protect this operation, the
661  * discipline specific functions will determine and grab it
662  */
663 int
altq_add_queue(struct pf_altq * a)664 altq_add_queue(struct pf_altq *a)
665 {
666 	int error = 0;
667 
668 	switch (a->scheduler) {
669 #ifdef ALTQ_CBQ
670 	case ALTQT_CBQ:
671 		error = cbq_add_queue(a);
672 		break;
673 #endif
674 #ifdef ALTQ_PRIQ
675 	case ALTQT_PRIQ:
676 		error = priq_add_queue(a);
677 		break;
678 #endif
679 #ifdef ALTQ_HFSC
680 	case ALTQT_HFSC:
681 		error = hfsc_add_queue(a);
682 		break;
683 #endif
684 	default:
685 		error = ENXIO;
686 	}
687 
688 	return (error);
689 }
690 
691 /*
692  * remove a queue from the discipline
693  * It is yet unclear what lock to use to protect this operation, the
694  * discipline specific functions will determine and grab it
695  */
696 int
altq_remove_queue(struct pf_altq * a)697 altq_remove_queue(struct pf_altq *a)
698 {
699 	int error = 0;
700 
701 	switch (a->scheduler) {
702 #ifdef ALTQ_CBQ
703 	case ALTQT_CBQ:
704 		error = cbq_remove_queue(a);
705 		break;
706 #endif
707 #ifdef ALTQ_PRIQ
708 	case ALTQT_PRIQ:
709 		error = priq_remove_queue(a);
710 		break;
711 #endif
712 #ifdef ALTQ_HFSC
713 	case ALTQT_HFSC:
714 		error = hfsc_remove_queue(a);
715 		break;
716 #endif
717 	default:
718 		error = ENXIO;
719 	}
720 
721 	return (error);
722 }
723 
724 /*
725  * get queue statistics
726  * Locking is done in the discipline specific functions with regards to
727  * copyout operations, also it is not yet clear which lock to use.
728  */
729 int
altq_getqstats(struct pf_altq * a,void * ubuf,int * nbytes)730 altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
731 {
732 	int error = 0;
733 
734 	switch (a->scheduler) {
735 #ifdef ALTQ_CBQ
736 	case ALTQT_CBQ:
737 		error = cbq_getqstats(a, ubuf, nbytes);
738 		break;
739 #endif
740 #ifdef ALTQ_PRIQ
741 	case ALTQT_PRIQ:
742 		error = priq_getqstats(a, ubuf, nbytes);
743 		break;
744 #endif
745 #ifdef ALTQ_HFSC
746 	case ALTQT_HFSC:
747 		error = hfsc_getqstats(a, ubuf, nbytes);
748 		break;
749 #endif
750 	default:
751 		error = ENXIO;
752 	}
753 
754 	return (error);
755 }
756 
757 /*
758  * read and write diffserv field in IPv4 or IPv6 header
759  */
760 u_int8_t
read_dsfield(m,pktattr)761 read_dsfield(m, pktattr)
762 	struct mbuf *m;
763 	struct altq_pktattr *pktattr;
764 {
765 	struct mbuf *m0;
766 	u_int8_t ds_field = 0;
767 
768 	if (pktattr == NULL ||
769 	    (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
770 		return ((u_int8_t)0);
771 
772 	/* verify that pattr_hdr is within the mbuf data */
773 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
774 		if ((pktattr->pattr_hdr >= m0->m_data) &&
775 		    (pktattr->pattr_hdr < m0->m_data + m0->m_len))
776 			break;
777 	if (m0 == NULL) {
778 		/* ick, pattr_hdr is stale */
779 		pktattr->pattr_af = AF_UNSPEC;
780 #ifdef ALTQ_DEBUG
781 		printf("read_dsfield: can't locate header!\n");
782 #endif
783 		return ((u_int8_t)0);
784 	}
785 
786 	if (pktattr->pattr_af == AF_INET) {
787 		struct ip *ip = (struct ip *)pktattr->pattr_hdr;
788 
789 		if (ip->ip_v != 4)
790 			return ((u_int8_t)0);	/* version mismatch! */
791 		ds_field = ip->ip_tos;
792 	}
793 #ifdef INET6
794 	else if (pktattr->pattr_af == AF_INET6) {
795 		struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
796 		u_int32_t flowlabel;
797 
798 		flowlabel = ntohl(ip6->ip6_flow);
799 		if ((flowlabel >> 28) != 6)
800 			return ((u_int8_t)0);	/* version mismatch! */
801 		ds_field = (flowlabel >> 20) & 0xff;
802 	}
803 #endif
804 	return (ds_field);
805 }
806 
807 void
write_dsfield(struct mbuf * m,struct altq_pktattr * pktattr,u_int8_t dsfield)808 write_dsfield(struct mbuf *m, struct altq_pktattr *pktattr, u_int8_t dsfield)
809 {
810 	struct mbuf *m0;
811 
812 	if (pktattr == NULL ||
813 	    (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
814 		return;
815 
816 	/* verify that pattr_hdr is within the mbuf data */
817 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
818 		if ((pktattr->pattr_hdr >= m0->m_data) &&
819 		    (pktattr->pattr_hdr < m0->m_data + m0->m_len))
820 			break;
821 	if (m0 == NULL) {
822 		/* ick, pattr_hdr is stale */
823 		pktattr->pattr_af = AF_UNSPEC;
824 #ifdef ALTQ_DEBUG
825 		printf("write_dsfield: can't locate header!\n");
826 #endif
827 		return;
828 	}
829 
830 	if (pktattr->pattr_af == AF_INET) {
831 		struct ip *ip = (struct ip *)pktattr->pattr_hdr;
832 		u_int8_t old;
833 		int32_t sum;
834 
835 		if (ip->ip_v != 4)
836 			return;		/* version mismatch! */
837 		old = ip->ip_tos;
838 		dsfield |= old & 3;	/* leave CU bits */
839 		if (old == dsfield)
840 			return;
841 		ip->ip_tos = dsfield;
842 		/*
843 		 * update checksum (from RFC1624)
844 		 *	   HC' = ~(~HC + ~m + m')
845 		 */
846 		sum = ~ntohs(ip->ip_sum) & 0xffff;
847 		sum += 0xff00 + (~old & 0xff) + dsfield;
848 		sum = (sum >> 16) + (sum & 0xffff);
849 		sum += (sum >> 16);  /* add carry */
850 
851 		ip->ip_sum = htons(~sum & 0xffff);
852 	}
853 #ifdef INET6
854 	else if (pktattr->pattr_af == AF_INET6) {
855 		struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
856 		u_int32_t flowlabel;
857 
858 		flowlabel = ntohl(ip6->ip6_flow);
859 		if ((flowlabel >> 28) != 6)
860 			return;		/* version mismatch! */
861 		flowlabel = (flowlabel & 0xf03fffff) | (dsfield << 20);
862 		ip6->ip6_flow = htonl(flowlabel);
863 	}
864 #endif
865 	return;
866 }
867 
868 
869 /*
870  * high resolution clock support taking advantage of a machine dependent
871  * high resolution time counter (e.g., timestamp counter of intel pentium).
872  * we assume
873  *  - 64-bit-long monotonically-increasing counter
874  *  - frequency range is 100M-4GHz (CPU speed)
875  */
876 /* if pcc is not available or disabled, emulate 256MHz using microtime() */
877 #define	MACHCLK_SHIFT	8
878 
879 int machclk_usepcc;
880 u_int32_t machclk_freq;
881 u_int32_t machclk_per_tick;
882 
883 #if defined(__i386__) && defined(__NetBSD__)
884 extern u_int64_t cpu_tsc_freq;
885 #endif
886 
887 #if (__FreeBSD_version >= 700035)
888 /* Update TSC freq with the value indicated by the caller. */
889 static void
tsc_freq_changed(void * arg,const struct cf_level * level,int status)890 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
891 {
892 	/* If there was an error during the transition, don't do anything. */
893 	if (status != 0)
894 		return;
895 
896 #if (__FreeBSD_version >= 701102) && (defined(__amd64__) || defined(__i386__))
897 	/* If TSC is P-state invariant, don't do anything. */
898 	if (tsc_is_invariant)
899 		return;
900 #endif
901 
902 	/* Total setting for this level gives the new frequency in MHz. */
903 	init_machclk();
904 }
905 EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
906     EVENTHANDLER_PRI_LAST);
907 #endif /* __FreeBSD_version >= 700035 */
908 
909 static void
init_machclk_setup(void)910 init_machclk_setup(void)
911 {
912 #if (__FreeBSD_version >= 600000)
913 	callout_init(&tbr_callout, 0);
914 #endif
915 
916 	machclk_usepcc = 1;
917 
918 #if (!defined(__amd64__) && !defined(__i386__)) || defined(ALTQ_NOPCC)
919 	machclk_usepcc = 0;
920 #endif
921 #if defined(__FreeBSD__) && defined(SMP)
922 	machclk_usepcc = 0;
923 #endif
924 #if defined(__NetBSD__) && defined(MULTIPROCESSOR)
925 	machclk_usepcc = 0;
926 #endif
927 #if defined(__amd64__) || defined(__i386__)
928 	/* check if TSC is available */
929 #ifdef __FreeBSD__
930 	if ((cpu_feature & CPUID_TSC) == 0 ||
931 	    atomic_load_acq_64(&tsc_freq) == 0)
932 #else
933 	if ((cpu_feature & CPUID_TSC) == 0)
934 #endif
935 		machclk_usepcc = 0;
936 #endif
937 }
938 
939 void
init_machclk(void)940 init_machclk(void)
941 {
942 	static int called;
943 
944 	/* Call one-time initialization function. */
945 	if (!called) {
946 		init_machclk_setup();
947 		called = 1;
948 	}
949 
950 	if (machclk_usepcc == 0) {
951 		/* emulate 256MHz using microtime() */
952 		machclk_freq = 1000000 << MACHCLK_SHIFT;
953 		machclk_per_tick = machclk_freq / hz;
954 #ifdef ALTQ_DEBUG
955 		printf("altq: emulate %uHz cpu clock\n", machclk_freq);
956 #endif
957 		return;
958 	}
959 
960 	/*
961 	 * if the clock frequency (of Pentium TSC or Alpha PCC) is
962 	 * accessible, just use it.
963 	 */
964 #if defined(__amd64__) || defined(__i386__)
965 #ifdef __FreeBSD__
966 	machclk_freq = atomic_load_acq_64(&tsc_freq);
967 #elif defined(__NetBSD__)
968 	machclk_freq = (u_int32_t)cpu_tsc_freq;
969 #elif defined(__OpenBSD__) && (defined(I586_CPU) || defined(I686_CPU))
970 	machclk_freq = pentium_mhz * 1000000;
971 #endif
972 #endif
973 
974 	/*
975 	 * if we don't know the clock frequency, measure it.
976 	 */
977 	if (machclk_freq == 0) {
978 		static int	wait;
979 		struct timeval	tv_start, tv_end;
980 		u_int64_t	start, end, diff;
981 		int		timo;
982 
983 		microtime(&tv_start);
984 		start = read_machclk();
985 		timo = hz;	/* 1 sec */
986 		(void)tsleep(&wait, PWAIT | PCATCH, "init_machclk", timo);
987 		microtime(&tv_end);
988 		end = read_machclk();
989 		diff = (u_int64_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000000
990 		    + tv_end.tv_usec - tv_start.tv_usec;
991 		if (diff != 0)
992 			machclk_freq = (u_int)((end - start) * 1000000 / diff);
993 	}
994 
995 	machclk_per_tick = machclk_freq / hz;
996 
997 #ifdef ALTQ_DEBUG
998 	printf("altq: CPU clock: %uHz\n", machclk_freq);
999 #endif
1000 }
1001 
1002 #if defined(__OpenBSD__) && defined(__i386__)
1003 static __inline u_int64_t
rdtsc(void)1004 rdtsc(void)
1005 {
1006 	u_int64_t rv;
1007 	__asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
1008 	return (rv);
1009 }
1010 #endif /* __OpenBSD__ && __i386__ */
1011 
1012 u_int64_t
read_machclk(void)1013 read_machclk(void)
1014 {
1015 	u_int64_t val;
1016 
1017 	if (machclk_usepcc) {
1018 #if defined(__amd64__) || defined(__i386__)
1019 		val = rdtsc();
1020 #else
1021 		panic("read_machclk");
1022 #endif
1023 	} else {
1024 		struct timeval tv;
1025 
1026 		microtime(&tv);
1027 		val = (((u_int64_t)(tv.tv_sec - boottime.tv_sec) * 1000000
1028 		    + tv.tv_usec) << MACHCLK_SHIFT);
1029 	}
1030 	return (val);
1031 }
1032 
1033 #ifdef ALTQ3_CLFIER_COMPAT
1034 
1035 #ifndef IPPROTO_ESP
1036 #define	IPPROTO_ESP	50		/* encapsulating security payload */
1037 #endif
1038 #ifndef IPPROTO_AH
1039 #define	IPPROTO_AH	51		/* authentication header */
1040 #endif
1041 
1042 /*
1043  * extract flow information from a given packet.
1044  * filt_mask shows flowinfo fields required.
1045  * we assume the ip header is in one mbuf, and addresses and ports are
1046  * in network byte order.
1047  */
1048 int
altq_extractflow(m,af,flow,filt_bmask)1049 altq_extractflow(m, af, flow, filt_bmask)
1050 	struct mbuf *m;
1051 	int af;
1052 	struct flowinfo *flow;
1053 	u_int32_t	filt_bmask;
1054 {
1055 
1056 	switch (af) {
1057 	case PF_INET: {
1058 		struct flowinfo_in *fin;
1059 		struct ip *ip;
1060 
1061 		ip = mtod(m, struct ip *);
1062 
1063 		if (ip->ip_v != 4)
1064 			break;
1065 
1066 		fin = (struct flowinfo_in *)flow;
1067 		fin->fi_len = sizeof(struct flowinfo_in);
1068 		fin->fi_family = AF_INET;
1069 
1070 		fin->fi_proto = ip->ip_p;
1071 		fin->fi_tos = ip->ip_tos;
1072 
1073 		fin->fi_src.s_addr = ip->ip_src.s_addr;
1074 		fin->fi_dst.s_addr = ip->ip_dst.s_addr;
1075 
1076 		if (filt_bmask & FIMB4_PORTS)
1077 			/* if port info is required, extract port numbers */
1078 			extract_ports4(m, ip, fin);
1079 		else {
1080 			fin->fi_sport = 0;
1081 			fin->fi_dport = 0;
1082 			fin->fi_gpi = 0;
1083 		}
1084 		return (1);
1085 	}
1086 
1087 #ifdef INET6
1088 	case PF_INET6: {
1089 		struct flowinfo_in6 *fin6;
1090 		struct ip6_hdr *ip6;
1091 
1092 		ip6 = mtod(m, struct ip6_hdr *);
1093 		/* should we check the ip version? */
1094 
1095 		fin6 = (struct flowinfo_in6 *)flow;
1096 		fin6->fi6_len = sizeof(struct flowinfo_in6);
1097 		fin6->fi6_family = AF_INET6;
1098 
1099 		fin6->fi6_proto = ip6->ip6_nxt;
1100 		fin6->fi6_tclass   = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
1101 
1102 		fin6->fi6_flowlabel = ip6->ip6_flow & htonl(0x000fffff);
1103 		fin6->fi6_src = ip6->ip6_src;
1104 		fin6->fi6_dst = ip6->ip6_dst;
1105 
1106 		if ((filt_bmask & FIMB6_PORTS) ||
1107 		    ((filt_bmask & FIMB6_PROTO)
1108 		     && ip6->ip6_nxt > IPPROTO_IPV6))
1109 			/*
1110 			 * if port info is required, or proto is required
1111 			 * but there are option headers, extract port
1112 			 * and protocol numbers.
1113 			 */
1114 			extract_ports6(m, ip6, fin6);
1115 		else {
1116 			fin6->fi6_sport = 0;
1117 			fin6->fi6_dport = 0;
1118 			fin6->fi6_gpi = 0;
1119 		}
1120 		return (1);
1121 	}
1122 #endif /* INET6 */
1123 
1124 	default:
1125 		break;
1126 	}
1127 
1128 	/* failed */
1129 	flow->fi_len = sizeof(struct flowinfo);
1130 	flow->fi_family = AF_UNSPEC;
1131 	return (0);
1132 }
1133 
1134 /*
1135  * helper routine to extract port numbers
1136  */
1137 /* structure for ipsec and ipv6 option header template */
1138 struct _opt6 {
1139 	u_int8_t	opt6_nxt;	/* next header */
1140 	u_int8_t	opt6_hlen;	/* header extension length */
1141 	u_int16_t	_pad;
1142 	u_int32_t	ah_spi;		/* security parameter index
1143 					   for authentication header */
1144 };
1145 
1146 /*
1147  * extract port numbers from a ipv4 packet.
1148  */
1149 static int
extract_ports4(m,ip,fin)1150 extract_ports4(m, ip, fin)
1151 	struct mbuf *m;
1152 	struct ip *ip;
1153 	struct flowinfo_in *fin;
1154 {
1155 	struct mbuf *m0;
1156 	u_short ip_off;
1157 	u_int8_t proto;
1158 	int 	off;
1159 
1160 	fin->fi_sport = 0;
1161 	fin->fi_dport = 0;
1162 	fin->fi_gpi = 0;
1163 
1164 	ip_off = ntohs(ip->ip_off);
1165 	/* if it is a fragment, try cached fragment info */
1166 	if (ip_off & IP_OFFMASK) {
1167 		ip4f_lookup(ip, fin);
1168 		return (1);
1169 	}
1170 
1171 	/* locate the mbuf containing the protocol header */
1172 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
1173 		if (((caddr_t)ip >= m0->m_data) &&
1174 		    ((caddr_t)ip < m0->m_data + m0->m_len))
1175 			break;
1176 	if (m0 == NULL) {
1177 #ifdef ALTQ_DEBUG
1178 		printf("extract_ports4: can't locate header! ip=%p\n", ip);
1179 #endif
1180 		return (0);
1181 	}
1182 	off = ((caddr_t)ip - m0->m_data) + (ip->ip_hl << 2);
1183 	proto = ip->ip_p;
1184 
1185 #ifdef ALTQ_IPSEC
1186  again:
1187 #endif
1188 	while (off >= m0->m_len) {
1189 		off -= m0->m_len;
1190 		m0 = m0->m_next;
1191 		if (m0 == NULL)
1192 			return (0);  /* bogus ip_hl! */
1193 	}
1194 	if (m0->m_len < off + 4)
1195 		return (0);
1196 
1197 	switch (proto) {
1198 	case IPPROTO_TCP:
1199 	case IPPROTO_UDP: {
1200 		struct udphdr *udp;
1201 
1202 		udp = (struct udphdr *)(mtod(m0, caddr_t) + off);
1203 		fin->fi_sport = udp->uh_sport;
1204 		fin->fi_dport = udp->uh_dport;
1205 		fin->fi_proto = proto;
1206 		}
1207 		break;
1208 
1209 #ifdef ALTQ_IPSEC
1210 	case IPPROTO_ESP:
1211 		if (fin->fi_gpi == 0){
1212 			u_int32_t *gpi;
1213 
1214 			gpi = (u_int32_t *)(mtod(m0, caddr_t) + off);
1215 			fin->fi_gpi   = *gpi;
1216 		}
1217 		fin->fi_proto = proto;
1218 		break;
1219 
1220 	case IPPROTO_AH: {
1221 			/* get next header and header length */
1222 			struct _opt6 *opt6;
1223 
1224 			opt6 = (struct _opt6 *)(mtod(m0, caddr_t) + off);
1225 			proto = opt6->opt6_nxt;
1226 			off += 8 + (opt6->opt6_hlen * 4);
1227 			if (fin->fi_gpi == 0 && m0->m_len >= off + 8)
1228 				fin->fi_gpi = opt6->ah_spi;
1229 		}
1230 		/* goto the next header */
1231 		goto again;
1232 #endif  /* ALTQ_IPSEC */
1233 
1234 	default:
1235 		fin->fi_proto = proto;
1236 		return (0);
1237 	}
1238 
1239 	/* if this is a first fragment, cache it. */
1240 	if (ip_off & IP_MF)
1241 		ip4f_cache(ip, fin);
1242 
1243 	return (1);
1244 }
1245 
1246 #ifdef INET6
1247 static int
extract_ports6(m,ip6,fin6)1248 extract_ports6(m, ip6, fin6)
1249 	struct mbuf *m;
1250 	struct ip6_hdr *ip6;
1251 	struct flowinfo_in6 *fin6;
1252 {
1253 	struct mbuf *m0;
1254 	int	off;
1255 	u_int8_t proto;
1256 
1257 	fin6->fi6_gpi   = 0;
1258 	fin6->fi6_sport = 0;
1259 	fin6->fi6_dport = 0;
1260 
1261 	/* locate the mbuf containing the protocol header */
1262 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
1263 		if (((caddr_t)ip6 >= m0->m_data) &&
1264 		    ((caddr_t)ip6 < m0->m_data + m0->m_len))
1265 			break;
1266 	if (m0 == NULL) {
1267 #ifdef ALTQ_DEBUG
1268 		printf("extract_ports6: can't locate header! ip6=%p\n", ip6);
1269 #endif
1270 		return (0);
1271 	}
1272 	off = ((caddr_t)ip6 - m0->m_data) + sizeof(struct ip6_hdr);
1273 
1274 	proto = ip6->ip6_nxt;
1275 	do {
1276 		while (off >= m0->m_len) {
1277 			off -= m0->m_len;
1278 			m0 = m0->m_next;
1279 			if (m0 == NULL)
1280 				return (0);
1281 		}
1282 		if (m0->m_len < off + 4)
1283 			return (0);
1284 
1285 		switch (proto) {
1286 		case IPPROTO_TCP:
1287 		case IPPROTO_UDP: {
1288 			struct udphdr *udp;
1289 
1290 			udp = (struct udphdr *)(mtod(m0, caddr_t) + off);
1291 			fin6->fi6_sport = udp->uh_sport;
1292 			fin6->fi6_dport = udp->uh_dport;
1293 			fin6->fi6_proto = proto;
1294 			}
1295 			return (1);
1296 
1297 		case IPPROTO_ESP:
1298 			if (fin6->fi6_gpi == 0) {
1299 				u_int32_t *gpi;
1300 
1301 				gpi = (u_int32_t *)(mtod(m0, caddr_t) + off);
1302 				fin6->fi6_gpi   = *gpi;
1303 			}
1304 			fin6->fi6_proto = proto;
1305 			return (1);
1306 
1307 		case IPPROTO_AH: {
1308 			/* get next header and header length */
1309 			struct _opt6 *opt6;
1310 
1311 			opt6 = (struct _opt6 *)(mtod(m0, caddr_t) + off);
1312 			if (fin6->fi6_gpi == 0 && m0->m_len >= off + 8)
1313 				fin6->fi6_gpi = opt6->ah_spi;
1314 			proto = opt6->opt6_nxt;
1315 			off += 8 + (opt6->opt6_hlen * 4);
1316 			/* goto the next header */
1317 			break;
1318 			}
1319 
1320 		case IPPROTO_HOPOPTS:
1321 		case IPPROTO_ROUTING:
1322 		case IPPROTO_DSTOPTS: {
1323 			/* get next header and header length */
1324 			struct _opt6 *opt6;
1325 
1326 			opt6 = (struct _opt6 *)(mtod(m0, caddr_t) + off);
1327 			proto = opt6->opt6_nxt;
1328 			off += (opt6->opt6_hlen + 1) * 8;
1329 			/* goto the next header */
1330 			break;
1331 			}
1332 
1333 		case IPPROTO_FRAGMENT:
1334 			/* ipv6 fragmentations are not supported yet */
1335 		default:
1336 			fin6->fi6_proto = proto;
1337 			return (0);
1338 		}
1339 	} while (1);
1340 	/*NOTREACHED*/
1341 }
1342 #endif /* INET6 */
1343 
1344 /*
1345  * altq common classifier
1346  */
1347 int
acc_add_filter(classifier,filter,class,phandle)1348 acc_add_filter(classifier, filter, class, phandle)
1349 	struct acc_classifier *classifier;
1350 	struct flow_filter *filter;
1351 	void	*class;
1352 	u_long	*phandle;
1353 {
1354 	struct acc_filter *afp, *prev, *tmp;
1355 	int	i, s;
1356 
1357 #ifdef INET6
1358 	if (filter->ff_flow.fi_family != AF_INET &&
1359 	    filter->ff_flow.fi_family != AF_INET6)
1360 		return (EINVAL);
1361 #else
1362 	if (filter->ff_flow.fi_family != AF_INET)
1363 		return (EINVAL);
1364 #endif
1365 
1366 	afp = malloc(sizeof(struct acc_filter),
1367 	       M_DEVBUF, M_WAITOK);
1368 	if (afp == NULL)
1369 		return (ENOMEM);
1370 	bzero(afp, sizeof(struct acc_filter));
1371 
1372 	afp->f_filter = *filter;
1373 	afp->f_class = class;
1374 
1375 	i = ACC_WILDCARD_INDEX;
1376 	if (filter->ff_flow.fi_family == AF_INET) {
1377 		struct flow_filter *filter4 = &afp->f_filter;
1378 
1379 		/*
1380 		 * if address is 0, it's a wildcard.  if address mask
1381 		 * isn't set, use full mask.
1382 		 */
1383 		if (filter4->ff_flow.fi_dst.s_addr == 0)
1384 			filter4->ff_mask.mask_dst.s_addr = 0;
1385 		else if (filter4->ff_mask.mask_dst.s_addr == 0)
1386 			filter4->ff_mask.mask_dst.s_addr = 0xffffffff;
1387 		if (filter4->ff_flow.fi_src.s_addr == 0)
1388 			filter4->ff_mask.mask_src.s_addr = 0;
1389 		else if (filter4->ff_mask.mask_src.s_addr == 0)
1390 			filter4->ff_mask.mask_src.s_addr = 0xffffffff;
1391 
1392 		/* clear extra bits in addresses  */
1393 		   filter4->ff_flow.fi_dst.s_addr &=
1394 		       filter4->ff_mask.mask_dst.s_addr;
1395 		   filter4->ff_flow.fi_src.s_addr &=
1396 		       filter4->ff_mask.mask_src.s_addr;
1397 
1398 		/*
1399 		 * if dst address is a wildcard, use hash-entry
1400 		 * ACC_WILDCARD_INDEX.
1401 		 */
1402 		if (filter4->ff_mask.mask_dst.s_addr != 0xffffffff)
1403 			i = ACC_WILDCARD_INDEX;
1404 		else
1405 			i = ACC_GET_HASH_INDEX(filter4->ff_flow.fi_dst.s_addr);
1406 	}
1407 #ifdef INET6
1408 	else if (filter->ff_flow.fi_family == AF_INET6) {
1409 		struct flow_filter6 *filter6 =
1410 			(struct flow_filter6 *)&afp->f_filter;
1411 #ifndef IN6MASK0 /* taken from kame ipv6 */
1412 #define	IN6MASK0	{{{ 0, 0, 0, 0 }}}
1413 #define	IN6MASK128	{{{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }}}
1414 		const struct in6_addr in6mask0 = IN6MASK0;
1415 		const struct in6_addr in6mask128 = IN6MASK128;
1416 #endif
1417 
1418 		if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_dst))
1419 			filter6->ff_mask6.mask6_dst = in6mask0;
1420 		else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_dst))
1421 			filter6->ff_mask6.mask6_dst = in6mask128;
1422 		if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_src))
1423 			filter6->ff_mask6.mask6_src = in6mask0;
1424 		else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_src))
1425 			filter6->ff_mask6.mask6_src = in6mask128;
1426 
1427 		/* clear extra bits in addresses  */
1428 		for (i = 0; i < 16; i++)
1429 			filter6->ff_flow6.fi6_dst.s6_addr[i] &=
1430 			    filter6->ff_mask6.mask6_dst.s6_addr[i];
1431 		for (i = 0; i < 16; i++)
1432 			filter6->ff_flow6.fi6_src.s6_addr[i] &=
1433 			    filter6->ff_mask6.mask6_src.s6_addr[i];
1434 
1435 		if (filter6->ff_flow6.fi6_flowlabel == 0)
1436 			i = ACC_WILDCARD_INDEX;
1437 		else
1438 			i = ACC_GET_HASH_INDEX(filter6->ff_flow6.fi6_flowlabel);
1439 	}
1440 #endif /* INET6 */
1441 
1442 	afp->f_handle = get_filt_handle(classifier, i);
1443 
1444 	/* update filter bitmask */
1445 	afp->f_fbmask = filt2fibmask(filter);
1446 	classifier->acc_fbmask |= afp->f_fbmask;
1447 
1448 	/*
1449 	 * add this filter to the filter list.
1450 	 * filters are ordered from the highest rule number.
1451 	 */
1452 #ifdef __NetBSD__
1453 	s = splnet();
1454 #else
1455 	s = splimp();
1456 #endif
1457 	prev = NULL;
1458 	LIST_FOREACH(tmp, &classifier->acc_filters[i], f_chain) {
1459 		if (tmp->f_filter.ff_ruleno > afp->f_filter.ff_ruleno)
1460 			prev = tmp;
1461 		else
1462 			break;
1463 	}
1464 	if (prev == NULL)
1465 		LIST_INSERT_HEAD(&classifier->acc_filters[i], afp, f_chain);
1466 	else
1467 		LIST_INSERT_AFTER(prev, afp, f_chain);
1468 	splx(s);
1469 
1470 	*phandle = afp->f_handle;
1471 	return (0);
1472 }
1473 
1474 int
acc_delete_filter(classifier,handle)1475 acc_delete_filter(classifier, handle)
1476 	struct acc_classifier *classifier;
1477 	u_long handle;
1478 {
1479 	struct acc_filter *afp;
1480 	int	s;
1481 
1482 	if ((afp = filth_to_filtp(classifier, handle)) == NULL)
1483 		return (EINVAL);
1484 
1485 #ifdef __NetBSD__
1486 	s = splnet();
1487 #else
1488 	s = splimp();
1489 #endif
1490 	LIST_REMOVE(afp, f_chain);
1491 	splx(s);
1492 
1493 	free(afp, M_DEVBUF);
1494 
1495 	/* todo: update filt_bmask */
1496 
1497 	return (0);
1498 }
1499 
1500 /*
1501  * delete filters referencing to the specified class.
1502  * if the all flag is not 0, delete all the filters.
1503  */
1504 int
acc_discard_filters(classifier,class,all)1505 acc_discard_filters(classifier, class, all)
1506 	struct acc_classifier *classifier;
1507 	void	*class;
1508 	int	all;
1509 {
1510 	struct acc_filter *afp;
1511 	int	i, s;
1512 
1513 #ifdef __NetBSD__
1514 	s = splnet();
1515 #else
1516 	s = splimp();
1517 #endif
1518 	for (i = 0; i < ACC_FILTER_TABLESIZE; i++) {
1519 		do {
1520 			LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
1521 				if (all || afp->f_class == class) {
1522 					LIST_REMOVE(afp, f_chain);
1523 					free(afp, M_DEVBUF);
1524 					/* start again from the head */
1525 					break;
1526 				}
1527 		} while (afp != NULL);
1528 	}
1529 	splx(s);
1530 
1531 	if (all)
1532 		classifier->acc_fbmask = 0;
1533 
1534 	return (0);
1535 }
1536 
1537 void *
acc_classify(clfier,m,af)1538 acc_classify(clfier, m, af)
1539 	void *clfier;
1540 	struct mbuf *m;
1541 	int af;
1542 {
1543 	struct acc_classifier *classifier;
1544 	struct flowinfo flow;
1545 	struct acc_filter *afp;
1546 	int	i;
1547 
1548 	classifier = (struct acc_classifier *)clfier;
1549 	altq_extractflow(m, af, &flow, classifier->acc_fbmask);
1550 
1551 	if (flow.fi_family == AF_INET) {
1552 		struct flowinfo_in *fp = (struct flowinfo_in *)&flow;
1553 
1554 		if ((classifier->acc_fbmask & FIMB4_ALL) == FIMB4_TOS) {
1555 			/* only tos is used */
1556 			LIST_FOREACH(afp,
1557 				 &classifier->acc_filters[ACC_WILDCARD_INDEX],
1558 				 f_chain)
1559 				if (apply_tosfilter4(afp->f_fbmask,
1560 						     &afp->f_filter, fp))
1561 					/* filter matched */
1562 					return (afp->f_class);
1563 		} else if ((classifier->acc_fbmask &
1564 			(~(FIMB4_PROTO|FIMB4_SPORT|FIMB4_DPORT) & FIMB4_ALL))
1565 		    == 0) {
1566 			/* only proto and ports are used */
1567 			LIST_FOREACH(afp,
1568 				 &classifier->acc_filters[ACC_WILDCARD_INDEX],
1569 				 f_chain)
1570 				if (apply_ppfilter4(afp->f_fbmask,
1571 						    &afp->f_filter, fp))
1572 					/* filter matched */
1573 					return (afp->f_class);
1574 		} else {
1575 			/* get the filter hash entry from its dest address */
1576 			i = ACC_GET_HASH_INDEX(fp->fi_dst.s_addr);
1577 			do {
1578 				/*
1579 				 * go through this loop twice.  first for dst
1580 				 * hash, second for wildcards.
1581 				 */
1582 				LIST_FOREACH(afp, &classifier->acc_filters[i],
1583 					     f_chain)
1584 					if (apply_filter4(afp->f_fbmask,
1585 							  &afp->f_filter, fp))
1586 						/* filter matched */
1587 						return (afp->f_class);
1588 
1589 				/*
1590 				 * check again for filters with a dst addr
1591 				 * wildcard.
1592 				 * (daddr == 0 || dmask != 0xffffffff).
1593 				 */
1594 				if (i != ACC_WILDCARD_INDEX)
1595 					i = ACC_WILDCARD_INDEX;
1596 				else
1597 					break;
1598 			} while (1);
1599 		}
1600 	}
1601 #ifdef INET6
1602 	else if (flow.fi_family == AF_INET6) {
1603 		struct flowinfo_in6 *fp6 = (struct flowinfo_in6 *)&flow;
1604 
1605 		/* get the filter hash entry from its flow ID */
1606 		if (fp6->fi6_flowlabel != 0)
1607 			i = ACC_GET_HASH_INDEX(fp6->fi6_flowlabel);
1608 		else
1609 			/* flowlable can be zero */
1610 			i = ACC_WILDCARD_INDEX;
1611 
1612 		/* go through this loop twice.  first for flow hash, second
1613 		   for wildcards. */
1614 		do {
1615 			LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
1616 				if (apply_filter6(afp->f_fbmask,
1617 					(struct flow_filter6 *)&afp->f_filter,
1618 					fp6))
1619 					/* filter matched */
1620 					return (afp->f_class);
1621 
1622 			/*
1623 			 * check again for filters with a wildcard.
1624 			 */
1625 			if (i != ACC_WILDCARD_INDEX)
1626 				i = ACC_WILDCARD_INDEX;
1627 			else
1628 				break;
1629 		} while (1);
1630 	}
1631 #endif /* INET6 */
1632 
1633 	/* no filter matched */
1634 	return (NULL);
1635 }
1636 
1637 static int
apply_filter4(fbmask,filt,pkt)1638 apply_filter4(fbmask, filt, pkt)
1639 	u_int32_t	fbmask;
1640 	struct flow_filter *filt;
1641 	struct flowinfo_in *pkt;
1642 {
1643 	if (filt->ff_flow.fi_family != AF_INET)
1644 		return (0);
1645 	if ((fbmask & FIMB4_SPORT) && filt->ff_flow.fi_sport != pkt->fi_sport)
1646 		return (0);
1647 	if ((fbmask & FIMB4_DPORT) && filt->ff_flow.fi_dport != pkt->fi_dport)
1648 		return (0);
1649 	if ((fbmask & FIMB4_DADDR) &&
1650 	    filt->ff_flow.fi_dst.s_addr !=
1651 	    (pkt->fi_dst.s_addr & filt->ff_mask.mask_dst.s_addr))
1652 		return (0);
1653 	if ((fbmask & FIMB4_SADDR) &&
1654 	    filt->ff_flow.fi_src.s_addr !=
1655 	    (pkt->fi_src.s_addr & filt->ff_mask.mask_src.s_addr))
1656 		return (0);
1657 	if ((fbmask & FIMB4_PROTO) && filt->ff_flow.fi_proto != pkt->fi_proto)
1658 		return (0);
1659 	if ((fbmask & FIMB4_TOS) && filt->ff_flow.fi_tos !=
1660 	    (pkt->fi_tos & filt->ff_mask.mask_tos))
1661 		return (0);
1662 	if ((fbmask & FIMB4_GPI) && filt->ff_flow.fi_gpi != (pkt->fi_gpi))
1663 		return (0);
1664 	/* match */
1665 	return (1);
1666 }
1667 
1668 /*
1669  * filter matching function optimized for a common case that checks
1670  * only protocol and port numbers
1671  */
1672 static int
apply_ppfilter4(fbmask,filt,pkt)1673 apply_ppfilter4(fbmask, filt, pkt)
1674 	u_int32_t	fbmask;
1675 	struct flow_filter *filt;
1676 	struct flowinfo_in *pkt;
1677 {
1678 	if (filt->ff_flow.fi_family != AF_INET)
1679 		return (0);
1680 	if ((fbmask & FIMB4_SPORT) && filt->ff_flow.fi_sport != pkt->fi_sport)
1681 		return (0);
1682 	if ((fbmask & FIMB4_DPORT) && filt->ff_flow.fi_dport != pkt->fi_dport)
1683 		return (0);
1684 	if ((fbmask & FIMB4_PROTO) && filt->ff_flow.fi_proto != pkt->fi_proto)
1685 		return (0);
1686 	/* match */
1687 	return (1);
1688 }
1689 
1690 /*
1691  * filter matching function only for tos field.
1692  */
1693 static int
apply_tosfilter4(fbmask,filt,pkt)1694 apply_tosfilter4(fbmask, filt, pkt)
1695 	u_int32_t	fbmask;
1696 	struct flow_filter *filt;
1697 	struct flowinfo_in *pkt;
1698 {
1699 	if (filt->ff_flow.fi_family != AF_INET)
1700 		return (0);
1701 	if ((fbmask & FIMB4_TOS) && filt->ff_flow.fi_tos !=
1702 	    (pkt->fi_tos & filt->ff_mask.mask_tos))
1703 		return (0);
1704 	/* match */
1705 	return (1);
1706 }
1707 
1708 #ifdef INET6
1709 static int
apply_filter6(fbmask,filt,pkt)1710 apply_filter6(fbmask, filt, pkt)
1711 	u_int32_t	fbmask;
1712 	struct flow_filter6 *filt;
1713 	struct flowinfo_in6 *pkt;
1714 {
1715 	int i;
1716 
1717 	if (filt->ff_flow6.fi6_family != AF_INET6)
1718 		return (0);
1719 	if ((fbmask & FIMB6_FLABEL) &&
1720 	    filt->ff_flow6.fi6_flowlabel != pkt->fi6_flowlabel)
1721 		return (0);
1722 	if ((fbmask & FIMB6_PROTO) &&
1723 	    filt->ff_flow6.fi6_proto != pkt->fi6_proto)
1724 		return (0);
1725 	if ((fbmask & FIMB6_SPORT) &&
1726 	    filt->ff_flow6.fi6_sport != pkt->fi6_sport)
1727 		return (0);
1728 	if ((fbmask & FIMB6_DPORT) &&
1729 	    filt->ff_flow6.fi6_dport != pkt->fi6_dport)
1730 		return (0);
1731 	if (fbmask & FIMB6_SADDR) {
1732 		for (i = 0; i < 4; i++)
1733 			if (filt->ff_flow6.fi6_src.s6_addr32[i] !=
1734 			    (pkt->fi6_src.s6_addr32[i] &
1735 			     filt->ff_mask6.mask6_src.s6_addr32[i]))
1736 				return (0);
1737 	}
1738 	if (fbmask & FIMB6_DADDR) {
1739 		for (i = 0; i < 4; i++)
1740 			if (filt->ff_flow6.fi6_dst.s6_addr32[i] !=
1741 			    (pkt->fi6_dst.s6_addr32[i] &
1742 			     filt->ff_mask6.mask6_dst.s6_addr32[i]))
1743 				return (0);
1744 	}
1745 	if ((fbmask & FIMB6_TCLASS) &&
1746 	    filt->ff_flow6.fi6_tclass !=
1747 	    (pkt->fi6_tclass & filt->ff_mask6.mask6_tclass))
1748 		return (0);
1749 	if ((fbmask & FIMB6_GPI) &&
1750 	    filt->ff_flow6.fi6_gpi != pkt->fi6_gpi)
1751 		return (0);
1752 	/* match */
1753 	return (1);
1754 }
1755 #endif /* INET6 */
1756 
1757 /*
1758  *  filter handle:
1759  *	bit 20-28: index to the filter hash table
1760  *	bit  0-19: unique id in the hash bucket.
1761  */
1762 static u_long
get_filt_handle(classifier,i)1763 get_filt_handle(classifier, i)
1764 	struct acc_classifier *classifier;
1765 	int	i;
1766 {
1767 	static u_long handle_number = 1;
1768 	u_long 	handle;
1769 	struct acc_filter *afp;
1770 
1771 	while (1) {
1772 		handle = handle_number++ & 0x000fffff;
1773 
1774 		if (LIST_EMPTY(&classifier->acc_filters[i]))
1775 			break;
1776 
1777 		LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
1778 			if ((afp->f_handle & 0x000fffff) == handle)
1779 				break;
1780 		if (afp == NULL)
1781 			break;
1782 		/* this handle is already used, try again */
1783 	}
1784 
1785 	return ((i << 20) | handle);
1786 }
1787 
1788 /* convert filter handle to filter pointer */
1789 static struct acc_filter *
filth_to_filtp(classifier,handle)1790 filth_to_filtp(classifier, handle)
1791 	struct acc_classifier *classifier;
1792 	u_long handle;
1793 {
1794 	struct acc_filter *afp;
1795 	int	i;
1796 
1797 	i = ACC_GET_HINDEX(handle);
1798 
1799 	LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
1800 		if (afp->f_handle == handle)
1801 			return (afp);
1802 
1803 	return (NULL);
1804 }
1805 
1806 /* create flowinfo bitmask */
1807 static u_int32_t
filt2fibmask(filt)1808 filt2fibmask(filt)
1809 	struct flow_filter *filt;
1810 {
1811 	u_int32_t mask = 0;
1812 #ifdef INET6
1813 	struct flow_filter6 *filt6;
1814 #endif
1815 
1816 	switch (filt->ff_flow.fi_family) {
1817 	case AF_INET:
1818 		if (filt->ff_flow.fi_proto != 0)
1819 			mask |= FIMB4_PROTO;
1820 		if (filt->ff_flow.fi_tos != 0)
1821 			mask |= FIMB4_TOS;
1822 		if (filt->ff_flow.fi_dst.s_addr != 0)
1823 			mask |= FIMB4_DADDR;
1824 		if (filt->ff_flow.fi_src.s_addr != 0)
1825 			mask |= FIMB4_SADDR;
1826 		if (filt->ff_flow.fi_sport != 0)
1827 			mask |= FIMB4_SPORT;
1828 		if (filt->ff_flow.fi_dport != 0)
1829 			mask |= FIMB4_DPORT;
1830 		if (filt->ff_flow.fi_gpi != 0)
1831 			mask |= FIMB4_GPI;
1832 		break;
1833 #ifdef INET6
1834 	case AF_INET6:
1835 		filt6 = (struct flow_filter6 *)filt;
1836 
1837 		if (filt6->ff_flow6.fi6_proto != 0)
1838 			mask |= FIMB6_PROTO;
1839 		if (filt6->ff_flow6.fi6_tclass != 0)
1840 			mask |= FIMB6_TCLASS;
1841 		if (!IN6_IS_ADDR_UNSPECIFIED(&filt6->ff_flow6.fi6_dst))
1842 			mask |= FIMB6_DADDR;
1843 		if (!IN6_IS_ADDR_UNSPECIFIED(&filt6->ff_flow6.fi6_src))
1844 			mask |= FIMB6_SADDR;
1845 		if (filt6->ff_flow6.fi6_sport != 0)
1846 			mask |= FIMB6_SPORT;
1847 		if (filt6->ff_flow6.fi6_dport != 0)
1848 			mask |= FIMB6_DPORT;
1849 		if (filt6->ff_flow6.fi6_gpi != 0)
1850 			mask |= FIMB6_GPI;
1851 		if (filt6->ff_flow6.fi6_flowlabel != 0)
1852 			mask |= FIMB6_FLABEL;
1853 		break;
1854 #endif /* INET6 */
1855 	}
1856 	return (mask);
1857 }
1858 
1859 
1860 /*
1861  * helper functions to handle IPv4 fragments.
1862  * currently only in-sequence fragments are handled.
1863  *	- fragment info is cached in a LRU list.
1864  *	- when a first fragment is found, cache its flow info.
1865  *	- when a non-first fragment is found, lookup the cache.
1866  */
1867 
1868 struct ip4_frag {
1869     TAILQ_ENTRY(ip4_frag) ip4f_chain;
1870     char    ip4f_valid;
1871     u_short ip4f_id;
1872     struct flowinfo_in ip4f_info;
1873 };
1874 
1875 static TAILQ_HEAD(ip4f_list, ip4_frag) ip4f_list; /* IPv4 fragment cache */
1876 
1877 #define	IP4F_TABSIZE		16	/* IPv4 fragment cache size */
1878 
1879 
1880 static void
ip4f_cache(ip,fin)1881 ip4f_cache(ip, fin)
1882 	struct ip *ip;
1883 	struct flowinfo_in *fin;
1884 {
1885 	struct ip4_frag *fp;
1886 
1887 	if (TAILQ_EMPTY(&ip4f_list)) {
1888 		/* first time call, allocate fragment cache entries. */
1889 		if (ip4f_init() < 0)
1890 			/* allocation failed! */
1891 			return;
1892 	}
1893 
1894 	fp = ip4f_alloc();
1895 	fp->ip4f_id = ip->ip_id;
1896 	fp->ip4f_info.fi_proto = ip->ip_p;
1897 	fp->ip4f_info.fi_src.s_addr = ip->ip_src.s_addr;
1898 	fp->ip4f_info.fi_dst.s_addr = ip->ip_dst.s_addr;
1899 
1900 	/* save port numbers */
1901 	fp->ip4f_info.fi_sport = fin->fi_sport;
1902 	fp->ip4f_info.fi_dport = fin->fi_dport;
1903 	fp->ip4f_info.fi_gpi   = fin->fi_gpi;
1904 }
1905 
1906 static int
ip4f_lookup(ip,fin)1907 ip4f_lookup(ip, fin)
1908 	struct ip *ip;
1909 	struct flowinfo_in *fin;
1910 {
1911 	struct ip4_frag *fp;
1912 
1913 	for (fp = TAILQ_FIRST(&ip4f_list); fp != NULL && fp->ip4f_valid;
1914 	     fp = TAILQ_NEXT(fp, ip4f_chain))
1915 		if (ip->ip_id == fp->ip4f_id &&
1916 		    ip->ip_src.s_addr == fp->ip4f_info.fi_src.s_addr &&
1917 		    ip->ip_dst.s_addr == fp->ip4f_info.fi_dst.s_addr &&
1918 		    ip->ip_p == fp->ip4f_info.fi_proto) {
1919 
1920 			/* found the matching entry */
1921 			fin->fi_sport = fp->ip4f_info.fi_sport;
1922 			fin->fi_dport = fp->ip4f_info.fi_dport;
1923 			fin->fi_gpi   = fp->ip4f_info.fi_gpi;
1924 
1925 			if ((ntohs(ip->ip_off) & IP_MF) == 0)
1926 				/* this is the last fragment,
1927 				   release the entry. */
1928 				ip4f_free(fp);
1929 
1930 			return (1);
1931 		}
1932 
1933 	/* no matching entry found */
1934 	return (0);
1935 }
1936 
1937 static int
ip4f_init(void)1938 ip4f_init(void)
1939 {
1940 	struct ip4_frag *fp;
1941 	int i;
1942 
1943 	TAILQ_INIT(&ip4f_list);
1944 	for (i=0; i<IP4F_TABSIZE; i++) {
1945 		fp = malloc(sizeof(struct ip4_frag),
1946 		       M_DEVBUF, M_NOWAIT);
1947 		if (fp == NULL) {
1948 			printf("ip4f_init: can't alloc %dth entry!\n", i);
1949 			if (i == 0)
1950 				return (-1);
1951 			return (0);
1952 		}
1953 		fp->ip4f_valid = 0;
1954 		TAILQ_INSERT_TAIL(&ip4f_list, fp, ip4f_chain);
1955 	}
1956 	return (0);
1957 }
1958 
1959 static struct ip4_frag *
ip4f_alloc(void)1960 ip4f_alloc(void)
1961 {
1962 	struct ip4_frag *fp;
1963 
1964 	/* reclaim an entry at the tail, put it at the head */
1965 	fp = TAILQ_LAST(&ip4f_list, ip4f_list);
1966 	TAILQ_REMOVE(&ip4f_list, fp, ip4f_chain);
1967 	fp->ip4f_valid = 1;
1968 	TAILQ_INSERT_HEAD(&ip4f_list, fp, ip4f_chain);
1969 	return (fp);
1970 }
1971 
1972 static void
ip4f_free(fp)1973 ip4f_free(fp)
1974 	struct ip4_frag *fp;
1975 {
1976 	TAILQ_REMOVE(&ip4f_list, fp, ip4f_chain);
1977 	fp->ip4f_valid = 0;
1978 	TAILQ_INSERT_TAIL(&ip4f_list, fp, ip4f_chain);
1979 }
1980 
1981 #endif /* ALTQ3_CLFIER_COMPAT */
1982