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