2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
17 #include "rx/rx_kcommon.h"
19 static struct protosw parent_proto; /* udp proto switch */
23 register struct mbuf *am;
25 register unsigned short *tsp;
28 register struct ip *ti;
33 struct sockaddr_in taddr;
36 int data_len, comp_sum;
37 /* make sure we have base ip and udp headers in first mbuf */
38 if (M_HASCL(am) || am->m_len < 28) {
39 am = m_pullup(am, 28);
43 hdr = (mtod(am, struct ip *))->ip_hl;
45 /* pull up more, the IP hdr is bigger than usual */
46 if (am->m_len < (8 + (hdr << 2))) {
47 am = m_pullup(am, 8 + (hdr << 2));
51 ti = mtod(am, struct ip *); /* recompute, since m_pullup allocates new mbuf */
52 tu = (struct udphdr *)(((char *)ti) + (hdr << 2)); /* skip ip hdr */
54 ti = mtod(am, struct ip *);
55 tu = (struct udphdr *)(((char *)ti) + 20); /* skip basic ip hdr */
58 /* now read the port out */
61 for (tsp = rxk_ports, i = 0; i < MAXRXPORTS; i++) {
68 /* if we get here, try to deliver packet to udp */
69 if (parent_proto.pr_input)
74 * the AIX version is complicated by the fact that the internet protocols
75 * are in a separate kernel extension, and they are unwilling to export their
76 * symbols to us. We can get there indirectly, however.
78 #include <net/netisr.h>
79 static struct ifqueue rxk_q; /* RXKluge queue */
80 static struct arpcom rxk_bogosity;
82 /* rxk_kpork - send pkt over to netwerk kporc for processing */
84 register struct mbuf *m;
86 find_input_type(0xdead, m, &rxk_bogosity, 0);
90 * AIX 4.3.3 changed the type of the second argument to
91 * ip_stripoptions(). The ip_stripoptions() prototype is in
92 * <netinet/proto_inet.h>. This header file also acquired a guard
93 * macro, _PROTO_INET_H_, at the same time. So we test for the guard
94 * macro to see which type we need to use for the second argument to
97 * This way we don't have to introduce a port just to compile AFS on AIX
101 #if defined(_PROTO_INET_H_) /* AIX 4.3.3 and presumably later */
102 #define STRIP_ARG2_TYPE unsigned long
103 #else /* AIX 4.3.2 and earlier */
104 #define STRIP_ARG2_TYPE struct mbuf *
108 ip_stripoptions(struct mbuf *m, STRIP_ARG2_TYPE mopt)
110 struct ip *ip = mtod(m, struct ip *);
112 register caddr_t opts;
115 olen = (ip->ip_hl << 2) - sizeof(struct ip);
116 opts = (caddr_t) (ip + 1);
117 i = m->m_len - (sizeof(struct ip) + olen);
118 memcpy(opts, opts + olen, (unsigned)i);
120 if (m->m_flags & M_PKTHDR)
121 m->m_pkthdr.len -= olen;
122 ip->ip_hl = sizeof(struct ip) >> 2;
125 /* rxk_RX_input - RX pkt input process */
127 register struct mbuf *am;
129 register unsigned short *tsp;
132 register struct ip *ti;
133 struct udpiphdr *tvu;
137 struct sockaddr_in taddr;
140 int data_len, comp_sum;
142 hdr = (ti = mtod(am, struct ip *))->ip_hl;
144 ip_stripoptions(am, 0); /* get rid of anything we don't need */
146 tu = (struct udphdr *)(((char *)ti) + 20);
148 * Make mbuf data length reflect UDP length.
149 * If not enough data to reflect UDP length, drop.
151 tvu = (struct udpiphdr *)ti;
152 tlen = ntohs((u_short) tvu->ui_ulen);
153 if ((int)ti->ip_len != tlen) {
154 if (tlen > (int)ti->ip_len) {
155 #ifdef RX_KERNEL_TRACE
156 int glockOwner = ISAFS_GLOCK();
159 afs_Trace3(afs_iclSetp, CM_TRACE_WASHERE, ICL_TYPE_STRING,
160 __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_INT32,
168 m_adj(am, tlen - (int)ti->ip_len);
170 /* deliver packet to rx */
171 taddr.sin_family = AF_INET; /* compute source address */
172 taddr.sin_port = tu->uh_sport;
173 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
174 /* handle the checksum. Note that this code damages the actual ip
175 * header (replacing it with the virtual one, which is the same size),
176 * so we must ensure we get everything out we need, first */
177 if (tu->uh_sum != 0) {
178 /* if the checksum is there, always check it. It's crazy not
179 * to, unless you can really be sure that your
180 * underlying network (and interfaces and drivers and
181 * DMA hardware, etc!) is error-free. First, fill
182 * in entire virtual ip header. */
183 #ifndef AFS_64BIT_KERNEL
188 tvu->ui_len = tvu->ui_ulen;
189 am->m_flags |= M_PKTHDR;
190 am->m_pkthdr.len = tlen;
191 #if !defined(AFS_AIX51_ENV) || !defined(AFS_64BIT_KERNEL)
192 if (in_cksum(am, sizeof(struct ip) + tlen)) {
193 /* checksum, including cksum field, doesn't come out 0, so
194 * this packet is bad */
195 #ifdef RX_KERNEL_TRACE
196 int glockOwner = ISAFS_GLOCK();
199 afs_Trace3(afs_iclSetp, CM_TRACE_WASHERE, ICL_TYPE_STRING,
200 __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_INT32,
210 { /* in_cksum() doesn't work correctly or the length is wrong? */
212 int glockOwner = ISAFS_GLOCK();
213 cksum = in_cksum(am, sizeof(struct ip) + tlen);
216 afs_Trace3(afs_iclSetp, CM_TRACE_WASHERE, ICL_TYPE_STRING,
217 __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_INT32,
227 * 28 is IP (20) + UDP (8) header. ulen includes
228 * udp header, and we *don't* tell RX about udp
229 * header either. So, we remove those 8 as well.
231 data_len = ntohs(tu->uh_ulen);
233 if (!(*rxk_GetPacketProc) (&phandle, data_len)) {
234 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
235 /* XXX should just increment counter here.. */
236 printf("rx: truncated UDP packet\n");
237 rxi_FreePacket(phandle);
239 (*rxk_PacketArrivalProc) (phandle, &taddr, rx_socket, data_len);
244 /* rxk_isr - RX Kluge Input Service Routine */
248 register struct mbuf *m;
249 IFQ_LOCK_DECL(); /* silly macro has trailing ';'. Sigh. */
251 IF_DEQUEUE(&rxk_q, m);
259 * UDP fast timer to raise events for all but Solaris and NCR.
260 * Called about 5 times per second (at unknown priority?). Must go to
261 * splnet or obtain global lock before touching anything significant.
269 /* do rx fasttimo processing here */
270 rxevent_RaiseEvents(&temp);
271 if (tproc = parent_proto.pr_fasttimo)
279 register struct protosw *pr;
280 extern struct protosw *pffindproto();
282 if (!rxk_initDone && (pr = pffindproto(AF_INET, IPPROTO_UDP, SOCK_DGRAM))) {
285 pr->pr_input = rxk_input;
286 pr->pr_fasttimo = rxk_fasttimo;
290 * don't bother with pr_drain and pr_ctlinput
291 * until we have something to do
293 rxk_q.ifq_maxlen = 128; /* obligatory XXX */
294 /* add pseudo pkt types as haque to get back onto net kproc */
296 (0xdead, NET_KPROC, rxk_isr, &rxk_q, NETISR_MAX - 1))
301 printf("\nAFS: no INTERNET protocol support found\n");
308 shutdown_rxkernel(void)
310 register struct protosw *pr;
312 extern struct protosw *pffindproto();
314 if (rxk_initDone && (pr = pffindproto(AF_INET, IPPROTO_UDP, SOCK_DGRAM))) {
318 for (i = 0; i < MAXRXPORTS; i++) {
321 soclose((struct socket *)rxk_portRocks[i]);
322 rxk_portRocks[i] = NULL;
329 /* osi_NetSend - send asize bytes at adata from asocket to host at addr.
331 * Now, why do we allocate a new buffer when we could theoretically use the one
332 * pointed to by adata? Because PRU_SEND returns after queueing the message,
333 * not after sending it. If the sender changes the data after queueing it,
334 * we'd see the already-queued data change. One attempt to fix this without
335 * adding a copy would be to have this function wait until the datagram is
336 * sent; however this doesn't work well. In particular, if a host is down, and
337 * an ARP fails to that host, this packet will be queued until the ARP request
338 * comes back, which could be hours later. We can't block in this routine that
339 * long, since it prevents RPC timeouts from happening.
341 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
342 * and just queue those. XXX
346 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
347 int nvec, afs_int32 asize, int istack)
349 register struct mbuf *tm, *um;
350 register afs_int32 code;
351 struct mbuf *top = 0;
352 register struct mbuf *m, **mp;
358 AFS_STATCNT(osi_NetSend);
359 #ifndef AFS_AIX41_ENV
361 * VRMIX has a version of sun's mclgetx() that works correctly with
362 * respect to mcopy(), so we can just dummy up the entire packet as
363 * an mbuf cluster, and pass it to the IP output routine (which will
364 * most likely have to frag it, but since mclgetx() has been fixed,
365 * will work ok). The only problem is that we have to wait until
366 * m_free() has been called on the cluster, to guarantee that we
367 * do not muck with it until it has gone out. We also must refrain
368 * from inadvertantly touching a piece of data that falls within the
369 * same cache line as any portion of the packet, if we have been lucky
370 * enough to be DMA-ing directly out from it.
371 * Certain IBM architects assure me that the rios is fast enough
372 * that the cost of the extra copy, as opposed to trying to
373 * DMA directly from the packet is barely worth my while,
374 * but I have a hard time accepting this.
376 * We can only use this code once we are passed in an indication of
377 * whether we are being called `process-synchronously' or not.
379 * of course, the packet must be pinned, which is currently true,
380 * but in future may not be.
385 tdata = dvec[0].iov_base;
386 tl = dvec[0].iov_len;
390 MGETHDR(m, M_DONTWAIT, MT_DATA);
393 MGET(m, M_DONTWAIT, MT_DATA);
397 /* can't get an mbuf, give up */
399 m_freem(top); /* free mbuf list we're building */
403 m->m_flags |= M_PKTHDR; /* XXX - temp */
405 m->m_pkthdr.rcvif = NULL;
409 * WARNING: the `4 * MLEN' is somewhat dubious. It is better than
410 * `NBPG', which may have no relation to `CLBYTES'. Also,
411 * `CLBYTES' may be so large that we never use clusters,
412 * resulting in far too many mbufs being used. It is often
413 * better to briefly use a cluster, even if we are only using a
414 * portion of it. Since we are on the xmit side, it shouldn't
415 * end up sitting on a queue for a potentially unbounded time
416 * (except perhaps if we are talking to ourself).
418 if (asize >= (MHLEN + 3 * MLEN)) {
419 MCLGET(m, M_DONTWAIT);
421 /* now compute usable size */
423 len = MIN(m->m_ext.ext_size, asize);
425 len = MIN(mlen, asize);
428 tpa = mtod(m, caddr_t);
434 memcpy(tpa, tdata, rlen);
439 top->m_pkthdr.len += rlen;
445 /* shouldn't come here! */
446 asize = 0; /* so we make progress toward completion */
449 tdata = dvec[i].iov_base;
450 tl = dvec[i].iov_len;
461 /* setup mbuf corresponding to destination address */
462 MGETHDR(um, M_DONTWAIT, MT_SONAME);
465 m_freem(top); /* free mbuf chain */
468 memcpy(mtod(um, caddr_t), addr, sizeof(*addr));
469 um->m_len = sizeof(*addr);
470 um->m_pkthdr.len = sizeof(*addr);
471 um->m_flags |= M_PKTHDR;
473 SOCKET_LOCK(asocket);
474 code = (*asocket->so_proto->pr_usrreq) (asocket, PRU_SEND, tm, um, 0);
475 SOCKET_UNLOCK(asocket);
483 #endif /* AFS_AIX41_ENV */