* Remove the registration of a network protocol, which requires clearing * per-protocol fields across all workstreams, including freeing all mbufs in * the queues at time of unregister. All work in netisr is briefly suspended * while this takes place. */
| 632 | * while this takes place. |
| 633 | */ |
| 634 | void |
| 635 | netisr_unregister(const struct netisr_handler *nhp) |
| 636 | { |
| 637 | VNET_ITERATOR_DECL(vnet_iter); |
| 638 | struct netisr_work *npwp; |
| 639 | #ifdef INVARIANTS |
| 640 | const char *name; |
| 641 | #endif |
| 642 | u_int i, proto; |
| 643 | |
| 644 | proto = nhp->nh_proto; |
| 645 | #ifdef INVARIANTS |
| 646 | name = nhp->nh_name; |
| 647 | #endif |
| 648 | KASSERT(proto < NETISR_MAXPROT, |
| 649 | ("%s(%u): protocol too big for %s", __func__, proto, name)); |
| 650 | |
| 651 | NETISR_WLOCK(); |
| 652 | KASSERT(netisr_proto[proto].np_handler != NULL, |
| 653 | ("%s(%u): protocol not registered for %s", __func__, proto, |
| 654 | name)); |
| 655 | |
| 656 | #ifdef VIMAGE |
| 657 | VNET_LIST_RLOCK_NOSLEEP(); |
| 658 | VNET_FOREACH(vnet_iter) { |
| 659 | CURVNET_SET(vnet_iter); |
| 660 | V_netisr_enable[proto] = 0; |
| 661 | CURVNET_RESTORE(); |
| 662 | } |
| 663 | VNET_LIST_RUNLOCK_NOSLEEP(); |
| 664 | #endif |
| 665 | |
| 666 | netisr_proto[proto].np_name = NULL; |
| 667 | netisr_proto[proto].np_handler = NULL; |
| 668 | netisr_proto[proto].np_m2flow = NULL; |
| 669 | netisr_proto[proto].np_m2cpuid = NULL; |
| 670 | netisr_proto[proto].np_qlimit = 0; |
| 671 | netisr_proto[proto].np_policy = 0; |
| 672 | CPU_FOREACH(i) { |
| 673 | npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto]; |
| 674 | netisr_drain_proto(npwp); |
| 675 | bzero(npwp, sizeof(*npwp)); |
| 676 | } |
| 677 | NETISR_WUNLOCK(); |
| 678 | } |
| 679 | |
| 680 | #ifdef VIMAGE |
| 681 | void |
no test coverage detected