This is a major cleanup of the LWKT message port code. The messaging code
[dragonfly.git] / sys / netinet / ip_demux.c
1 /*
2  * Copyright (c) 2003 Jeffrey Hsu
3  * All rights reserved.
4  *
5  * $DragonFly: src/sys/netinet/ip_demux.c,v 1.3 2003/11/20 06:05:31 dillon Exp $
6  */
7
8 #include "opt_inet.h"
9
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/kernel.h>
13 #include <sys/socket.h>
14 #include <sys/socketvar.h>
15 #include <sys/thread.h>
16 #include <sys/sysctl.h>
17
18 #include <net/if.h>
19 #include <net/netisr.h>
20
21 #include <netinet/in_systm.h>
22 #include <netinet/in.h>
23 #include <netinet/in_var.h>
24 #include <netinet/in_pcb.h>
25 #include <netinet/ip.h>
26 #include <netinet/ip_var.h>
27 #include <netinet/tcp.h>
28 #include <netinet/tcpip.h>
29 #include <netinet/tcp_var.h>
30 #include <netinet/udp.h>
31 #include <netinet/udp_var.h>
32
33 extern struct thread netisr_cpu[];
34
35 static struct thread tcp_thread[MAXCPU];
36 static struct thread udp_thread[MAXCPU];
37
38 /*
39  * XXX when we remove the MP lock changes to this must be master-synchronized
40  */
41 static int      ip_mthread_enable = 0;
42 SYSCTL_INT(_net_inet_ip, OID_AUTO, mthread_enable, CTLFLAG_RW,
43     &ip_mthread_enable, 0, "");
44
45 static int
46 INP_MPORT_HASH(in_addr_t src, in_addr_t dst, int sport, int dport)
47 {
48         int hv;
49
50         hv = (int)ntohl(src) ^ (int)ntohl(dst) ^ 
51                 (int)ntohs(sport) ^ (int)ntohs(dport);
52         return((hv & 0xFFFF) % ncpus);
53 }
54
55 lwkt_port_t
56 ip_mport(struct mbuf *m)
57 {
58         struct ip *ip = mtod(m, struct ip *);
59         int hlen;
60         struct tcphdr *th;
61         struct udphdr *uh;
62         lwkt_port_t port;
63
64         if (ip_mthread_enable == 0)
65                 return (&netisr_cpu[0].td_msgport);
66
67         if (m->m_len < sizeof(struct ip) &&
68             (m = m_pullup(m, sizeof(struct ip))) == NULL) {
69                 ipstat.ips_toosmall++;
70                 return (NULL);
71         }
72
73         /*
74          * XXX generic packet handling defrag on CPU 0 for now.
75          */
76         if (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK))
77                 return (&netisr_cpu[0].td_msgport);
78
79         hlen = ip->ip_hl << 2;
80
81         switch (ip->ip_p) {
82         case IPPROTO_TCP:
83                 if (m->m_len < sizeof(struct tcpiphdr) &&
84                     (m = m_pullup(m, sizeof(struct tcpiphdr))) == NULL) {
85                         tcpstat.tcps_rcvshort++;
86                         return (NULL);
87                 }
88
89                 th = (struct tcphdr *)((caddr_t)ip + hlen);
90                 port = &tcp_thread[INP_MPORT_HASH(ip->ip_src.s_addr,
91                     ip->ip_dst.s_addr, th->th_sport, th->th_dport)].td_msgport;
92                 break;
93         case IPPROTO_UDP:
94                 if (m->m_len < hlen + sizeof(struct udphdr) &&
95                     (m = m_pullup(m, hlen + sizeof(struct udphdr))) == NULL) {
96                         udpstat.udps_hdrops++;
97                         return (NULL);
98                 }
99
100                 uh = (struct udphdr *)((caddr_t)ip + hlen);
101                 port = &udp_thread[INP_MPORT_HASH(ip->ip_src.s_addr,
102                     ip->ip_dst.s_addr, uh->uh_sport, uh->uh_dport)].td_msgport;
103                 break;
104         default:
105                 port = &netisr_cpu[0].td_msgport;
106                 break;
107         }
108         KKASSERT(port->mp_putport != NULL);
109
110         return (port);
111 }
112
113 lwkt_port_t
114 tcp_soport(struct socket *so)
115 {
116         struct inpcb *inp = sotoinpcb(so);
117
118         return (&tcp_thread[INP_MPORT_HASH(inp->inp_laddr.s_addr,
119             inp->inp_faddr.s_addr, inp->inp_lport, inp->inp_fport)].td_msgport);
120 }
121
122 lwkt_port_t
123 udp_soport(struct socket *so)
124 {
125         struct inpcb *inp = sotoinpcb(so);
126
127         return (&udp_thread[INP_MPORT_HASH(inp->inp_laddr.s_addr,
128             inp->inp_faddr.s_addr, inp->inp_lport, inp->inp_fport)].td_msgport);
129 }
130
131 void
132 tcp_thread_init(void)
133 {
134         int cpu;
135
136         for (cpu = 0; cpu < ncpus; cpu++) {
137                 lwkt_create(netmsg_service_loop, NULL, NULL, 
138                         &tcp_thread[cpu], 0, cpu, "tcp_thread %d", cpu);
139         }
140 }
141
142 void
143 udp_thread_init(void)
144 {
145         int cpu;
146
147         for (cpu = 0; cpu < ncpus; cpu++) {
148                 lwkt_create(netmsg_service_loop, NULL, NULL,
149                         &udp_thread[cpu], 0, cpu, "udp_thread %d", cpu);
150         }
151 }