Merge from vendor branch TCPDUMP:
[dragonfly.git] / sys / net / netisr.c
1 /*-
2  * Copyright (c) 2003 Jeffrey Hsu
3  * Copyright (c) 2003 Jonathan Lemon
4  * Copyright (c) 2003 Matthew Dillon
5  *
6  * $DragonFly: src/sys/net/netisr.c,v 1.16 2004/04/24 06:55:57 hsu Exp $
7  */
8
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <sys/malloc.h>
13 #include <sys/msgport.h>
14 #include <sys/proc.h>
15 #include <sys/interrupt.h>
16 #include <sys/socket.h>
17 #include <sys/sysctl.h>
18 #include <net/if.h>
19 #include <net/if_var.h>
20 #include <net/netisr.h>
21 #include <machine/cpufunc.h>
22 #include <machine/ipl.h>
23
24 #include <sys/thread2.h>
25 #include <sys/msgport2.h>
26
27 static struct netisr netisrs[NETISR_MAX];
28
29 /* Per-CPU thread to handle any protocol.  */
30 struct thread netisr_cpu[MAXCPU];
31 lwkt_port netisr_afree_rport;
32
33 /*
34  * netisr_afree_rport replymsg function, only used to handle async
35  * messages which the sender has abandoned to their fate.
36  */
37 static void
38 netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
39 {
40     free(msg, M_LWKTMSG);
41 }
42
43 /*
44  * We must construct a custom putport function (which runs in the context
45  * of the message originator)
46  *
47  * Our custom putport must check for self-referential messages, which can
48  * occur when the so_upcall routine is called (e.g. nfs).  Self referential
49  * messages are executed synchronously.  However, we must panic if the message
50  * is not marked DONE on completion because the self-referential case cannot
51  * block without deadlocking.
52  */
53 int
54 netmsg_put_port(lwkt_port_t port, lwkt_msg_t lmsg)
55 {
56     int error;
57
58     if ((lmsg->ms_flags & MSGF_ASYNC) == 0 && port->mp_td == curthread) {
59         error = lmsg->ms_cmd.cm_func(lmsg);
60         if (error == EASYNC && (lmsg->ms_flags & MSGF_DONE) == 0)
61             panic("netmsg_put_port: self-referential deadlock on netport");
62         return(error);
63     } else {
64         return(lwkt_default_putport(port, lmsg));
65     }
66 }
67
68 static void
69 netisr_init(void)
70 {
71     int i;
72
73     /* Create default per-cpu threads for generic protocol handling. */
74     for (i = 0; i < ncpus; ++i) {
75         lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
76             "netisr_cpu %d", i);
77         netisr_cpu[i].td_msgport.mp_putport = netmsg_put_port;
78     }
79     lwkt_initport(&netisr_afree_rport, NULL);
80     netisr_afree_rport.mp_replyport = netisr_autofree_reply;
81 }
82
83 SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
84
85 void
86 netmsg_service_loop(void *arg)
87 {
88     struct netmsg *msg;
89
90     while ((msg = lwkt_waitport(&curthread->td_msgport, NULL)))
91         msg->nm_lmsg.ms_cmd.cm_func(&msg->nm_lmsg);
92 }
93
94 /*
95  * Call the netisr directly.
96  * Queueing may be done in the msg port layer at its discretion.
97  */
98 void
99 netisr_dispatch(int num, struct mbuf *m)
100 {
101     /* just queue it for now XXX JH */
102     netisr_queue(num, m);
103 }
104
105 /*
106  * Same as netisr_dispatch(), but always queue.
107  * This is either used in places where we are not confident that
108  * direct dispatch is possible, or where queueing is required.
109  */
110 int
111 netisr_queue(int num, struct mbuf *m)
112 {
113     struct netisr *ni;
114     struct netmsg_packet *pmsg;
115     lwkt_port_t port;
116
117     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
118         ("netisr_queue: bad isr %d", num));
119
120     ni = &netisrs[num];
121     if (ni->ni_handler == NULL) {
122         printf("netisr_queue: unregistered isr %d\n", num);
123         return (EIO);
124     }
125
126     if (!(port = ni->ni_mport(m)))
127         return (EIO);
128
129     /* use better message allocation system with limits later XXX JH */
130     pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_WAITOK);
131
132     lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
133                 lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
134     pmsg->nm_packet = m;
135     lwkt_sendmsg(port, &pmsg->nm_lmsg);
136     return (0);
137 }
138
139 void
140 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
141 {
142     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
143         ("netisr_register: bad isr %d", num));
144
145     netisrs[num].ni_mport = mportfn;
146     netisrs[num].ni_handler = handler;
147 }
148
149 int
150 netisr_unregister(int num)
151 {
152     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
153         ("unregister_netisr: bad isr number: %d\n", num));
154
155     /* XXX JH */
156     return (0);
157 }
158
159 /*
160  * Return message port for default handler thread on CPU 0.
161  */
162 lwkt_port_t
163 cpu0_portfn(struct mbuf *m)
164 {
165     return (&netisr_cpu[0].td_msgport);
166 }
167
168 /* ARGSUSED */
169 lwkt_port_t
170 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused,
171             int req __unused)
172 {
173     return (&netisr_cpu[0].td_msgport);
174 }
175
176 /*
177  * This function is used to call the netisr handler from the appropriate
178  * netisr thread for polling and other purposes.
179  */
180 void
181 schednetisr(int num)
182 {
183     struct netisr *ni = &netisrs[num];
184     struct netmsg *pmsg;
185     lwkt_port_t port = &netisr_cpu[0].td_msgport;
186
187     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
188         ("schednetisr: bad isr %d", num));
189
190     pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT);
191     if (pmsg) {
192         lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
193                     lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
194         lwkt_sendmsg(port, &pmsg->nm_lmsg);
195     }
196 }