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"
15 #include "rx/rx_kcommon.h"
17 static struct protosw parent_proto
; /* udp proto switch */
20 rxk_input(struct mbuf
*am
, int hlen
)
30 struct sockaddr_in taddr
;
33 int data_len
, comp_sum
;
34 /* make sure we have base ip and udp headers in first mbuf */
35 if (M_HASCL(am
) || am
->m_len
< 28) {
36 am
= m_pullup(am
, 28);
40 hdr
= (mtod(am
, struct ip
*))->ip_hl
;
42 /* pull up more, the IP hdr is bigger than usual */
43 if (am
->m_len
< (8 + (hdr
<< 2))) {
44 am
= m_pullup(am
, 8 + (hdr
<< 2));
48 ti
= mtod(am
, struct ip
*); /* recompute, since m_pullup allocates new mbuf */
49 tu
= (struct udphdr
*)(((char *)ti
) + (hdr
<< 2)); /* skip ip hdr */
51 ti
= mtod(am
, struct ip
*);
52 tu
= (struct udphdr
*)(((char *)ti
) + 20); /* skip basic ip hdr */
55 /* now read the port out */
58 for (tsp
= rxk_ports
, i
= 0; i
< MAXRXPORTS
; i
++) {
65 /* if we get here, try to deliver packet to udp */
66 if (parent_proto
.pr_input
)
71 * the AIX version is complicated by the fact that the internet protocols
72 * are in a separate kernel extension, and they are unwilling to export their
73 * symbols to us. We can get there indirectly, however.
75 #include <net/netisr.h>
76 static struct ifqueue rxk_q
; /* RXKluge queue */
77 static struct arpcom rxk_bogosity
;
79 /* rxk_kpork - send pkt over to netwerk kporc for processing */
80 rxk_kpork(struct mbuf
*m
)
82 find_input_type(0xdead, m
, &rxk_bogosity
, 0);
86 * AIX 4.3.3 changed the type of the second argument to
87 * ip_stripoptions(). The ip_stripoptions() prototype is in
88 * <netinet/proto_inet.h>. This header file also acquired a guard
89 * macro, _PROTO_INET_H_, at the same time. So we test for the guard
90 * macro to see which type we need to use for the second argument to
93 * This way we don't have to introduce a port just to compile AFS on AIX
97 #if defined(_PROTO_INET_H_) /* AIX 4.3.3 and presumably later */
98 #define STRIP_ARG2_TYPE unsigned long
99 #else /* AIX 4.3.2 and earlier */
100 #define STRIP_ARG2_TYPE struct mbuf *
104 ip_stripoptions(struct mbuf
*m
, STRIP_ARG2_TYPE mopt
)
106 struct ip
*ip
= mtod(m
, struct ip
*);
111 olen
= (ip
->ip_hl
<< 2) - sizeof(struct ip
);
112 opts
= (caddr_t
) (ip
+ 1);
113 i
= m
->m_len
- (sizeof(struct ip
) + olen
);
114 memcpy(opts
, opts
+ olen
, (unsigned)i
);
116 if (m
->m_flags
& M_PKTHDR
)
117 m
->m_pkthdr
.len
-= olen
;
118 ip
->ip_hl
= sizeof(struct ip
) >> 2;
121 /* rxk_RX_input - RX pkt input process */
122 rxk_RX_input(struct mbuf
*am
)
128 struct udpiphdr
*tvu
;
130 struct rx_packet
*phandle
;
132 struct sockaddr_in taddr
;
135 int data_len
, comp_sum
;
137 hdr
= (ti
= mtod(am
, struct ip
*))->ip_hl
;
139 ip_stripoptions(am
, 0); /* get rid of anything we don't need */
141 tu
= (struct udphdr
*)(((char *)ti
) + 20);
143 * Make mbuf data length reflect UDP length.
144 * If not enough data to reflect UDP length, drop.
146 tvu
= (struct udpiphdr
*)ti
;
147 tlen
= ntohs((u_short
) tvu
->ui_ulen
);
148 if ((int)ti
->ip_len
!= tlen
) {
149 if (tlen
> (int)ti
->ip_len
) {
150 #ifdef RX_KERNEL_TRACE
151 int glockOwner
= ISAFS_GLOCK();
154 afs_Trace3(afs_iclSetp
, CM_TRACE_WASHERE
, ICL_TYPE_STRING
,
155 __FILE__
, ICL_TYPE_INT32
, __LINE__
, ICL_TYPE_INT32
,
163 m_adj(am
, tlen
- (int)ti
->ip_len
);
165 /* deliver packet to rx */
166 taddr
.sin_family
= AF_INET
; /* compute source address */
167 taddr
.sin_port
= tu
->uh_sport
;
168 taddr
.sin_addr
.s_addr
= ti
->ip_src
.s_addr
;
169 /* handle the checksum. Note that this code damages the actual ip
170 * header (replacing it with the virtual one, which is the same size),
171 * so we must ensure we get everything out we need, first */
172 if (tu
->uh_sum
!= 0) {
173 /* if the checksum is there, always check it. It's crazy not
174 * to, unless you can really be sure that your
175 * underlying network (and interfaces and drivers and
176 * DMA hardware, etc!) is error-free. First, fill
177 * in entire virtual ip header. */
178 #ifndef AFS_64BIT_KERNEL
183 tvu
->ui_len
= tvu
->ui_ulen
;
184 am
->m_flags
|= M_PKTHDR
;
185 am
->m_pkthdr
.len
= tlen
;
186 #if !defined(AFS_AIX51_ENV) || !defined(AFS_64BIT_KERNEL)
187 if (in_cksum(am
, sizeof(struct ip
) + tlen
)) {
188 /* checksum, including cksum field, doesn't come out 0, so
189 * this packet is bad */
190 #ifdef RX_KERNEL_TRACE
191 int glockOwner
= ISAFS_GLOCK();
194 afs_Trace3(afs_iclSetp
, CM_TRACE_WASHERE
, ICL_TYPE_STRING
,
195 __FILE__
, ICL_TYPE_INT32
, __LINE__
, ICL_TYPE_INT32
,
205 { /* in_cksum() doesn't work correctly or the length is wrong? */
207 int glockOwner
= ISAFS_GLOCK();
208 cksum
= in_cksum(am
, sizeof(struct ip
) + tlen
);
211 afs_Trace3(afs_iclSetp
, CM_TRACE_WASHERE
, ICL_TYPE_STRING
,
212 __FILE__
, ICL_TYPE_INT32
, __LINE__
, ICL_TYPE_INT32
,
222 * 28 is IP (20) + UDP (8) header. ulen includes
223 * udp header, and we *don't* tell RX about udp
224 * header either. So, we remove those 8 as well.
226 data_len
= ntohs(tu
->uh_ulen
);
228 if (!(*rxk_GetPacketProc
) (&phandle
, data_len
)) {
229 if (rx_mb_to_packet(am
, m_freem
, 28, data_len
, phandle
)) {
230 /* XXX should just increment counter here.. */
231 printf("rx: truncated UDP packet\n");
232 rxi_FreePacket(phandle
);
234 (*rxk_PacketArrivalProc
) (phandle
, &taddr
, rx_socket
, data_len
);
239 /* rxk_isr - RX Kluge Input Service Routine */
244 IFQ_LOCK_DECL(); /* silly macro has trailing ';'. Sigh. */
246 IF_DEQUEUE(&rxk_q
, m
);
254 * UDP fast timer to raise events for all but Solaris and NCR.
255 * Called about 5 times per second (at unknown priority?). Must go to
256 * splnet or obtain global lock before touching anything significant.
261 void (*tproc
) (void);
264 /* do rx fasttimo processing here */
265 rxevent_RaiseEvents(&temp
);
266 if (tproc
= parent_proto
.pr_fasttimo
)
275 extern struct protosw
*pffindproto();
277 if (!rxk_initDone
&& (pr
= pffindproto(AF_INET
, IPPROTO_UDP
, SOCK_DGRAM
))) {
280 pr
->pr_input
= rxk_input
;
281 pr
->pr_fasttimo
= rxk_fasttimo
;
285 * don't bother with pr_drain and pr_ctlinput
286 * until we have something to do
288 rxk_q
.ifq_maxlen
= 128; /* obligatory XXX */
289 /* add pseudo pkt types as haque to get back onto net kproc */
291 (0xdead, NET_KPROC
, rxk_isr
, &rxk_q
, NETISR_MAX
- 1))
296 printf("\nAFS: no INTERNET protocol support found\n");
303 shutdown_rxkernel(void)
307 extern struct protosw
*pffindproto();
309 if (rxk_initDone
&& (pr
= pffindproto(AF_INET
, IPPROTO_UDP
, SOCK_DGRAM
))) {
313 for (i
= 0; i
< MAXRXPORTS
; i
++) {
316 soclose((struct socket
*)rxk_portRocks
[i
]);
317 rxk_portRocks
[i
] = NULL
;
320 del_input_type(0xdead);
325 /* osi_NetSend - send asize bytes at adata from asocket to host at addr.
327 * Now, why do we allocate a new buffer when we could theoretically use the one
328 * pointed to by adata? Because PRU_SEND returns after queueing the message,
329 * not after sending it. If the sender changes the data after queueing it,
330 * we'd see the already-queued data change. One attempt to fix this without
331 * adding a copy would be to have this function wait until the datagram is
332 * sent; however this doesn't work well. In particular, if a host is down, and
333 * an ARP fails to that host, this packet will be queued until the ARP request
334 * comes back, which could be hours later. We can't block in this routine that
335 * long, since it prevents RPC timeouts from happening.
337 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
338 * and just queue those. XXX
342 osi_NetSend(osi_socket asocket
, struct sockaddr_in
*addr
, struct iovec
*dvec
,
343 int nvec
, afs_int32 asize
, int istack
)
345 struct mbuf
*tm
, *um
;
347 struct mbuf
*top
= 0;
348 struct mbuf
*m
, **mp
;
354 AFS_STATCNT(osi_NetSend
);
355 #ifndef AFS_AIX41_ENV
357 * VRMIX has a version of sun's mclgetx() that works correctly with
358 * respect to mcopy(), so we can just dummy up the entire packet as
359 * an mbuf cluster, and pass it to the IP output routine (which will
360 * most likely have to frag it, but since mclgetx() has been fixed,
361 * will work ok). The only problem is that we have to wait until
362 * m_free() has been called on the cluster, to guarantee that we
363 * do not muck with it until it has gone out. We also must refrain
364 * from inadvertantly touching a piece of data that falls within the
365 * same cache line as any portion of the packet, if we have been lucky
366 * enough to be DMA-ing directly out from it.
367 * Certain IBM architects assure me that the rios is fast enough
368 * that the cost of the extra copy, as opposed to trying to
369 * DMA directly from the packet is barely worth my while,
370 * but I have a hard time accepting this.
372 * We can only use this code once we are passed in an indication of
373 * whether we are being called `process-synchronously' or not.
375 * of course, the packet must be pinned, which is currently true,
376 * but in future may not be.
381 tdata
= dvec
[0].iov_base
;
382 tl
= dvec
[0].iov_len
;
386 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
389 MGET(m
, M_DONTWAIT
, MT_DATA
);
393 /* can't get an mbuf, give up */
395 m_freem(top
); /* free mbuf list we're building */
399 m
->m_flags
|= M_PKTHDR
; /* XXX - temp */
401 m
->m_pkthdr
.rcvif
= NULL
;
405 * WARNING: the `4 * MLEN' is somewhat dubious. It is better than
406 * `NBPG', which may have no relation to `CLBYTES'. Also,
407 * `CLBYTES' may be so large that we never use clusters,
408 * resulting in far too many mbufs being used. It is often
409 * better to briefly use a cluster, even if we are only using a
410 * portion of it. Since we are on the xmit side, it shouldn't
411 * end up sitting on a queue for a potentially unbounded time
412 * (except perhaps if we are talking to ourself).
414 if (asize
>= (MHLEN
+ 3 * MLEN
)) {
415 MCLGET(m
, M_DONTWAIT
);
417 /* now compute usable size */
419 len
= MIN(m
->m_ext
.ext_size
, asize
);
421 len
= MIN(mlen
, asize
);
424 tpa
= mtod(m
, caddr_t
);
430 memcpy(tpa
, tdata
, rlen
);
435 top
->m_pkthdr
.len
+= rlen
;
441 /* shouldn't come here! */
442 asize
= 0; /* so we make progress toward completion */
445 tdata
= dvec
[i
].iov_base
;
446 tl
= dvec
[i
].iov_len
;
457 /* setup mbuf corresponding to destination address */
458 MGETHDR(um
, M_DONTWAIT
, MT_SONAME
);
461 m_freem(top
); /* free mbuf chain */
464 memcpy(mtod(um
, caddr_t
), addr
, sizeof(*addr
));
465 um
->m_len
= sizeof(*addr
);
466 um
->m_pkthdr
.len
= sizeof(*addr
);
467 um
->m_flags
|= M_PKTHDR
;
469 SOCKET_LOCK(asocket
);
470 code
= (*asocket
->so_proto
->pr_usrreq
) (asocket
, PRU_SEND
, tm
, um
, 0);
471 SOCKET_UNLOCK(asocket
);
479 #endif /* AFS_AIX41_ENV */