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 } 152