1: /*
2: * Copyright (c) 2003 Jeffrey Hsu
3: * All rights reserved.
4: *
5: * $DragonFly: src/sys/netinet/ip_demux.c,v 1.4 2004/03/05 19:47:28 hsu 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: /*
49: * Use low order bytes.
50: * This particular hash function is only good for ncpus < 256.
51: */
52: #if (BYTE_ORDER == LITTLE_ENDIAN)
53: return (((src >> 24) ^ (sport >> 8) ^ (dst >> 24) ^ (dport >> 8)) &
54: ncpus2_mask);
55: #else
56: return ((src ^ sport ^ dst ^ dport) & ncpus2_mask);
57: #endif
58: }
59:
60: lwkt_port_t
61: ip_mport(struct mbuf *m)
62: {
63: struct ip *ip = mtod(m, struct ip *);
64: int hlen;
65: struct tcphdr *th;
66: struct udphdr *uh;
67: lwkt_port_t port;
68:
69: if (ip_mthread_enable == 0)
70: return (&netisr_cpu[0].td_msgport);
71:
72: if (m->m_len < sizeof(struct ip) &&
73: (m = m_pullup(m, sizeof(struct ip))) == NULL) {
74: ipstat.ips_toosmall++;
75: return (NULL);
76: }
77:
78: /*
79: * XXX generic packet handling defrag on CPU 0 for now.
80: */
81: if (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK))
82: return (&netisr_cpu[0].td_msgport);
83:
84: hlen = ip->ip_hl << 2;
85:
86: switch (ip->ip_p) {
87: case IPPROTO_TCP:
88: if (m->m_len < sizeof(struct tcpiphdr) &&
89: (m = m_pullup(m, sizeof(struct tcpiphdr))) == NULL) {
90: tcpstat.tcps_rcvshort++;
91: return (NULL);
92: }
93:
94: th = (struct tcphdr *)((caddr_t)ip + hlen);
95: port = &tcp_thread[INP_MPORT_HASH(ip->ip_src.s_addr,
96: ip->ip_dst.s_addr, th->th_sport, th->th_dport)].td_msgport;
97: break;
98: case IPPROTO_UDP:
99: if (m->m_len < hlen + sizeof(struct udphdr) &&
100: (m = m_pullup(m, hlen + sizeof(struct udphdr))) == NULL) {
101: udpstat.udps_hdrops++;
102: return (NULL);
103: }
104:
105: uh = (struct udphdr *)((caddr_t)ip + hlen);
106: port = &udp_thread[INP_MPORT_HASH(ip->ip_src.s_addr,
107: ip->ip_dst.s_addr, uh->uh_sport, uh->uh_dport)].td_msgport;
108: break;
109: default:
110: port = &netisr_cpu[0].td_msgport;
111: break;
112: }
113: KKASSERT(port->mp_putport != NULL);
114:
115: return (port);
116: }
117:
118: lwkt_port_t
119: tcp_soport(struct socket *so)
120: {
121: struct inpcb *inp = sotoinpcb(so);
122:
123: return (&tcp_thread[INP_MPORT_HASH(inp->inp_laddr.s_addr,
124: inp->inp_faddr.s_addr, inp->inp_lport, inp->inp_fport)].td_msgport);
125: }
126:
127: lwkt_port_t
128: udp_soport(struct socket *so)
129: {
130: struct inpcb *inp = sotoinpcb(so);
131:
132: return (&udp_thread[INP_MPORT_HASH(inp->inp_laddr.s_addr,
133: inp->inp_faddr.s_addr, inp->inp_lport, inp->inp_fport)].td_msgport);
134: }
135:
136: void
137: tcp_thread_init(void)
138: {
139: int cpu;
140:
141: for (cpu = 0; cpu < ncpus2; cpu++) {
142: lwkt_create(netmsg_service_loop, NULL, NULL,
143: &tcp_thread[cpu], 0, cpu, "tcp_thread %d", cpu);
144: }
145: }
146:
147: void
148: udp_thread_init(void)
149: {
150: int cpu;
151:
152: for (cpu = 0; cpu < ncpus2; cpu++) {
153: lwkt_create(netmsg_service_loop, NULL, NULL,
154: &udp_thread[cpu], 0, cpu, "udp_thread %d", cpu);
155: }
156: }