netisr.c revision 111888
1111888Sjlemon/*- 2111888Sjlemon * Copyright (c) 2001,2002,2003 Jonathan Lemon <jlemon@FreeBSD.org> 3103781Sjake * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 4103781Sjake * All rights reserved. 5103781Sjake * 6103781Sjake * Redistribution and use in source and binary forms, with or without 7103781Sjake * modification, are permitted provided that the following conditions 8103781Sjake * are met: 9103781Sjake * 1. Redistributions of source code must retain the above copyright 10111888Sjlemon * notice, this list of conditions and the following disclaimer. 11103781Sjake * 2. Redistributions in binary form must reproduce the above copyright 12103781Sjake * notice, this list of conditions and the following disclaimer in the 13103781Sjake * documentation and/or other materials provided with the distribution. 14103781Sjake * 15111888Sjlemon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16111888Sjlemon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17111888Sjlemon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18111888Sjlemon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19111888Sjlemon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20111888Sjlemon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21111888Sjlemon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22111888Sjlemon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23111888Sjlemon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24111888Sjlemon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25111888Sjlemon * SUCH DAMAGE. 26103781Sjake * 27103781Sjake * $FreeBSD: head/sys/net/netisr.c 111888 2003-03-04 23:19:55Z jlemon $ 28103781Sjake */ 29103781Sjake 30103781Sjake#include <sys/param.h> 31111888Sjlemon#include <sys/bus.h> 32111888Sjlemon#include <sys/rtprio.h> 33103781Sjake#include <sys/systm.h> 34103781Sjake#include <sys/interrupt.h> 35103781Sjake#include <sys/kernel.h> 36111888Sjlemon#include <sys/kthread.h> 37111888Sjlemon#include <sys/lock.h> 38111888Sjlemon#include <sys/malloc.h> 39111888Sjlemon#include <sys/proc.h> 40111888Sjlemon#include <sys/random.h> 41111888Sjlemon#include <sys/resourcevar.h> 42111888Sjlemon#include <sys/sysctl.h> 43111888Sjlemon#include <sys/unistd.h> 44111888Sjlemon#include <machine/atomic.h> 45111888Sjlemon#include <machine/cpu.h> 46111888Sjlemon#include <machine/stdarg.h> 47103781Sjake 48111888Sjlemon#include <sys/mbuf.h> 49111888Sjlemon#include <sys/socket.h> 50111888Sjlemon 51111888Sjlemon#include <net/if.h> 52111888Sjlemon#include <net/if_types.h> 53111888Sjlemon#include <net/if_var.h> 54103781Sjake#include <net/netisr.h> 55103781Sjake 56111888Sjlemonvolatile unsigned int netisr; /* scheduling bits for network */ 57103781Sjake 58111888Sjlemonstruct netisr { 59111888Sjlemon netisr_t *ni_handler; 60111888Sjlemon struct ifqueue *ni_queue; 61111888Sjlemon} netisrs[32]; 62103781Sjake 63111888Sjlemonstatic struct mtx netisr_mtx; 64111888Sjlemonstatic void *net_ih; 65111888Sjlemon 66103781Sjakevoid 67103781Sjakelegacy_setsoftnet(void) 68103781Sjake{ 69103781Sjake swi_sched(net_ih, 0); 70103781Sjake} 71103781Sjake 72111888Sjlemonvoid 73111888Sjlemonnetisr_register(int num, netisr_t *handler, struct ifqueue *inq) 74103781Sjake{ 75103781Sjake 76111888Sjlemon KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), 77111888Sjlemon ("bad isr %d", num)); 78111888Sjlemon netisrs[num].ni_handler = handler; 79111888Sjlemon netisrs[num].ni_queue = inq; 80111888Sjlemon} 81111888Sjlemon 82111888Sjlemonvoid 83111888Sjlemonnetisr_unregister(int num) 84111888Sjlemon{ 85111888Sjlemon struct netisr *ni; 86111888Sjlemon int s; 87111888Sjlemon 88111888Sjlemon KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), 89111888Sjlemon ("bad isr %d", num)); 90111888Sjlemon ni = &netisrs[num]; 91111888Sjlemon ni->ni_handler = NULL; 92111888Sjlemon if (ni->ni_queue != NULL) { 93111888Sjlemon s = splimp(); 94111888Sjlemon IF_DRAIN(ni->ni_queue); 95111888Sjlemon splx(s); 96103781Sjake } 97103781Sjake} 98103781Sjake 99111888Sjlemonstruct isrstat { 100111888Sjlemon int isrs_count; /* dispatch count */ 101111888Sjlemon int isrs_directed; /* ...successfully dispatched */ 102111888Sjlemon int isrs_deferred; /* ...queued instead */ 103111888Sjlemon int isrs_bypassed; /* bypassed queued packets */ 104111888Sjlemon int isrs_queued; /* intentionally queueued */ 105111888Sjlemon int isrs_swi_count; /* swi_net handlers called */ 106111888Sjlemon}; 107111888Sjlemonstatic struct isrstat isrstat; 108111888Sjlemon 109111888SjlemonSYSCTL_NODE(_net, OID_AUTO, isr, CTLFLAG_RW, 0, "netisr counters"); 110111888Sjlemon 111111888Sjlemonstatic int netisr_enable = 0; 112111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, enable, CTLFLAG_RW, 113111888Sjlemon &netisr_enable, 0, "enable direct dispatch"); 114111888Sjlemon 115111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, count, CTLFLAG_RD, 116111888Sjlemon &isrstat.isrs_count, 0, ""); 117111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, directed, CTLFLAG_RD, 118111888Sjlemon &isrstat.isrs_directed, 0, ""); 119111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, deferred, CTLFLAG_RD, 120111888Sjlemon &isrstat.isrs_deferred, 0, ""); 121111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, bypassed, CTLFLAG_RD, 122111888Sjlemon &isrstat.isrs_bypassed, 0, ""); 123111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, queued, CTLFLAG_RD, 124111888Sjlemon &isrstat.isrs_queued, 0, ""); 125111888SjlemonSYSCTL_INT(_net_isr, OID_AUTO, swi_count, CTLFLAG_RD, 126111888Sjlemon &isrstat.isrs_swi_count, 0, ""); 127111888Sjlemon 128111888Sjlemon/* 129111888Sjlemon * Call the netisr directly instead of queueing the packet, if possible. 130111888Sjlemon * 131111888Sjlemon * Ideally, the permissibility of calling the routine would be determined 132111888Sjlemon * by checking if splnet() was asserted at the time the device interrupt 133111888Sjlemon * occurred; if so, this indicates that someone is in the network stack. 134111888Sjlemon * 135111888Sjlemon * However, bus_setup_intr uses INTR_TYPE_NET, which sets splnet before 136111888Sjlemon * calling the interrupt handler, so the previous mask is unavailable. 137111888Sjlemon * Approximate this by checking intr_nesting_level instead; if any SWI 138111888Sjlemon * handlers are running, the packet is queued instead. 139111888Sjlemon */ 140111888Sjlemonvoid 141111888Sjlemonnetisr_dispatch(int num, struct mbuf *m) 142103781Sjake{ 143111888Sjlemon struct netisr *ni; 144103781Sjake 145111888Sjlemon isrstat.isrs_count++; 146111888Sjlemon KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), 147111888Sjlemon ("bad isr %d", num)); 148111888Sjlemon ni = &netisrs[num]; 149111888Sjlemon KASSERT(ni->ni_queue != NULL, ("no queue for isr %d", num)); 150111888Sjlemon if (netisr_enable && mtx_trylock(&netisr_mtx)) { 151111888Sjlemon isrstat.isrs_directed++; 152111888Sjlemon /* 153111888Sjlemon * One slight problem here is that packets might bypass 154111888Sjlemon * each other in the stack, if an earlier one happened 155111888Sjlemon * to get stuck in the queue. 156111888Sjlemon * 157111888Sjlemon * we can either: 158111888Sjlemon * a. drain the queue before handling this packet, 159111888Sjlemon * b. fallback to queueing the packet, 160111888Sjlemon * c. sweep the issue under the rug and ignore it. 161111888Sjlemon * 162111888Sjlemon * Currently, we do c), and keep a rough event counter. 163111888Sjlemon */ 164111888Sjlemon if (_IF_QLEN(ni->ni_queue) > 0) 165111888Sjlemon isrstat.isrs_bypassed++; 166111888Sjlemon ni->ni_handler(m); 167111888Sjlemon mtx_unlock(&netisr_mtx); 168111888Sjlemon } else { 169111888Sjlemon isrstat.isrs_deferred++; 170111888Sjlemon if (IF_HANDOFF(ni->ni_queue, m, NULL)) 171111888Sjlemon schednetisr(num); 172103781Sjake } 173103781Sjake} 174103781Sjake 175111888Sjlemon/* 176111888Sjlemon * Same as above, but always queue. 177111888Sjlemon * This is either used in places where we are not confident that 178111888Sjlemon * direct dispatch is possible, or where queueing is required. 179111888Sjlemon */ 180111888Sjlemonint 181111888Sjlemonnetisr_queue(int num, struct mbuf *m) 182111888Sjlemon{ 183111888Sjlemon struct netisr *ni; 184111888Sjlemon 185111888Sjlemon KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), 186111888Sjlemon ("bad isr %d", num)); 187111888Sjlemon ni = &netisrs[num]; 188111888Sjlemon KASSERT(ni->ni_queue != NULL, ("no queue for isr %d", num)); 189111888Sjlemon isrstat.isrs_queued++; 190111888Sjlemon if (!IF_HANDOFF(ni->ni_queue, m, NULL)) 191111888Sjlemon return (0); 192111888Sjlemon schednetisr(num); 193111888Sjlemon return (1); 194111888Sjlemon} 195103781Sjake 196103781Sjakestatic void 197103781Sjakeswi_net(void *dummy) 198103781Sjake{ 199111888Sjlemon struct netisr *ni; 200111888Sjlemon struct mbuf *m; 201103781Sjake u_int bits; 202103781Sjake int i; 203103781Sjake#ifdef DEVICE_POLLING 204111888Sjlemon const int polling = 1; 205111888Sjlemon#else 206111888Sjlemon const int polling = 0; 207103781Sjake#endif 208111888Sjlemon 209111888Sjlemon mtx_lock(&netisr_mtx); 210111888Sjlemon do { 211111888Sjlemon bits = atomic_readandclear_int(&netisr); 212111888Sjlemon if (bits == 0) 213111888Sjlemon break; 214111888Sjlemon while ((i = ffs(bits)) != 0) { 215111888Sjlemon isrstat.isrs_swi_count++; 216111888Sjlemon i--; 217111888Sjlemon bits &= ~(1 << i); 218111888Sjlemon ni = &netisrs[i]; 219111888Sjlemon if (ni->ni_handler == NULL) { 220111888Sjlemon printf("swi_net: unregistered isr %d.\n", i); 221111888Sjlemon continue; 222111888Sjlemon } 223111888Sjlemon if (ni->ni_queue == NULL) 224111888Sjlemon ni->ni_handler(NULL); 225111888Sjlemon else 226111888Sjlemon for (;;) { 227111888Sjlemon IF_DEQUEUE(ni->ni_queue, m); 228111888Sjlemon if (m == NULL) 229111888Sjlemon break; 230111888Sjlemon ni->ni_handler(m); 231111888Sjlemon } 232111888Sjlemon } 233111888Sjlemon } while (polling); 234111888Sjlemon mtx_unlock(&netisr_mtx); 235103781Sjake} 236103781Sjake 237103781Sjakestatic void 238103781Sjakestart_netisr(void *dummy) 239103781Sjake{ 240103781Sjake 241111888Sjlemon mtx_init(&netisr_mtx, "netisr lock", NULL, MTX_DEF); 242103781Sjake if (swi_add(NULL, "net", swi_net, NULL, SWI_NET, 0, &net_ih)) 243103781Sjake panic("start_netisr"); 244103781Sjake} 245103781SjakeSYSINIT(start_netisr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_netisr, NULL) 246