2 * Copyright (c) 2003 Jeffrey Hsu
5 * $DragonFly: src/sys/netinet/ip_demux.c,v 1.6 2004/03/06 01:58:55 hsu Exp $
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>
19 #include <net/netisr.h>
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>
33 extern struct thread netisr_cpu[];
35 static struct thread tcp_thread[MAXCPU];
36 static struct thread udp_thread[MAXCPU];
39 * XXX when we remove the MP lock changes to this must be master-synchronized
41 static int ip_mthread_enable = 0;
42 SYSCTL_INT(_net_inet_ip, OID_AUTO, mthread_enable, CTLFLAG_RW,
43 &ip_mthread_enable, 0, "");
46 INP_MPORT_HASH(in_addr_t src, in_addr_t dst, in_port_t sport, in_port_t dport)
49 * Use low order bytes.
52 #if (BYTE_ORDER == LITTLE_ENDIAN)
53 KASSERT(ncpus2 < 256, ("need different hash function")); /* XXX JH */
54 return (((src >> 24) ^ (sport >> 8) ^ (dst >> 24) ^ (dport >> 8)) &
57 return ((src ^ sport ^ dst ^ dport) & ncpus2_mask);
62 * Map a packet to a protocol processing thread.
65 ip_mport(struct mbuf *m)
67 struct ip *ip = mtod(m, struct ip *);
75 if (ip_mthread_enable == 0)
76 return (&netisr_cpu[0].td_msgport);
78 if (m->m_len < sizeof(struct ip) &&
79 (m = m_pullup(m, sizeof(struct ip))) == NULL) {
80 ipstat.ips_toosmall++;
85 * XXX generic packet handling defrag on CPU 0 for now.
87 if (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK))
88 return (&netisr_cpu[0].td_msgport);
90 iphlen = ip->ip_hl << 2;
94 if (m->m_len < iphlen + sizeof(struct tcphdr) &&
95 (m = m_pullup(m, iphlen + sizeof(struct tcphdr))) == NULL) {
96 tcpstat.tcps_rcvshort++;
99 th = (struct tcphdr *)((caddr_t)ip + iphlen);
100 off = th->th_off << 2;
101 if (off < sizeof(struct tcphdr) || off > ip->ip_len) {
102 tcpstat.tcps_rcvbadoff++;
105 if (m->m_len < sizeof(struct ip) + off) {
106 m = m_pullup(m, sizeof(struct ip) + off);
108 tcpstat.tcps_rcvshort++;
111 ip = mtod(m, struct ip *);
112 th = (struct tcphdr *)((caddr_t)ip + iphlen);
115 cpu = INP_MPORT_HASH(ip->ip_src.s_addr, ip->ip_dst.s_addr,
116 th->th_sport, th->th_dport);
117 port = &tcp_thread[cpu].td_msgport;
120 if (m->m_len < iphlen + sizeof(struct udphdr) &&
121 (m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) {
122 udpstat.udps_hdrops++;
125 uh = (struct udphdr *)((caddr_t)ip + iphlen);
127 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
128 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
131 cpu = INP_MPORT_HASH(ip->ip_src.s_addr,
132 ip->ip_dst.s_addr, uh->uh_sport, uh->uh_dport);
134 port = &udp_thread[cpu].td_msgport;
137 port = &netisr_cpu[0].td_msgport;
140 KKASSERT(port->mp_putport != NULL);
146 * Map a TCP socket to a protocol processing thread.
149 tcp_soport(struct socket *so, struct sockaddr *nam)
154 * The following processing all take place on Protocol Thread 0:
155 * only bind() and connect() have a non-null nam parameter
156 * attach() has a null socket parameter
157 * Fast and slow timeouts pass in two NULLs
159 if (nam != NULL || so == NULL)
160 return (&tcp_thread[0].td_msgport);
163 * Already bound and connected. For TCP connections, the
164 * (faddr, fport, laddr, lport) association cannot change now.
166 * Note: T/TCP code needs some reorganization to fit into
170 if (!inp) /* connection reset by peer */
171 return (&tcp_thread[0].td_msgport);
174 * Rely on type-stable memory and check in protocol handler
175 * to fix race condition here w/ deallocation of inp. XXX JH
178 return (&tcp_thread[INP_MPORT_HASH(inp->inp_laddr.s_addr,
179 inp->inp_faddr.s_addr, inp->inp_lport,
180 inp->inp_fport)].td_msgport);
184 * Map a UDP socket to a protocol processing thread.
187 udp_soport(struct socket *so, struct sockaddr *nam)
192 * The following processing all take place on Protocol Thread 0:
193 * only bind() and connect() have a non-null nam parameter
194 * attach() has a null socket parameter
195 * Fast and slow timeouts pass in two NULLs
197 if (nam != NULL || so == NULL)
198 return (&udp_thread[0].td_msgport);
202 if (IN_MULTICAST(ntohl(inp->inp_laddr.s_addr)))
203 return (&udp_thread[0].td_msgport);
206 * Rely on type-stable memory and check in protocol handler
207 * to fix race condition here w/ deallocation of inp. XXX JH
210 return (&udp_thread[INP_MPORT_HASH(inp->inp_laddr.s_addr,
211 inp->inp_faddr.s_addr, inp->inp_lport,
212 inp->inp_fport)].td_msgport);
216 tcp_thread_init(void)
220 for (cpu = 0; cpu < ncpus2; cpu++) {
221 lwkt_create(netmsg_service_loop, NULL, NULL,
222 &tcp_thread[cpu], 0, cpu, "tcp_thread %d", cpu);
227 udp_thread_init(void)
231 for (cpu = 0; cpu < ncpus2; cpu++) {
232 lwkt_create(netmsg_service_loop, NULL, NULL,
233 &udp_thread[cpu], 0, cpu, "udp_thread %d", cpu);