* Process packets associated with a workstream and protocol. For reasons of * fairness, we process up to one complete netisr queue at a time, moving the * queue to a stack-local queue for processing, but do not loop refreshing * from the global queue. The caller is responsible for deciding whether to * loop, and for setting the NWS_RUNNING flag. The passed workstream will be * locked on en
| 875 | * processing. The number of packets processed is returned. |
| 876 | */ |
| 877 | static u_int |
| 878 | netisr_process_workstream_proto(struct netisr_workstream *nwsp, u_int proto) |
| 879 | { |
| 880 | struct netisr_work local_npw, *npwp; |
| 881 | u_int handled; |
| 882 | struct mbuf *m; |
| 883 | |
| 884 | NETISR_LOCK_ASSERT(); |
| 885 | NWS_LOCK_ASSERT(nwsp); |
| 886 | |
| 887 | KASSERT(nwsp->nws_flags & NWS_RUNNING, |
| 888 | ("%s(%u): not running", __func__, proto)); |
| 889 | KASSERT(proto >= 0 && proto < NETISR_MAXPROT, |
| 890 | ("%s(%u): invalid proto\n", __func__, proto)); |
| 891 | |
| 892 | npwp = &nwsp->nws_work[proto]; |
| 893 | if (npwp->nw_len == 0) |
| 894 | return (0); |
| 895 | |
| 896 | /* |
| 897 | * Move the global work queue to a thread-local work queue. |
| 898 | * |
| 899 | * Notice that this means the effective maximum length of the queue |
| 900 | * is actually twice that of the maximum queue length specified in |
| 901 | * the protocol registration call. |
| 902 | */ |
| 903 | handled = npwp->nw_len; |
| 904 | local_npw = *npwp; |
| 905 | npwp->nw_head = NULL; |
| 906 | npwp->nw_tail = NULL; |
| 907 | npwp->nw_len = 0; |
| 908 | nwsp->nws_pendingbits &= ~(1 << proto); |
| 909 | NWS_UNLOCK(nwsp); |
| 910 | while ((m = local_npw.nw_head) != NULL) { |
| 911 | local_npw.nw_head = m->m_nextpkt; |
| 912 | m->m_nextpkt = NULL; |
| 913 | if (local_npw.nw_head == NULL) |
| 914 | local_npw.nw_tail = NULL; |
| 915 | local_npw.nw_len--; |
| 916 | VNET_ASSERT(m->m_pkthdr.rcvif != NULL, |
| 917 | ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m)); |
| 918 | CURVNET_SET(m->m_pkthdr.rcvif->if_vnet); |
| 919 | netisr_proto[proto].np_handler(m); |
| 920 | CURVNET_RESTORE(); |
| 921 | } |
| 922 | KASSERT(local_npw.nw_len == 0, |
| 923 | ("%s(%u): len %u", __func__, proto, local_npw.nw_len)); |
| 924 | if (netisr_proto[proto].np_drainedcpu) |
| 925 | netisr_proto[proto].np_drainedcpu(nwsp->nws_cpu); |
| 926 | NWS_LOCK(nwsp); |
| 927 | npwp->nw_handled += handled; |
| 928 | return (handled); |
| 929 | } |
| 930 | |
| 931 | /* |
| 932 | * SWI handler for netisr -- processes packets in a set of workstreams that |