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 */
22 rxk_input(struct mbuf *am, int hlen)
32 struct sockaddr_in taddr;
35 int data_len, comp_sum;
36 /* make sure we have base ip and udp headers in first mbuf */
37 if (M_HASCL(am) || am->m_len < 28) {
38 am = m_pullup(am, 28);
42 hdr = (mtod(am, struct ip *))->ip_hl;
44 /* pull up more, the IP hdr is bigger than usual */
45 if (am->m_len < (8 + (hdr << 2))) {
46 am = m_pullup(am, 8 + (hdr << 2));
50 ti = mtod(am, struct ip *); /* recompute, since m_pullup allocates new mbuf */
51 tu = (struct udphdr *)(((char *)ti) + (hdr << 2)); /* skip ip hdr */
53 ti = mtod(am, struct ip *);
54 tu = (struct udphdr *)(((char *)ti) + 20); /* skip basic ip hdr */
57 /* now read the port out */
60 for (tsp = rxk_ports, i = 0; i < MAXRXPORTS; i++) {
67 /* if we get here, try to deliver packet to udp */
68 if (parent_proto.pr_input)
73 * the AIX version is complicated by the fact that the internet protocols
74 * are in a separate kernel extension, and they are unwilling to export their
75 * symbols to us. We can get there indirectly, however.
77 #include <net/netisr.h>
78 static struct ifqueue rxk_q; /* RXKluge queue */
79 static struct arpcom rxk_bogosity;
81 /* rxk_kpork - send pkt over to netwerk kporc for processing */
82 rxk_kpork(struct mbuf *m)
84 find_input_type(0xdead, m, &rxk_bogosity, 0);
88 * AIX 4.3.3 changed the type of the second argument to
89 * ip_stripoptions(). The ip_stripoptions() prototype is in
90 * <netinet/proto_inet.h>. This header file also acquired a guard
91 * macro, _PROTO_INET_H_, at the same time. So we test for the guard
92 * macro to see which type we need to use for the second argument to
95 * This way we don't have to introduce a port just to compile AFS on AIX
99 #if defined(_PROTO_INET_H_) /* AIX 4.3.3 and presumably later */
100 #define STRIP_ARG2_TYPE unsigned long
101 #else /* AIX 4.3.2 and earlier */
102 #define STRIP_ARG2_TYPE struct mbuf *
106 ip_stripoptions(struct mbuf *m, STRIP_ARG2_TYPE mopt)
108 struct ip *ip = mtod(m, struct ip *);
113 olen = (ip->ip_hl << 2) - sizeof(struct ip);
114 opts = (caddr_t) (ip + 1);
115 i = m->m_len - (sizeof(struct ip) + olen);
116 memcpy(opts, opts + olen, (unsigned)i);
118 if (m->m_flags & M_PKTHDR)
119 m->m_pkthdr.len -= olen;
120 ip->ip_hl = sizeof(struct ip) >> 2;
123 /* rxk_RX_input - RX pkt input process */
124 rxk_RX_input(struct mbuf *am)
130 struct udpiphdr *tvu;
132 struct rx_packet *phandle;
134 struct sockaddr_in taddr;
137 int data_len, comp_sum;
139 hdr = (ti = mtod(am, struct ip *))->ip_hl;
141 ip_stripoptions(am, 0); /* get rid of anything we don't need */
143 tu = (struct udphdr *)(((char *)ti) + 20);
145 * Make mbuf data length reflect UDP length.
146 * If not enough data to reflect UDP length, drop.
148 tvu = (struct udpiphdr *)ti;
149 tlen = ntohs((u_short) tvu->ui_ulen);
150 if ((int)ti->ip_len != tlen) {
151 if (tlen > (int)ti->ip_len) {
152 #ifdef RX_KERNEL_TRACE
153 int glockOwner = ISAFS_GLOCK();
156 afs_Trace3(afs_iclSetp, CM_TRACE_WASHERE, ICL_TYPE_STRING,
157 __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_INT32,
165 m_adj(am, tlen - (int)ti->ip_len);
167 /* deliver packet to rx */
168 taddr.sin_family = AF_INET; /* compute source address */
169 taddr.sin_port = tu->uh_sport;
170 taddr.sin_addr.s_addr = ti->ip_src.s_addr;
171 /* handle the checksum. Note that this code damages the actual ip
172 * header (replacing it with the virtual one, which is the same size),
173 * so we must ensure we get everything out we need, first */
174 if (tu->uh_sum != 0) {
175 /* if the checksum is there, always check it. It's crazy not
176 * to, unless you can really be sure that your
177 * underlying network (and interfaces and drivers and
178 * DMA hardware, etc!) is error-free. First, fill
179 * in entire virtual ip header. */
180 #ifndef AFS_64BIT_KERNEL
185 tvu->ui_len = tvu->ui_ulen;
186 am->m_flags |= M_PKTHDR;
187 am->m_pkthdr.len = tlen;
188 #if !defined(AFS_AIX51_ENV) || !defined(AFS_64BIT_KERNEL)
189 if (in_cksum(am, sizeof(struct ip) + tlen)) {
190 /* checksum, including cksum field, doesn't come out 0, so
191 * this packet is bad */
192 #ifdef RX_KERNEL_TRACE
193 int glockOwner = ISAFS_GLOCK();
196 afs_Trace3(afs_iclSetp, CM_TRACE_WASHERE, ICL_TYPE_STRING,
197 __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_INT32,
207 { /* in_cksum() doesn't work correctly or the length is wrong? */
209 int glockOwner = ISAFS_GLOCK();
210 cksum = in_cksum(am, sizeof(struct ip) + tlen);
213 afs_Trace3(afs_iclSetp, CM_TRACE_WASHERE, ICL_TYPE_STRING,
214 __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_INT32,
224 * 28 is IP (20) + UDP (8) header. ulen includes
225 * udp header, and we *don't* tell RX about udp
226 * header either. So, we remove those 8 as well.
228 data_len = ntohs(tu->uh_ulen);
230 if (!(*rxk_GetPacketProc) (&phandle, data_len)) {
231 if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
232 /* XXX should just increment counter here.. */
233 printf("rx: truncated UDP packet\n");
234 rxi_FreePacket(phandle);
236 (*rxk_PacketArrivalProc) (phandle, &taddr, rx_socket, data_len);
241 /* rxk_isr - RX Kluge Input Service Routine */
246 IFQ_LOCK_DECL(); /* silly macro has trailing ';'. Sigh. */
248 IF_DEQUEUE(&rxk_q, m);
256 * UDP fast timer to raise events for all but Solaris and NCR.
257 * Called about 5 times per second (at unknown priority?). Must go to
258 * splnet or obtain global lock before touching anything significant.
263 void (*tproc) (void);
266 /* do rx fasttimo processing here */
267 rxevent_RaiseEvents(&temp);
268 if (tproc = parent_proto.pr_fasttimo)
277 extern struct protosw *pffindproto();
279 if (!rxk_initDone && (pr = pffindproto(AF_INET, IPPROTO_UDP, SOCK_DGRAM))) {
282 pr->pr_input = rxk_input;
283 pr->pr_fasttimo = rxk_fasttimo;
287 * don't bother with pr_drain and pr_ctlinput
288 * until we have something to do
290 rxk_q.ifq_maxlen = 128; /* obligatory XXX */
291 /* add pseudo pkt types as haque to get back onto net kproc */
293 (0xdead, NET_KPROC, rxk_isr, &rxk_q, NETISR_MAX - 1))
298 printf("\nAFS: no INTERNET protocol support found\n");
305 shutdown_rxkernel(void)
309 extern struct protosw *pffindproto();
311 if (rxk_initDone && (pr = pffindproto(AF_INET, IPPROTO_UDP, SOCK_DGRAM))) {
315 for (i = 0; i < MAXRXPORTS; i++) {
318 soclose((struct socket *)rxk_portRocks[i]);
319 rxk_portRocks[i] = NULL;
322 del_input_type(0xdead);
327 /* osi_NetSend - send asize bytes at adata from asocket to host at addr.
329 * Now, why do we allocate a new buffer when we could theoretically use the one
330 * pointed to by adata? Because PRU_SEND returns after queueing the message,
331 * not after sending it. If the sender changes the data after queueing it,
332 * we'd see the already-queued data change. One attempt to fix this without
333 * adding a copy would be to have this function wait until the datagram is
334 * sent; however this doesn't work well. In particular, if a host is down, and
335 * an ARP fails to that host, this packet will be queued until the ARP request
336 * comes back, which could be hours later. We can't block in this routine that
337 * long, since it prevents RPC timeouts from happening.
339 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
340 * and just queue those. XXX
344 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
345 int nvec, afs_int32 asize, int istack)
347 struct mbuf *tm, *um;
349 struct mbuf *top = 0;
350 struct mbuf *m, **mp;
356 AFS_STATCNT(osi_NetSend);
357 #ifndef AFS_AIX41_ENV
359 * VRMIX has a version of sun's mclgetx() that works correctly with
360 * respect to mcopy(), so we can just dummy up the entire packet as
361 * an mbuf cluster, and pass it to the IP output routine (which will
362 * most likely have to frag it, but since mclgetx() has been fixed,
363 * will work ok). The only problem is that we have to wait until
364 * m_free() has been called on the cluster, to guarantee that we
365 * do not muck with it until it has gone out. We also must refrain
366 * from inadvertantly touching a piece of data that falls within the
367 * same cache line as any portion of the packet, if we have been lucky
368 * enough to be DMA-ing directly out from it.
369 * Certain IBM architects assure me that the rios is fast enough
370 * that the cost of the extra copy, as opposed to trying to
371 * DMA directly from the packet is barely worth my while,
372 * but I have a hard time accepting this.
374 * We can only use this code once we are passed in an indication of
375 * whether we are being called `process-synchronously' or not.
377 * of course, the packet must be pinned, which is currently true,
378 * but in future may not be.
383 tdata = dvec[0].iov_base;
384 tl = dvec[0].iov_len;
388 MGETHDR(m, M_DONTWAIT, MT_DATA);
391 MGET(m, M_DONTWAIT, MT_DATA);
395 /* can't get an mbuf, give up */
397 m_freem(top); /* free mbuf list we're building */
401 m->m_flags |= M_PKTHDR; /* XXX - temp */
403 m->m_pkthdr.rcvif = NULL;
407 * WARNING: the `4 * MLEN' is somewhat dubious. It is better than
408 * `NBPG', which may have no relation to `CLBYTES'. Also,
409 * `CLBYTES' may be so large that we never use clusters,
410 * resulting in far too many mbufs being used. It is often
411 * better to briefly use a cluster, even if we are only using a
412 * portion of it. Since we are on the xmit side, it shouldn't
413 * end up sitting on a queue for a potentially unbounded time
414 * (except perhaps if we are talking to ourself).
416 if (asize >= (MHLEN + 3 * MLEN)) {
417 MCLGET(m, M_DONTWAIT);
419 /* now compute usable size */
421 len = MIN(m->m_ext.ext_size, asize);
423 len = MIN(mlen, asize);
426 tpa = mtod(m, caddr_t);
432 memcpy(tpa, tdata, rlen);
437 top->m_pkthdr.len += rlen;
443 /* shouldn't come here! */
444 asize = 0; /* so we make progress toward completion */
447 tdata = dvec[i].iov_base;
448 tl = dvec[i].iov_len;
459 /* setup mbuf corresponding to destination address */
460 MGETHDR(um, M_DONTWAIT, MT_SONAME);
463 m_freem(top); /* free mbuf chain */
466 memcpy(mtod(um, caddr_t), addr, sizeof(*addr));
467 um->m_len = sizeof(*addr);
468 um->m_pkthdr.len = sizeof(*addr);
469 um->m_flags |= M_PKTHDR;
471 SOCKET_LOCK(asocket);
472 code = (*asocket->so_proto->pr_usrreq) (asocket, PRU_SEND, tm, um, 0);
473 SOCKET_UNLOCK(asocket);
481 #endif /* AFS_AIX41_ENV */