1 /*- 2 * Copyright (c) 2005 The DragonFly Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 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 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 3. Neither the name of The DragonFly Project nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific, prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifndef _NET_IFQ_VAR_H_ 33 #define _NET_IFQ_VAR_H_ 34 35 #ifndef _KERNEL 36 #error "This file should not be included by userland programs." 37 #endif 38 39 #ifndef _SYS_SYSTM_H_ 40 #include <sys/systm.h> 41 #endif 42 #ifndef _SYS_SERIALIZE_H_ 43 #include <sys/serialize.h> 44 #endif 45 #ifndef _SYS_MBUF_H_ 46 #include <sys/mbuf.h> 47 #endif 48 #ifndef _NET_IF_VAR_H_ 49 #include <net/if_var.h> 50 #endif 51 #ifndef _NET_ALTQ_IF_ALTQ_H_ 52 #include <net/altq/if_altq.h> 53 #endif 54 55 #define ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq) \ 56 KASSERT(ifsq_get_ifp((ifsq)) == (ifp) && \ 57 ifsq_get_index((ifsq)) == ALTQ_SUBQ_INDEX_DEFAULT, \ 58 ("not ifp's default subqueue")); 59 60 struct ifaltq; 61 struct ifaltq_subque; 62 63 /* 64 * Subqueue watchdog 65 */ 66 typedef void (*ifsq_watchdog_t)(struct ifaltq_subque *); 67 68 struct ifsubq_watchdog { 69 struct callout wd_callout; 70 int wd_timer; 71 struct ifaltq_subque *wd_subq; 72 ifsq_watchdog_t wd_watchdog; 73 }; 74 75 /* 76 * Support for "classic" ALTQ interfaces. 77 */ 78 int ifsq_classic_enqueue(struct ifaltq_subque *, struct mbuf *, 79 struct altq_pktattr *); 80 struct mbuf *ifsq_classic_dequeue(struct ifaltq_subque *, int); 81 int ifsq_classic_request(struct ifaltq_subque *, int, void *); 82 void ifq_set_classic(struct ifaltq *); 83 84 void ifq_set_maxlen(struct ifaltq *, int); 85 void ifq_set_methods(struct ifaltq *, altq_mapsubq_t, 86 ifsq_enqueue_t, ifsq_dequeue_t, ifsq_request_t); 87 int ifq_mapsubq_default(struct ifaltq *, int); 88 int ifq_mapsubq_modulo(struct ifaltq *, int); 89 90 void ifsq_devstart(struct ifaltq_subque *ifsq); 91 void ifsq_devstart_sched(struct ifaltq_subque *ifsq); 92 93 void ifsq_watchdog_init(struct ifsubq_watchdog *, 94 struct ifaltq_subque *, ifsq_watchdog_t); 95 void ifsq_watchdog_start(struct ifsubq_watchdog *); 96 void ifsq_watchdog_stop(struct ifsubq_watchdog *); 97 98 /* 99 * Dispatch a packet to an interface. 100 */ 101 int ifq_dispatch(struct ifnet *, struct mbuf *, 102 struct altq_pktattr *); 103 104 #ifdef ALTQ 105 106 static __inline int 107 ifq_is_enabled(struct ifaltq *_ifq) 108 { 109 return(_ifq->altq_flags & ALTQF_ENABLED); 110 } 111 112 static __inline int 113 ifq_is_attached(struct ifaltq *_ifq) 114 { 115 return(_ifq->altq_disc != NULL); 116 } 117 118 #else /* !ALTQ */ 119 120 static __inline int 121 ifq_is_enabled(struct ifaltq *_ifq) 122 { 123 return(0); 124 } 125 126 static __inline int 127 ifq_is_attached(struct ifaltq *_ifq) 128 { 129 return(0); 130 } 131 132 #endif /* ALTQ */ 133 134 static __inline int 135 ifq_is_ready(struct ifaltq *_ifq) 136 { 137 return(_ifq->altq_flags & ALTQF_READY); 138 } 139 140 static __inline void 141 ifq_set_ready(struct ifaltq *_ifq) 142 { 143 _ifq->altq_flags |= ALTQF_READY; 144 } 145 146 /* 147 * Subqueue lock must be held 148 */ 149 static __inline int 150 ifsq_enqueue_locked(struct ifaltq_subque *_ifsq, struct mbuf *_m, 151 struct altq_pktattr *_pa) 152 { 153 #ifdef ALTQ 154 if (!ifq_is_enabled(_ifsq->ifsq_altq)) 155 return ifsq_classic_enqueue(_ifsq, _m, _pa); 156 else 157 #endif 158 return _ifsq->ifsq_enqueue(_ifsq, _m, _pa); 159 } 160 161 static __inline int 162 ifsq_enqueue(struct ifaltq_subque *_ifsq, struct mbuf *_m, 163 struct altq_pktattr *_pa) 164 { 165 int _error; 166 167 ALTQ_SQ_LOCK(_ifsq); 168 _error = ifsq_enqueue_locked(_ifsq, _m, _pa); 169 ALTQ_SQ_UNLOCK(_ifsq); 170 return _error; 171 } 172 173 static __inline struct mbuf * 174 ifsq_dequeue(struct ifaltq_subque *_ifsq) 175 { 176 struct mbuf *_m; 177 178 ALTQ_SQ_LOCK(_ifsq); 179 if (_ifsq->ifsq_prepended != NULL) { 180 _m = _ifsq->ifsq_prepended; 181 _ifsq->ifsq_prepended = NULL; 182 ALTQ_SQ_CNTR_DEC(_ifsq, _m->m_pkthdr.len); 183 ALTQ_SQ_UNLOCK(_ifsq); 184 return _m; 185 } 186 187 #ifdef ALTQ 188 if (_ifsq->ifsq_altq->altq_tbr != NULL) 189 _m = tbr_dequeue(_ifsq, ALTDQ_REMOVE); 190 else if (!ifq_is_enabled(_ifsq->ifsq_altq)) 191 _m = ifsq_classic_dequeue(_ifsq, ALTDQ_REMOVE); 192 else 193 #endif 194 _m = _ifsq->ifsq_dequeue(_ifsq, ALTDQ_REMOVE); 195 ALTQ_SQ_UNLOCK(_ifsq); 196 return _m; 197 } 198 199 /* 200 * Subqueue lock must be held 201 */ 202 static __inline struct mbuf * 203 ifsq_poll_locked(struct ifaltq_subque *_ifsq) 204 { 205 if (_ifsq->ifsq_prepended != NULL) 206 return _ifsq->ifsq_prepended; 207 208 #ifdef ALTQ 209 if (_ifsq->ifsq_altq->altq_tbr != NULL) 210 return tbr_dequeue(_ifsq, ALTDQ_POLL); 211 else if (!ifq_is_enabled(_ifsq->ifsq_altq)) 212 return ifsq_classic_dequeue(_ifsq, ALTDQ_POLL); 213 else 214 #endif 215 return _ifsq->ifsq_dequeue(_ifsq, ALTDQ_POLL); 216 } 217 218 static __inline struct mbuf * 219 ifsq_poll(struct ifaltq_subque *_ifsq) 220 { 221 struct mbuf *_m; 222 223 ALTQ_SQ_LOCK(_ifsq); 224 _m = ifsq_poll_locked(_ifsq); 225 ALTQ_SQ_UNLOCK(_ifsq); 226 return _m; 227 } 228 229 static __inline int 230 ifsq_poll_pktlen(struct ifaltq_subque *_ifsq) 231 { 232 struct mbuf *_m; 233 int _len = 0; 234 235 ALTQ_SQ_LOCK(_ifsq); 236 237 _m = ifsq_poll_locked(_ifsq); 238 if (_m != NULL) { 239 M_ASSERTPKTHDR(_m); 240 _len = _m->m_pkthdr.len; 241 } 242 243 ALTQ_SQ_UNLOCK(_ifsq); 244 245 return _len; 246 } 247 248 /* 249 * Subqueue lock must be held 250 */ 251 static __inline void 252 ifsq_purge_locked(struct ifaltq_subque *_ifsq) 253 { 254 if (_ifsq->ifsq_prepended != NULL) { 255 ALTQ_SQ_CNTR_DEC(_ifsq, _ifsq->ifsq_prepended->m_pkthdr.len); 256 m_freem(_ifsq->ifsq_prepended); 257 _ifsq->ifsq_prepended = NULL; 258 } 259 260 #ifdef ALTQ 261 if (!ifq_is_enabled(_ifsq->ifsq_altq)) 262 ifsq_classic_request(_ifsq, ALTRQ_PURGE, NULL); 263 else 264 #endif 265 _ifsq->ifsq_request(_ifsq, ALTRQ_PURGE, NULL); 266 } 267 268 static __inline void 269 ifsq_purge(struct ifaltq_subque *_ifsq) 270 { 271 ALTQ_SQ_LOCK(_ifsq); 272 ifsq_purge_locked(_ifsq); 273 ALTQ_SQ_UNLOCK(_ifsq); 274 } 275 276 static __inline void 277 ifq_lock_all(struct ifaltq *_ifq) 278 { 279 int _q; 280 281 for (_q = 0; _q < _ifq->altq_subq_cnt; ++_q) 282 ALTQ_SQ_LOCK(&_ifq->altq_subq[_q]); 283 } 284 285 static __inline void 286 ifq_unlock_all(struct ifaltq *_ifq) 287 { 288 int _q; 289 290 for (_q = _ifq->altq_subq_cnt - 1; _q >= 0; --_q) 291 ALTQ_SQ_UNLOCK(&_ifq->altq_subq[_q]); 292 } 293 294 /* 295 * All of the subqueue locks must be held 296 */ 297 static __inline void 298 ifq_purge_all_locked(struct ifaltq *_ifq) 299 { 300 int _q; 301 302 for (_q = 0; _q < _ifq->altq_subq_cnt; ++_q) 303 ifsq_purge_locked(&_ifq->altq_subq[_q]); 304 } 305 306 static __inline void 307 ifq_purge_all(struct ifaltq *_ifq) 308 { 309 ifq_lock_all(_ifq); 310 ifq_purge_all_locked(_ifq); 311 ifq_unlock_all(_ifq); 312 } 313 314 static __inline void 315 ifq_classify(struct ifaltq *_ifq, struct mbuf *_m, uint8_t _af, 316 struct altq_pktattr *_pa) 317 { 318 #ifdef ALTQ 319 if (ifq_is_enabled(_ifq)) { 320 _pa->pattr_af = _af; 321 _pa->pattr_hdr = mtod(_m, caddr_t); 322 if (ifq_is_enabled(_ifq) && 323 (_ifq->altq_flags & ALTQF_CLASSIFY)) { 324 /* XXX default subqueue */ 325 struct ifaltq_subque *_ifsq = 326 &_ifq->altq_subq[ALTQ_SUBQ_INDEX_DEFAULT]; 327 328 ALTQ_SQ_LOCK(_ifsq); 329 if (ifq_is_enabled(_ifq) && 330 (_ifq->altq_flags & ALTQF_CLASSIFY)) 331 _ifq->altq_classify(_ifq, _m, _pa); 332 ALTQ_SQ_UNLOCK(_ifsq); 333 } 334 } 335 #endif 336 } 337 338 static __inline void 339 ifsq_prepend(struct ifaltq_subque *_ifsq, struct mbuf *_m) 340 { 341 ALTQ_SQ_LOCK(_ifsq); 342 KASSERT(_ifsq->ifsq_prepended == NULL, ("pending prepended mbuf")); 343 _ifsq->ifsq_prepended = _m; 344 ALTQ_SQ_CNTR_INC(_ifsq, _m->m_pkthdr.len); 345 ALTQ_SQ_UNLOCK(_ifsq); 346 } 347 348 /* 349 * Subqueue hardware serializer must be held 350 */ 351 static __inline void 352 ifsq_set_oactive(struct ifaltq_subque *_ifsq) 353 { 354 _ifsq->ifsq_hw_oactive = 1; 355 } 356 357 /* 358 * Subqueue hardware serializer must be held 359 */ 360 static __inline void 361 ifsq_clr_oactive(struct ifaltq_subque *_ifsq) 362 { 363 _ifsq->ifsq_hw_oactive = 0; 364 } 365 366 /* 367 * Subqueue hardware serializer must be held 368 */ 369 static __inline int 370 ifsq_is_oactive(const struct ifaltq_subque *_ifsq) 371 { 372 return _ifsq->ifsq_hw_oactive; 373 } 374 375 /* 376 * Hand a packet to the interface's default subqueue. 377 * 378 * The default subqueue hardware serializer must be held. If the 379 * subqueue hardware serializer is not held yet, ifq_dispatch() 380 * should be used to get better performance. 381 */ 382 static __inline int 383 ifq_handoff(struct ifnet *_ifp, struct mbuf *_m, struct altq_pktattr *_pa) 384 { 385 struct ifaltq_subque *_ifsq; 386 int _error; 387 int _qid = ALTQ_SUBQ_INDEX_DEFAULT; /* XXX default subqueue */ 388 389 _ifsq = &_ifp->if_snd.altq_subq[_qid]; 390 391 ASSERT_ALTQ_SQ_SERIALIZED_HW(_ifsq); 392 _error = ifsq_enqueue(_ifsq, _m, _pa); 393 if (_error == 0) { 394 IFNET_STAT_INC(_ifp, obytes, _m->m_pkthdr.len); 395 if (_m->m_flags & M_MCAST) 396 IFNET_STAT_INC(_ifp, omcasts, 1); 397 if (!ifsq_is_oactive(_ifsq)) 398 (*_ifp->if_start)(_ifp, _ifsq); 399 } else { 400 IFNET_STAT_INC(_ifp, oqdrops, 1); 401 } 402 return(_error); 403 } 404 405 static __inline int 406 ifsq_is_empty(const struct ifaltq_subque *_ifsq) 407 { 408 return(_ifsq->ifsq_len == 0); 409 } 410 411 /* 412 * Subqueue lock must be held 413 */ 414 static __inline int 415 ifsq_data_ready(struct ifaltq_subque *_ifsq) 416 { 417 #ifdef ALTQ 418 if (_ifsq->ifsq_altq->altq_tbr != NULL) 419 return (ifsq_poll_locked(_ifsq) != NULL); 420 else 421 #endif 422 return !ifsq_is_empty(_ifsq); 423 } 424 425 /* 426 * Subqueue lock must be held 427 */ 428 static __inline int 429 ifsq_is_started(const struct ifaltq_subque *_ifsq) 430 { 431 return _ifsq->ifsq_started; 432 } 433 434 /* 435 * Subqueue lock must be held 436 */ 437 static __inline void 438 ifsq_set_started(struct ifaltq_subque *_ifsq) 439 { 440 _ifsq->ifsq_started = 1; 441 } 442 443 /* 444 * Subqueue lock must be held 445 */ 446 static __inline void 447 ifsq_clr_started(struct ifaltq_subque *_ifsq) 448 { 449 _ifsq->ifsq_started = 0; 450 } 451 452 static __inline struct ifsubq_stage * 453 ifsq_get_stage(struct ifaltq_subque *_ifsq, int _cpuid) 454 { 455 return &_ifsq->ifsq_stage[_cpuid]; 456 } 457 458 static __inline int 459 ifsq_get_cpuid(const struct ifaltq_subque *_ifsq) 460 { 461 return _ifsq->ifsq_cpuid; 462 } 463 464 static __inline void 465 ifsq_set_cpuid(struct ifaltq_subque *_ifsq, int _cpuid) 466 { 467 KASSERT(_cpuid >= 0 && _cpuid < ncpus, 468 ("invalid ifsq_cpuid %d", _cpuid)); 469 _ifsq->ifsq_cpuid = _cpuid; 470 } 471 472 static __inline struct lwkt_msg * 473 ifsq_get_ifstart_lmsg(struct ifaltq_subque *_ifsq, int _cpuid) 474 { 475 return &_ifsq->ifsq_ifstart_nmsg[_cpuid].lmsg; 476 } 477 478 static __inline int 479 ifsq_get_index(const struct ifaltq_subque *_ifsq) 480 { 481 return _ifsq->ifsq_index; 482 } 483 484 static __inline void 485 ifsq_set_priv(struct ifaltq_subque *_ifsq, void *_priv) 486 { 487 _ifsq->ifsq_hw_priv = _priv; 488 } 489 490 static __inline void * 491 ifsq_get_priv(const struct ifaltq_subque *_ifsq) 492 { 493 return _ifsq->ifsq_hw_priv; 494 } 495 496 static __inline struct ifnet * 497 ifsq_get_ifp(const struct ifaltq_subque *_ifsq) 498 { 499 return _ifsq->ifsq_ifp; 500 } 501 502 static __inline void 503 ifsq_set_hw_serialize(struct ifaltq_subque *_ifsq, 504 struct lwkt_serialize *_hwslz) 505 { 506 KASSERT(_hwslz != NULL, ("NULL hw serialize")); 507 KASSERT(_ifsq->ifsq_hw_serialize == NULL, 508 ("hw serialize has been setup")); 509 _ifsq->ifsq_hw_serialize = _hwslz; 510 } 511 512 static __inline void 513 ifsq_serialize_hw(struct ifaltq_subque *_ifsq) 514 { 515 lwkt_serialize_enter(_ifsq->ifsq_hw_serialize); 516 } 517 518 static __inline void 519 ifsq_deserialize_hw(struct ifaltq_subque *_ifsq) 520 { 521 lwkt_serialize_exit(_ifsq->ifsq_hw_serialize); 522 } 523 524 static __inline int 525 ifsq_tryserialize_hw(struct ifaltq_subque *_ifsq) 526 { 527 return lwkt_serialize_try(_ifsq->ifsq_hw_serialize); 528 } 529 530 static __inline struct ifaltq_subque * 531 ifq_get_subq_default(const struct ifaltq *_ifq) 532 { 533 return &_ifq->altq_subq[ALTQ_SUBQ_INDEX_DEFAULT]; 534 } 535 536 static __inline struct ifaltq_subque * 537 ifq_get_subq(const struct ifaltq *_ifq, int _idx) 538 { 539 KASSERT(_idx >= 0 && _idx < _ifq->altq_subq_cnt, 540 ("invalid qid %d", _idx)); 541 return &_ifq->altq_subq[_idx]; 542 } 543 544 static __inline struct ifaltq_subque * 545 ifq_map_subq(struct ifaltq *_ifq, int _cpuid) 546 { 547 int _idx = _ifq->altq_mapsubq(_ifq, _cpuid); 548 return ifq_get_subq(_ifq, _idx); 549 } 550 551 static __inline void 552 ifq_set_subq_cnt(struct ifaltq *_ifq, int _cnt) 553 { 554 _ifq->altq_subq_cnt = _cnt; 555 } 556 557 static __inline void 558 ifq_set_subq_divisor(struct ifaltq *_ifq, uint32_t _divisor) 559 { 560 561 KASSERT(_divisor > 0, ("invalid divisor %u", _divisor)); 562 KASSERT(_divisor <= _ifq->altq_subq_cnt, 563 ("invalid divisor %u, max %d", _divisor, _ifq->altq_subq_cnt)); 564 _ifq->altq_subq_mappriv = _divisor; 565 } 566 567 /* COMPAT */ 568 static __inline int 569 ifq_is_oactive(const struct ifaltq *_ifq) 570 { 571 return ifsq_is_oactive(ifq_get_subq_default(_ifq)); 572 } 573 574 /* COMPAT */ 575 static __inline void 576 ifq_set_oactive(struct ifaltq *_ifq) 577 { 578 ifsq_set_oactive(ifq_get_subq_default(_ifq)); 579 } 580 581 /* COMPAT */ 582 static __inline void 583 ifq_clr_oactive(struct ifaltq *_ifq) 584 { 585 ifsq_clr_oactive(ifq_get_subq_default(_ifq)); 586 } 587 588 /* COMPAT */ 589 static __inline int 590 ifq_is_empty(struct ifaltq *_ifq) 591 { 592 return ifsq_is_empty(ifq_get_subq_default(_ifq)); 593 } 594 595 /* COMPAT */ 596 static __inline void 597 ifq_purge(struct ifaltq *_ifq) 598 { 599 ifsq_purge(ifq_get_subq_default(_ifq)); 600 } 601 602 /* COMPAT */ 603 static __inline struct mbuf * 604 ifq_dequeue(struct ifaltq *_ifq) 605 { 606 return ifsq_dequeue(ifq_get_subq_default(_ifq)); 607 } 608 609 /* COMPAT */ 610 static __inline void 611 ifq_prepend(struct ifaltq *_ifq, struct mbuf *_m) 612 { 613 ifsq_prepend(ifq_get_subq_default(_ifq), _m); 614 } 615 616 /* COMPAT */ 617 static __inline void 618 ifq_set_cpuid(struct ifaltq *_ifq, int _cpuid) 619 { 620 KASSERT(_ifq->altq_subq_cnt == 1, 621 ("invalid subqueue count %d", _ifq->altq_subq_cnt)); 622 ifsq_set_cpuid(ifq_get_subq_default(_ifq), _cpuid); 623 } 624 625 /* COMPAT */ 626 static __inline void 627 ifq_set_hw_serialize(struct ifaltq *_ifq, struct lwkt_serialize *_hwslz) 628 { 629 KASSERT(_ifq->altq_subq_cnt == 1, 630 ("invalid subqueue count %d", _ifq->altq_subq_cnt)); 631 ifsq_set_hw_serialize(ifq_get_subq_default(_ifq), _hwslz); 632 } 633 634 #endif /* _NET_IFQ_VAR_H_ */ 635