missing-assert-h-20031129
[openafs.git] / src / rx / rx_packet.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #ifdef KERNEL
12 #include "afs/param.h"
13 #else
14 #include <afs/param.h>
15 #endif
16
17 RCSID
18     ("$Header$");
19
20 #ifdef KERNEL
21 #if defined(UKERNEL)
22 #include "afs/sysincludes.h"
23 #include "afsincludes.h"
24 #include "rx/rx_kcommon.h"
25 #include "rx/rx_clock.h"
26 #include "rx/rx_queue.h"
27 #include "rx/rx_packet.h"
28 #else /* defined(UKERNEL) */
29 #ifdef RX_KERNEL_TRACE
30 #include "../rx/rx_kcommon.h"
31 #endif
32 #include "h/types.h"
33 #ifndef AFS_LINUX20_ENV
34 #include "h/systm.h"
35 #endif
36 #if defined(AFS_SGI_ENV) || defined(AFS_HPUX110_ENV)
37 #include "afs/sysincludes.h"
38 #endif
39 #if defined(AFS_OBSD_ENV)
40 #include "h/proc.h"
41 #endif
42 #include "h/socket.h"
43 #if !defined(AFS_SUN5_ENV) &&  !defined(AFS_LINUX20_ENV) && !defined(AFS_HPUX110_ENV)
44 #if     !defined(AFS_OSF_ENV) && !defined(AFS_AIX41_ENV)
45 #include "sys/mount.h"          /* it gets pulled in by something later anyway */
46 #endif
47 #include "h/mbuf.h"
48 #endif
49 #include "netinet/in.h"
50 #include "afs/afs_osi.h"
51 #include "rx_kmutex.h"
52 #include "rx/rx_clock.h"
53 #include "rx/rx_queue.h"
54 #ifdef  AFS_SUN5_ENV
55 #include <sys/sysmacros.h>
56 #endif
57 #include "rx/rx_packet.h"
58 #endif /* defined(UKERNEL) */
59 #include "rx/rx_globals.h"
60 #else /* KERNEL */
61 #include "sys/types.h"
62 #include <sys/stat.h>
63 #include <errno.h>
64 #if defined(AFS_NT40_ENV) || defined(AFS_DJGPP_ENV)
65 #ifdef AFS_NT40_ENV
66 #include <winsock2.h>
67 #else
68 #include <sys/socket.h>
69 #include <netinet/in.h>
70 #endif /* AFS_NT40_ENV */
71 #include "rx_xmit_nt.h"
72 #include <stdlib.h>
73 #else
74 #include <sys/socket.h>
75 #include <netinet/in.h>
76 #endif
77 #include "rx_clock.h"
78 #include "rx.h"
79 #include "rx_queue.h"
80 #ifdef  AFS_SUN5_ENV
81 #include <sys/sysmacros.h>
82 #endif
83 #include "rx_packet.h"
84 #include "rx_globals.h"
85 #include <lwp.h>
86 #include <assert.h>
87 #ifdef HAVE_STRING_H
88 #include <string.h>
89 #else
90 #ifdef HAVE_STRINGS_H
91 #include <strings.h>
92 #endif
93 #endif
94 #ifdef HAVE_UNISTD_H
95 #include <unistd.h>
96 #endif
97 #endif /* KERNEL */
98
99 #ifdef RX_LOCKS_DB
100 /* rxdb_fileID is used to identify the lock location, along with line#. */
101 static int rxdb_fileID = RXDB_FILE_RX_PACKET;
102 #endif /* RX_LOCKS_DB */
103 struct rx_packet *rx_mallocedP = 0;
104
105 extern char cml_version_number[];
106 extern int (*rx_almostSent) ();
107
108 static void rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
109                                 afs_int32 ahost, short aport,
110                                 afs_int32 istack);
111
112 /* some rules about packets:
113  * 1.  When a packet is allocated, the final iov_buf contains room for
114  * a security trailer, but iov_len masks that fact.  If the security
115  * package wants to add the trailer, it may do so, and then extend
116  * iov_len appropriately.  For this reason, packet's niovecs and
117  * iov_len fields should be accurate before calling PreparePacket.
118 */
119
120 /* Preconditions:
121  *        all packet buffers (iov_base) are integral multiples of 
122  *        the word size.
123  *        offset is an integral multiple of the word size.
124  */
125 afs_int32
126 rx_SlowGetInt32(struct rx_packet *packet, size_t offset)
127 {
128     unsigned int i;
129     size_t l;
130     for (l = 0, i = 1; i < packet->niovecs; i++) {
131         if (l + packet->wirevec[i].iov_len > offset) {
132             return
133                 *((afs_int32 *) ((char *)(packet->wirevec[i].iov_base) +
134                                  (offset - l)));
135         }
136         l += packet->wirevec[i].iov_len;
137     }
138
139     return 0;
140 }
141
142 /* Preconditions:
143  *        all packet buffers (iov_base) are integral multiples of the word size.
144  *        offset is an integral multiple of the word size.
145  */
146 afs_int32
147 rx_SlowPutInt32(struct rx_packet * packet, size_t offset, afs_int32 data)
148 {
149     unsigned int i;
150     size_t l;
151     for (l = 0, i = 1; i < packet->niovecs; i++) {
152         if (l + packet->wirevec[i].iov_len > offset) {
153             *((afs_int32 *) ((char *)(packet->wirevec[i].iov_base) +
154                              (offset - l))) = data;
155             return 0;
156         }
157         l += packet->wirevec[i].iov_len;
158     }
159
160     return 0;
161 }
162
163 /* Preconditions:
164  *        all packet buffers (iov_base) are integral multiples of the
165  *        word size.
166  *        offset is an integral multiple of the word size.
167  * Packet Invariants:
168  *         all buffers are contiguously arrayed in the iovec from 0..niovecs-1
169  */
170 afs_int32
171 rx_SlowReadPacket(struct rx_packet * packet, unsigned int offset, int resid,
172                   char *out)
173 {
174     unsigned int i, j, l, r;
175     for (l = 0, i = 1; i < packet->niovecs; i++) {
176         if (l + packet->wirevec[i].iov_len > offset) {
177             break;
178         }
179         l += packet->wirevec[i].iov_len;
180     }
181
182     /* i is the iovec which contains the first little bit of data in which we
183      * are interested.  l is the total length of everything prior to this iovec.
184      * j is the number of bytes we can safely copy out of this iovec.
185      */
186     r = resid;
187     while ((resid > 0) && (i < packet->niovecs)) {
188         j = MIN(resid, packet->wirevec[i].iov_len - (offset - l));
189         memcpy(out, (char *)(packet->wirevec[i].iov_base) + (offset - l), j);
190         resid -= j;
191         l += packet->wirevec[i].iov_len;
192         i++;
193     }
194
195     return (resid ? (r - resid) : r);
196 }
197
198
199 /* Preconditions:
200  *        all packet buffers (iov_base) are integral multiples of the
201  *        word size.
202  *        offset is an integral multiple of the word size.
203  */
204 afs_int32
205 rx_SlowWritePacket(struct rx_packet * packet, int offset, int resid, char *in)
206 {
207     int i, j, l, r;
208     char *b;
209
210     for (l = 0, i = 1; i < packet->niovecs; i++) {
211         if (l + packet->wirevec[i].iov_len > offset) {
212             break;
213         }
214         l += packet->wirevec[i].iov_len;
215     }
216
217     /* i is the iovec which contains the first little bit of data in which we
218      * are interested.  l is the total length of everything prior to this iovec.
219      * j is the number of bytes we can safely copy out of this iovec.
220      */
221     r = resid;
222     while ((resid > 0) && (i < RX_MAXWVECS)) {
223         if (i >= packet->niovecs)
224             if (rxi_AllocDataBuf(packet, resid, RX_PACKET_CLASS_SEND_CBUF) > 0) /* ++niovecs as a side-effect */
225                 break;
226
227         b = (char *)(packet->wirevec[i].iov_base) + (offset - l);
228         j = MIN(resid, packet->wirevec[i].iov_len - (offset - l));
229         memcpy(b, in, j);
230         resid -= j;
231         l += packet->wirevec[i].iov_len;
232         i++;
233     }
234
235     return (resid ? (r - resid) : r);
236 }
237
238 static struct rx_packet *
239 allocCBuf(int class)
240 {
241     struct rx_packet *c;
242     SPLVAR;
243
244     NETPRI;
245     MUTEX_ENTER(&rx_freePktQ_lock);
246
247 #ifdef KERNEL
248     if (rxi_OverQuota(class)) {
249         c = NULL;
250         rxi_NeedMorePackets = TRUE;
251         MUTEX_ENTER(&rx_stats_mutex);
252         switch (class) {
253         case RX_PACKET_CLASS_RECEIVE:
254             rx_stats.receivePktAllocFailures++;
255             break;
256         case RX_PACKET_CLASS_SEND:
257             rx_stats.sendPktAllocFailures++;
258             break;
259         case RX_PACKET_CLASS_SPECIAL:
260             rx_stats.specialPktAllocFailures++;
261             break;
262         case RX_PACKET_CLASS_RECV_CBUF:
263             rx_stats.receiveCbufPktAllocFailures++;
264             break;
265         case RX_PACKET_CLASS_SEND_CBUF:
266             rx_stats.sendCbufPktAllocFailures++;
267             break;
268         }
269         MUTEX_EXIT(&rx_stats_mutex);
270         goto done;
271     }
272
273     if (queue_IsEmpty(&rx_freePacketQueue)) {
274         c = NULL;
275         rxi_NeedMorePackets = TRUE;
276         goto done;
277     }
278 #else /* KERNEL */
279     if (queue_IsEmpty(&rx_freePacketQueue)) {
280         rxi_MorePacketsNoLock(rx_initSendWindow);
281     }
282 #endif /* KERNEL */
283
284     rx_nFreePackets--;
285     c = queue_First(&rx_freePacketQueue, rx_packet);
286     queue_Remove(c);
287     if (!(c->flags & RX_PKTFLAG_FREE))
288         osi_Panic("rxi_AllocPacket: packet not free\n");
289     c->flags = 0;               /* clear RX_PKTFLAG_FREE, initialize the rest */
290     c->header.flags = 0;
291
292 #ifdef KERNEL
293   done:
294 #endif
295     MUTEX_EXIT(&rx_freePktQ_lock);
296
297     USERPRI;
298     return c;
299 }
300
301 /*
302  * Free a packet currently used as a continuation buffer
303  */
304 void
305 rxi_freeCBuf(struct rx_packet *c)
306 {
307     SPLVAR;
308
309     NETPRI;
310     MUTEX_ENTER(&rx_freePktQ_lock);
311
312     rxi_FreePacketNoLock(c);
313     /* Wakeup anyone waiting for packets */
314     rxi_PacketsUnWait();
315
316     MUTEX_EXIT(&rx_freePktQ_lock);
317     USERPRI;
318 }
319
320 /* this one is kind of awful.
321  * In rxkad, the packet has been all shortened, and everything, ready for 
322  * sending.  All of a sudden, we discover we need some of that space back.
323  * This isn't terribly general, because it knows that the packets are only
324  * rounded up to the EBS (userdata + security header).
325  */
326 int
327 rxi_RoundUpPacket(struct rx_packet *p, unsigned int nb)
328 {
329     int i;
330     i = p->niovecs - 1;
331     if (p->wirevec[i].iov_base == (caddr_t) p->localdata) {
332         if (p->wirevec[i].iov_len <= RX_FIRSTBUFFERSIZE - nb) {
333             p->wirevec[i].iov_len += nb;
334             return 0;
335         }
336     } else {
337         if (p->wirevec[i].iov_len <= RX_CBUFFERSIZE - nb) {
338             p->wirevec[i].iov_len += nb;
339             return 0;
340         }
341     }
342
343     return 0;
344 }
345
346 /* get sufficient space to store nb bytes of data (or more), and hook
347  * it into the supplied packet.  Return nbytes<=0 if successful, otherwise
348  * returns the number of bytes >0 which it failed to come up with.
349  * Don't need to worry about locking on packet, since only
350  * one thread can manipulate one at a time. Locking on continution
351  * packets is handled by allocCBuf */
352 /* MTUXXX don't need to go throught the for loop if we can trust niovecs */
353 int
354 rxi_AllocDataBuf(struct rx_packet *p, int nb, int class)
355 {
356     int i;
357
358     for (i = p->niovecs; nb > 0 && i < RX_MAXWVECS; i++) {
359         register struct rx_packet *cb;
360         if ((cb = allocCBuf(class))) {
361             p->wirevec[i].iov_base = (caddr_t) cb->localdata;
362             p->wirevec[i].iov_len = RX_CBUFFERSIZE;
363             nb -= RX_CBUFFERSIZE;
364             p->length += RX_CBUFFERSIZE;
365             p->niovecs++;
366         } else
367             break;
368     }
369
370     return nb;
371 }
372
373 /* Add more packet buffers */
374 void
375 rxi_MorePackets(int apackets)
376 {
377     struct rx_packet *p, *e;
378     int getme;
379     SPLVAR;
380
381     getme = apackets * sizeof(struct rx_packet);
382     p = rx_mallocedP = (struct rx_packet *)osi_Alloc(getme);
383
384     PIN(p, getme);              /* XXXXX */
385     memset((char *)p, 0, getme);
386     NETPRI;
387     AFS_RXGLOCK();
388     MUTEX_ENTER(&rx_freePktQ_lock);
389
390     for (e = p + apackets; p < e; p++) {
391         p->wirevec[0].iov_base = (char *)(p->wirehead);
392         p->wirevec[0].iov_len = RX_HEADER_SIZE;
393         p->wirevec[1].iov_base = (char *)(p->localdata);
394         p->wirevec[1].iov_len = RX_FIRSTBUFFERSIZE;
395         p->flags |= RX_PKTFLAG_FREE;
396         p->niovecs = 2;
397
398         queue_Append(&rx_freePacketQueue, p);
399     }
400     rx_nFreePackets += apackets;
401     rxi_NeedMorePackets = FALSE;
402     rxi_PacketsUnWait();
403
404     AFS_RXGUNLOCK();
405     MUTEX_EXIT(&rx_freePktQ_lock);
406     USERPRI;
407 }
408
409 #ifndef KERNEL
410 /* Add more packet buffers */
411 void
412 rxi_MorePacketsNoLock(int apackets)
413 {
414     struct rx_packet *p, *e;
415     int getme;
416
417     /* allocate enough packets that 1/4 of the packets will be able
418      * to hold maximal amounts of data */
419     apackets += (apackets / 4)
420         * ((rx_maxJumboRecvSize - RX_FIRSTBUFFERSIZE) / RX_CBUFFERSIZE);
421     getme = apackets * sizeof(struct rx_packet);
422     p = rx_mallocedP = (struct rx_packet *)osi_Alloc(getme);
423
424     memset((char *)p, 0, getme);
425
426     for (e = p + apackets; p < e; p++) {
427         p->wirevec[0].iov_base = (char *)(p->wirehead);
428         p->wirevec[0].iov_len = RX_HEADER_SIZE;
429         p->wirevec[1].iov_base = (char *)(p->localdata);
430         p->wirevec[1].iov_len = RX_FIRSTBUFFERSIZE;
431         p->flags |= RX_PKTFLAG_FREE;
432         p->niovecs = 2;
433
434         queue_Append(&rx_freePacketQueue, p);
435     }
436     rx_nFreePackets += apackets;
437     rxi_NeedMorePackets = FALSE;
438     rxi_PacketsUnWait();
439 }
440 #endif /* !KERNEL */
441
442 void
443 rxi_FreeAllPackets(void)
444 {
445     /* must be called at proper interrupt level, etcetera */
446     /* MTUXXX need to free all Packets */
447     osi_Free(rx_mallocedP,
448              (rx_maxReceiveWindow + 2) * sizeof(struct rx_packet));
449     UNPIN(rx_mallocedP, (rx_maxReceiveWindow + 2) * sizeof(struct rx_packet));
450 }
451
452 /* Allocate more packets iff we need more continuation buffers */
453 /* In kernel, can't page in memory with interrupts disabled, so we
454  * don't use the event mechanism. */
455 void
456 rx_CheckPackets(void)
457 {
458     if (rxi_NeedMorePackets) {
459         rxi_MorePackets(rx_initSendWindow);
460     }
461 }
462
463 /* In the packet freeing routine below, the assumption is that
464    we want all of the packets to be used equally frequently, so that we
465    don't get packet buffers paging out.  It would be just as valid to
466    assume that we DO want them to page out if not many are being used.
467    In any event, we assume the former, and append the packets to the end
468    of the free list.  */
469 /* This explanation is bogus.  The free list doesn't remain in any kind of
470    useful order for afs_int32: the packets in use get pretty much randomly scattered 
471    across all the pages.  In order to permit unused {packets,bufs} to page out, they
472    must be stored so that packets which are adjacent in memory are adjacent in the 
473    free list.  An array springs rapidly to mind.
474    */
475
476 /* Actually free the packet p. */
477 void
478 rxi_FreePacketNoLock(struct rx_packet *p)
479 {
480     dpf(("Free %x\n", (int)p));
481
482     if (p->flags & RX_PKTFLAG_FREE)
483         osi_Panic("rxi_FreePacketNoLock: packet already free\n");
484     rx_nFreePackets++;
485     p->flags |= RX_PKTFLAG_FREE;
486     queue_Append(&rx_freePacketQueue, p);
487 }
488
489 int
490 rxi_FreeDataBufsNoLock(struct rx_packet *p, int first)
491 {
492     struct iovec *iov, *end;
493
494     if (first != 1)             /* MTUXXX */
495         osi_Panic("FreeDataBufs 1: first must be 1");
496     iov = &p->wirevec[1];
497     end = iov + (p->niovecs - 1);
498     if (iov->iov_base != (caddr_t) p->localdata)        /* MTUXXX */
499         osi_Panic("FreeDataBufs 2: vec 1 must be localdata");
500     for (iov++; iov < end; iov++) {
501         if (!iov->iov_base)
502             osi_Panic("FreeDataBufs 3: vecs 2-niovecs must not be NULL");
503         rxi_FreePacketNoLock(RX_CBUF_TO_PACKET(iov->iov_base, p));
504     }
505     p->length = 0;
506     p->niovecs = 0;
507
508     return 0;
509 }
510
511 int rxi_nBadIovecs = 0;
512
513 /* rxi_RestoreDataBufs 
514  *
515  * Restore the correct sizes to the iovecs. Called when reusing a packet
516  * for reading off the wire.
517  */
518 void
519 rxi_RestoreDataBufs(struct rx_packet *p)
520 {
521     int i;
522     struct iovec *iov = &p->wirevec[2];
523
524     p->wirevec[0].iov_base = (char *)(p->wirehead);
525     p->wirevec[0].iov_len = RX_HEADER_SIZE;
526     p->wirevec[1].iov_base = (char *)(p->localdata);
527     p->wirevec[1].iov_len = RX_FIRSTBUFFERSIZE;
528
529     for (i = 2, iov = &p->wirevec[2]; i < p->niovecs; i++, iov++) {
530         if (!iov->iov_base) {
531             rxi_nBadIovecs++;
532             p->niovecs = i;
533             break;
534         }
535         iov->iov_len = RX_CBUFFERSIZE;
536     }
537 }
538
539 int
540 rxi_TrimDataBufs(struct rx_packet *p, int first)
541 {
542     int length;
543     struct iovec *iov, *end;
544     SPLVAR;
545
546     if (first != 1)
547         osi_Panic("TrimDataBufs 1: first must be 1");
548
549     /* Skip over continuation buffers containing message data */
550     iov = &p->wirevec[2];
551     end = iov + (p->niovecs - 2);
552     length = p->length - p->wirevec[1].iov_len;
553     for (; iov < end && length > 0; iov++) {
554         if (!iov->iov_base)
555             osi_Panic("TrimDataBufs 3: vecs 1-niovecs must not be NULL");
556         length -= iov->iov_len;
557     }
558
559     /* iov now points to the first empty data buffer. */
560     if (iov >= end)
561         return 0;
562
563     NETPRI;
564     MUTEX_ENTER(&rx_freePktQ_lock);
565
566     for (; iov < end; iov++) {
567         if (!iov->iov_base)
568             osi_Panic("TrimDataBufs 4: vecs 2-niovecs must not be NULL");
569         rxi_FreePacketNoLock(RX_CBUF_TO_PACKET(iov->iov_base, p));
570         p->niovecs--;
571     }
572     rxi_PacketsUnWait();
573
574     MUTEX_EXIT(&rx_freePktQ_lock);
575     USERPRI;
576
577     return 0;
578 }
579
580 /* Free the packet p.  P is assumed not to be on any queue, i.e.
581  * remove it yourself first if you call this routine. */
582 void
583 rxi_FreePacket(struct rx_packet *p)
584 {
585     SPLVAR;
586
587     NETPRI;
588     MUTEX_ENTER(&rx_freePktQ_lock);
589
590     rxi_FreeDataBufsNoLock(p, 1);
591     rxi_FreePacketNoLock(p);
592     /* Wakeup anyone waiting for packets */
593     rxi_PacketsUnWait();
594
595     MUTEX_EXIT(&rx_freePktQ_lock);
596     USERPRI;
597 }
598
599
600 /* rxi_AllocPacket sets up p->length so it reflects the number of 
601  * bytes in the packet at this point, **not including** the header.
602  * The header is absolutely necessary, besides, this is the way the
603  * length field is usually used */
604 struct rx_packet *
605 rxi_AllocPacketNoLock(int class)
606 {
607     register struct rx_packet *p;
608
609 #ifdef KERNEL
610     if (rxi_OverQuota(class)) {
611         rxi_NeedMorePackets = TRUE;
612         MUTEX_ENTER(&rx_stats_mutex);
613         switch (class) {
614         case RX_PACKET_CLASS_RECEIVE:
615             rx_stats.receivePktAllocFailures++;
616             break;
617         case RX_PACKET_CLASS_SEND:
618             rx_stats.sendPktAllocFailures++;
619             break;
620         case RX_PACKET_CLASS_SPECIAL:
621             rx_stats.specialPktAllocFailures++;
622             break;
623         case RX_PACKET_CLASS_RECV_CBUF:
624             rx_stats.receiveCbufPktAllocFailures++;
625             break;
626         case RX_PACKET_CLASS_SEND_CBUF:
627             rx_stats.sendCbufPktAllocFailures++;
628             break;
629         }
630         MUTEX_EXIT(&rx_stats_mutex);
631         return (struct rx_packet *)0;
632     }
633 #endif /* KERNEL */
634
635     MUTEX_ENTER(&rx_stats_mutex);
636     rx_stats.packetRequests++;
637     MUTEX_EXIT(&rx_stats_mutex);
638
639 #ifdef KERNEL
640     if (queue_IsEmpty(&rx_freePacketQueue))
641         osi_Panic("rxi_AllocPacket error");
642 #else /* KERNEL */
643     if (queue_IsEmpty(&rx_freePacketQueue))
644         rxi_MorePacketsNoLock(rx_initSendWindow);
645 #endif /* KERNEL */
646
647     rx_nFreePackets--;
648     p = queue_First(&rx_freePacketQueue, rx_packet);
649     if (!(p->flags & RX_PKTFLAG_FREE))
650         osi_Panic("rxi_AllocPacket: packet not free\n");
651
652     dpf(("Alloc %x, class %d\n", (int)p, class));
653
654     queue_Remove(p);
655     p->flags = 0;               /* clear RX_PKTFLAG_FREE, initialize the rest */
656     p->header.flags = 0;
657
658     /* have to do this here because rx_FlushWrite fiddles with the iovs in
659      * order to truncate outbound packets.  In the near future, may need 
660      * to allocate bufs from a static pool here, and/or in AllocSendPacket
661      */
662     p->wirevec[0].iov_base = (char *)(p->wirehead);
663     p->wirevec[0].iov_len = RX_HEADER_SIZE;
664     p->wirevec[1].iov_base = (char *)(p->localdata);
665     p->wirevec[1].iov_len = RX_FIRSTBUFFERSIZE;
666     p->niovecs = 2;
667     p->length = RX_FIRSTBUFFERSIZE;
668     return p;
669 }
670
671 struct rx_packet *
672 rxi_AllocPacket(int class)
673 {
674     register struct rx_packet *p;
675
676     MUTEX_ENTER(&rx_freePktQ_lock);
677     p = rxi_AllocPacketNoLock(class);
678     MUTEX_EXIT(&rx_freePktQ_lock);
679     return p;
680 }
681
682 /* This guy comes up with as many buffers as it {takes,can get} given
683  * the MTU for this call. It also sets the packet length before
684  * returning.  caution: this is often called at NETPRI
685  * Called with call locked.
686  */
687 struct rx_packet *
688 rxi_AllocSendPacket(register struct rx_call *call, int want)
689 {
690     register struct rx_packet *p = (struct rx_packet *)0;
691     register int mud;
692     register unsigned delta;
693
694     SPLVAR;
695     mud = call->MTU - RX_HEADER_SIZE;
696     delta =
697         rx_GetSecurityHeaderSize(rx_ConnectionOf(call)) +
698         rx_GetSecurityMaxTrailerSize(rx_ConnectionOf(call));
699
700     while (!(call->error)) {
701         MUTEX_ENTER(&rx_freePktQ_lock);
702         /* if an error occurred, or we get the packet we want, we're done */
703         if ((p = rxi_AllocPacketNoLock(RX_PACKET_CLASS_SEND))) {
704             MUTEX_EXIT(&rx_freePktQ_lock);
705
706             want += delta;
707             want = MIN(want, mud);
708
709             if ((unsigned)want > p->length)
710                 (void)rxi_AllocDataBuf(p, (want - p->length),
711                                        RX_PACKET_CLASS_SEND_CBUF);
712
713             if ((unsigned)p->length > mud)
714                 p->length = mud;
715
716             if (delta >= p->length) {
717                 rxi_FreePacket(p);
718                 p = NULL;
719             } else {
720                 p->length -= delta;
721             }
722             break;
723         }
724
725         /* no error occurred, and we didn't get a packet, so we sleep.
726          * At this point, we assume that packets will be returned
727          * sooner or later, as packets are acknowledged, and so we
728          * just wait.  */
729         NETPRI;
730         call->flags |= RX_CALL_WAIT_PACKETS;
731         CALL_HOLD(call, RX_CALL_REFCOUNT_PACKET);
732         MUTEX_EXIT(&call->lock);
733         rx_waitingForPackets = 1;
734
735 #ifdef  RX_ENABLE_LOCKS
736         CV_WAIT(&rx_waitingForPackets_cv, &rx_freePktQ_lock);
737 #else
738         osi_rxSleep(&rx_waitingForPackets);
739 #endif
740         MUTEX_EXIT(&rx_freePktQ_lock);
741         MUTEX_ENTER(&call->lock);
742         CALL_RELE(call, RX_CALL_REFCOUNT_PACKET);
743         call->flags &= ~RX_CALL_WAIT_PACKETS;
744         USERPRI;
745     }
746
747     return p;
748 }
749
750 #ifndef KERNEL
751
752 /* count the number of used FDs */
753 static int
754 CountFDs(register int amax)
755 {
756     struct stat tstat;
757     register int i, code;
758     register int count;
759
760     count = 0;
761     for (i = 0; i < amax; i++) {
762         code = fstat(i, &tstat);
763         if (code == 0)
764             count++;
765     }
766     return count;
767 }
768
769 #else /* KERNEL */
770
771 #define CountFDs(amax) amax
772
773 #endif /* KERNEL */
774
775 #if !defined(KERNEL) || defined(UKERNEL)
776
777 /* This function reads a single packet from the interface into the
778  * supplied packet buffer (*p).  Return 0 if the packet is bogus.  The
779  * (host,port) of the sender are stored in the supplied variables, and
780  * the data length of the packet is stored in the packet structure.
781  * The header is decoded. */
782 int
783 rxi_ReadPacket(int socket, register struct rx_packet *p, afs_uint32 * host,
784                u_short * port)
785 {
786     struct sockaddr_in from;
787     int nbytes;
788     afs_int32 rlen;
789     register afs_int32 tlen, savelen;
790     struct msghdr msg;
791     rx_computelen(p, tlen);
792     rx_SetDataSize(p, tlen);    /* this is the size of the user data area */
793
794     tlen += RX_HEADER_SIZE;     /* now this is the size of the entire packet */
795     rlen = rx_maxJumboRecvSize; /* this is what I am advertising.  Only check
796                                  * it once in order to avoid races.  */
797     tlen = rlen - tlen;
798     if (tlen > 0) {
799         tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_SEND_CBUF);
800         if (tlen > 0) {
801             tlen = rlen - tlen;
802         } else
803             tlen = rlen;
804     } else
805         tlen = rlen;
806
807     /* Extend the last iovec for padding, it's just to make sure that the 
808      * read doesn't return more data than we expect, and is done to get around
809      * our problems caused by the lack of a length field in the rx header.
810      * Use the extra buffer that follows the localdata in each packet
811      * structure. */
812     savelen = p->wirevec[p->niovecs - 1].iov_len;
813     p->wirevec[p->niovecs - 1].iov_len += RX_EXTRABUFFERSIZE;
814
815     memset((char *)&msg, 0, sizeof(msg));
816     msg.msg_name = (char *)&from;
817     msg.msg_namelen = sizeof(struct sockaddr_in);
818     msg.msg_iov = p->wirevec;
819     msg.msg_iovlen = p->niovecs;
820     nbytes = rxi_Recvmsg(socket, &msg, 0);
821
822     /* restore the vec to its correct state */
823     p->wirevec[p->niovecs - 1].iov_len = savelen;
824
825     p->length = (nbytes - RX_HEADER_SIZE);
826     if ((nbytes > tlen) || (p->length & 0x8000)) {      /* Bogus packet */
827         if (nbytes > 0)
828             rxi_MorePackets(rx_initSendWindow);
829 #ifndef AFS_NT40_ENV
830         else if (nbytes < 0 && errno == EWOULDBLOCK) {
831             MUTEX_ENTER(&rx_stats_mutex);
832             rx_stats.noPacketOnRead++;
833             MUTEX_EXIT(&rx_stats_mutex);
834         }
835 #endif
836         else {
837             MUTEX_ENTER(&rx_stats_mutex);
838             rx_stats.bogusPacketOnRead++;
839             rx_stats.bogusHost = from.sin_addr.s_addr;
840             MUTEX_EXIT(&rx_stats_mutex);
841             dpf(("B: bogus packet from [%x,%d] nb=%d", from.sin_addr.s_addr,
842                  from.sin_port, nbytes));
843         }
844         return 0;
845     } else {
846         /* Extract packet header. */
847         rxi_DecodePacketHeader(p);
848
849         *host = from.sin_addr.s_addr;
850         *port = from.sin_port;
851         if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
852             struct rx_peer *peer;
853             MUTEX_ENTER(&rx_stats_mutex);
854             rx_stats.packetsRead[p->header.type - 1]++;
855             MUTEX_EXIT(&rx_stats_mutex);
856             /*
857              * Try to look up this peer structure.  If it doesn't exist,
858              * don't create a new one - 
859              * we don't keep count of the bytes sent/received if a peer
860              * structure doesn't already exist.
861              *
862              * The peer/connection cleanup code assumes that there is 1 peer
863              * per connection.  If we actually created a peer structure here
864              * and this packet was an rxdebug packet, the peer structure would
865              * never be cleaned up.
866              */
867             peer = rxi_FindPeer(*host, *port, 0, 0);
868             if (peer) {
869                 MUTEX_ENTER(&peer->peer_lock);
870                 hadd32(peer->bytesReceived, p->length);
871                 MUTEX_EXIT(&peer->peer_lock);
872             }
873         }
874
875         /* Free any empty packet buffers at the end of this packet */
876         rxi_TrimDataBufs(p, 1);
877
878         return 1;
879     }
880 }
881
882 #endif /* !KERNEL || UKERNEL */
883
884 /* This function splits off the first packet in a jumbo packet.
885  * As of AFS 3.5, jumbograms contain more than one fixed size
886  * packet, and the RX_JUMBO_PACKET flag is set in all but the
887  * last packet header. All packets (except the last) are padded to
888  * fall on RX_CBUFFERSIZE boundaries.
889  * HACK: We store the length of the first n-1 packets in the
890  * last two pad bytes. */
891
892 struct rx_packet *
893 rxi_SplitJumboPacket(register struct rx_packet *p, afs_int32 host, short port,
894                      int first)
895 {
896     struct rx_packet *np;
897     struct rx_jumboHeader *jp;
898     int niov, i;
899     struct iovec *iov;
900     int length;
901     afs_uint32 temp;
902
903     /* All but the last packet in each jumbogram are RX_JUMBOBUFFERSIZE
904      * bytes in length. All but the first packet are preceded by
905      * an abbreviated four byte header. The length of the last packet
906      * is calculated from the size of the jumbogram. */
907     length = RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
908
909     if ((int)p->length < length) {
910         dpf(("rxi_SplitJumboPacket: bogus length %d\n", p->length));
911         return NULL;
912     }
913     niov = p->niovecs - 2;
914     if (niov < 1) {
915         dpf(("rxi_SplitJumboPacket: bogus niovecs %d\n", p->niovecs));
916         return NULL;
917     }
918     iov = &p->wirevec[2];
919     np = RX_CBUF_TO_PACKET(iov->iov_base, p);
920
921     /* Get a pointer to the abbreviated packet header */
922     jp = (struct rx_jumboHeader *)
923         ((char *)(p->wirevec[1].iov_base) + RX_JUMBOBUFFERSIZE);
924
925     /* Set up the iovecs for the next packet */
926     np->wirevec[0].iov_base = (char *)(&np->wirehead[0]);
927     np->wirevec[0].iov_len = sizeof(struct rx_header);
928     np->wirevec[1].iov_base = (char *)(&np->localdata[0]);
929     np->wirevec[1].iov_len = length - RX_JUMBOHEADERSIZE;
930     np->niovecs = niov + 1;
931     for (i = 2, iov++; i <= niov; i++, iov++) {
932         np->wirevec[i] = *iov;
933     }
934     np->length = p->length - length;
935     p->length = RX_JUMBOBUFFERSIZE;
936     p->niovecs = 2;
937
938     /* Convert the jumbo packet header to host byte order */
939     temp = ntohl(*(afs_uint32 *) jp);
940     jp->flags = (u_char) (temp >> 24);
941     jp->cksum = (u_short) (temp);
942
943     /* Fill in the packet header */
944     np->header = p->header;
945     np->header.serial = p->header.serial + 1;
946     np->header.seq = p->header.seq + 1;
947     np->header.flags = jp->flags;
948     np->header.spare = jp->cksum;
949
950     return np;
951 }
952
953 #ifndef KERNEL
954 /* Send a udp datagram */
955 int
956 osi_NetSend(osi_socket socket, void *addr, struct iovec *dvec, int nvecs,
957             int length, int istack)
958 {
959     struct msghdr msg;
960
961     memset(&msg, 0, sizeof(msg));
962     msg.msg_iov = dvec;
963     msg.msg_iovlen = nvecs;
964     msg.msg_name = addr;
965     msg.msg_namelen = sizeof(struct sockaddr_in);
966
967     rxi_Sendmsg(socket, &msg, 0);
968
969     return 0;
970 }
971 #elif !defined(UKERNEL)
972 /*
973  * message receipt is done in rxk_input or rx_put.
974  */
975
976 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX110_ENV)
977 /*
978  * Copy an mblock to the contiguous area pointed to by cp.
979  * MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
980  * but it doesn't really.
981  * Returns the number of bytes not transferred.
982  * The message is NOT changed.
983  */
984 static int
985 cpytoc(mblk_t * mp, register int off, register int len, register char *cp)
986 {
987     register int n;
988
989     for (; mp && len > 0; mp = mp->b_cont) {
990         if (mp->b_datap->db_type != M_DATA) {
991             return -1;
992         }
993         n = MIN(len, (mp->b_wptr - mp->b_rptr));
994         memcpy(cp, (char *)mp->b_rptr, n);
995         cp += n;
996         len -= n;
997         mp->b_rptr += n;
998     }
999     return (len);
1000 }
1001
1002 /* MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
1003  * but it doesn't really.  
1004  * This sucks, anyway, do it like m_cpy.... below 
1005  */
1006 static int
1007 cpytoiovec(mblk_t * mp, int off, int len, register struct iovec *iovs,
1008            int niovs)
1009 {
1010     register int m, n, o, t, i;
1011
1012     for (i = -1, t = 0; i < niovs && mp && len > 0; mp = mp->b_cont) {
1013         if (mp->b_datap->db_type != M_DATA) {
1014             return -1;
1015         }
1016         n = MIN(len, (mp->b_wptr - mp->b_rptr));
1017         len -= n;
1018         while (n) {
1019             if (!t) {
1020                 o = 0;
1021                 i++;
1022                 t = iovs[i].iov_len;
1023             }
1024             m = MIN(n, t);
1025             memcpy(iovs[i].iov_base + o, (char *)mp->b_rptr, m);
1026             mp->b_rptr += m;
1027             o += m;
1028             t -= m;
1029             n -= m;
1030         }
1031     }
1032     return (len);
1033 }
1034
1035 #define m_cpytoc(a, b, c, d)  cpytoc(a, b, c, d)
1036 #define m_cpytoiovec(a, b, c, d, e) cpytoiovec(a, b, c, d, e)
1037 #else
1038 #if !defined(AFS_LINUX20_ENV)
1039 static int
1040 m_cpytoiovec(struct mbuf *m, int off, int len, struct iovec iovs[], int niovs)
1041 {
1042     caddr_t p1, p2;
1043     unsigned int l1, l2, i, t;
1044
1045     if (m == NULL || off < 0 || len < 0 || iovs == NULL)
1046         osi_Panic("m_cpytoiovec");      /* MTUXXX probably don't need this check */
1047
1048     while (off && m)
1049         if (m->m_len <= off) {
1050             off -= m->m_len;
1051             m = m->m_next;
1052             continue;
1053         } else
1054             break;
1055
1056     if (m == NULL)
1057         return len;
1058
1059     p1 = mtod(m, caddr_t) + off;
1060     l1 = m->m_len - off;
1061     i = 0;
1062     p2 = iovs[0].iov_base;
1063     l2 = iovs[0].iov_len;
1064
1065     while (len) {
1066         t = MIN(l1, MIN(l2, (unsigned int)len));
1067         memcpy(p2, p1, t);
1068         p1 += t;
1069         p2 += t;
1070         l1 -= t;
1071         l2 -= t;
1072         len -= t;
1073         if (!l1) {
1074             m = m->m_next;
1075             if (!m)
1076                 break;
1077             p1 = mtod(m, caddr_t);
1078             l1 = m->m_len;
1079         }
1080         if (!l2) {
1081             if (++i >= niovs)
1082                 break;
1083             p2 = iovs[i].iov_base;
1084             l2 = iovs[i].iov_len;
1085         }
1086
1087     }
1088
1089     return len;
1090 }
1091 #endif /* LINUX */
1092 #endif /* AFS_SUN5_ENV */
1093
1094 #if !defined(AFS_LINUX20_ENV)
1095 int
1096 rx_mb_to_packet(amb, free, hdr_len, data_len, phandle)
1097 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX110_ENV)
1098      mblk_t *amb;
1099 #else
1100      struct mbuf *amb;
1101 #endif
1102      void (*free) ();
1103      struct rx_packet *phandle;
1104      int hdr_len, data_len;
1105 {
1106     register int code;
1107
1108     code =
1109         m_cpytoiovec(amb, hdr_len, data_len, phandle->wirevec,
1110                      phandle->niovecs);
1111     (*free) (amb);
1112
1113     return code;
1114 }
1115 #endif /* LINUX */
1116 #endif /*KERNEL && !UKERNEL */
1117
1118
1119 /* send a response to a debug packet */
1120
1121 struct rx_packet *
1122 rxi_ReceiveDebugPacket(register struct rx_packet *ap, osi_socket asocket,
1123                        afs_int32 ahost, short aport, int istack)
1124 {
1125     struct rx_debugIn tin;
1126     afs_int32 tl;
1127     struct rx_serverQueueEntry *np, *nqe;
1128
1129     /*
1130      * Only respond to client-initiated Rx debug packets,
1131      * and clear the client flag in the response.
1132      */
1133     if (ap->header.flags & RX_CLIENT_INITIATED) {
1134         ap->header.flags = ap->header.flags & ~RX_CLIENT_INITIATED;
1135         rxi_EncodePacketHeader(ap);
1136     } else {
1137         return ap;
1138     }
1139
1140     rx_packetread(ap, 0, sizeof(struct rx_debugIn), (char *)&tin);
1141     /* all done with packet, now set length to the truth, so we can 
1142      * reuse this packet */
1143     rx_computelen(ap, ap->length);
1144
1145     tin.type = ntohl(tin.type);
1146     tin.index = ntohl(tin.index);
1147     switch (tin.type) {
1148     case RX_DEBUGI_GETSTATS:{
1149             struct rx_debugStats tstat;
1150
1151             /* get basic stats */
1152             memset((char *)&tstat, 0, sizeof(tstat));   /* make sure spares are zero */
1153             tstat.version = RX_DEBUGI_VERSION;
1154 #ifndef RX_ENABLE_LOCKS
1155             tstat.waitingForPackets = rx_waitingForPackets;
1156 #endif
1157             tstat.nFreePackets = htonl(rx_nFreePackets);
1158             tstat.callsExecuted = htonl(rxi_nCalls);
1159             tstat.packetReclaims = htonl(rx_packetReclaims);
1160             tstat.usedFDs = CountFDs(64);
1161             tstat.nWaiting = htonl(rx_nWaiting);
1162             queue_Count(&rx_idleServerQueue, np, nqe, rx_serverQueueEntry,
1163                         tstat.idleThreads);
1164             tstat.idleThreads = htonl(tstat.idleThreads);
1165             tl = sizeof(struct rx_debugStats) - ap->length;
1166             if (tl > 0)
1167                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1168
1169             if (tl <= 0) {
1170                 rx_packetwrite(ap, 0, sizeof(struct rx_debugStats),
1171                                (char *)&tstat);
1172                 ap->length = sizeof(struct rx_debugStats);
1173                 rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1174                 rx_computelen(ap, ap->length);
1175             }
1176             break;
1177         }
1178
1179     case RX_DEBUGI_GETALLCONN:
1180     case RX_DEBUGI_GETCONN:{
1181             int i, j;
1182             register struct rx_connection *tc;
1183             struct rx_call *tcall;
1184             struct rx_debugConn tconn;
1185             int all = (tin.type == RX_DEBUGI_GETALLCONN);
1186
1187
1188             tl = sizeof(struct rx_debugConn) - ap->length;
1189             if (tl > 0)
1190                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1191             if (tl > 0)
1192                 return ap;
1193
1194             memset((char *)&tconn, 0, sizeof(tconn));   /* make sure spares are zero */
1195             /* get N'th (maybe) "interesting" connection info */
1196             for (i = 0; i < rx_hashTableSize; i++) {
1197 #if !defined(KERNEL)
1198                 /* the time complexity of the algorithm used here
1199                  * exponentially increses with the number of connections.
1200                  */
1201 #ifdef AFS_PTHREAD_ENV
1202                 pthread_yield();
1203 #else
1204                 (void)IOMGR_Poll();
1205 #endif
1206 #endif
1207                 MUTEX_ENTER(&rx_connHashTable_lock);
1208                 /* We might be slightly out of step since we are not 
1209                  * locking each call, but this is only debugging output.
1210                  */
1211                 for (tc = rx_connHashTable[i]; tc; tc = tc->next) {
1212                     if ((all || rxi_IsConnInteresting(tc))
1213                         && tin.index-- <= 0) {
1214                         tconn.host = tc->peer->host;
1215                         tconn.port = tc->peer->port;
1216                         tconn.cid = htonl(tc->cid);
1217                         tconn.epoch = htonl(tc->epoch);
1218                         tconn.serial = htonl(tc->serial);
1219                         for (j = 0; j < RX_MAXCALLS; j++) {
1220                             tconn.callNumber[j] = htonl(tc->callNumber[j]);
1221                             if ((tcall = tc->call[j])) {
1222                                 tconn.callState[j] = tcall->state;
1223                                 tconn.callMode[j] = tcall->mode;
1224                                 tconn.callFlags[j] = tcall->flags;
1225                                 if (queue_IsNotEmpty(&tcall->rq))
1226                                     tconn.callOther[j] |= RX_OTHER_IN;
1227                                 if (queue_IsNotEmpty(&tcall->tq))
1228                                     tconn.callOther[j] |= RX_OTHER_OUT;
1229                             } else
1230                                 tconn.callState[j] = RX_STATE_NOTINIT;
1231                         }
1232
1233                         tconn.natMTU = htonl(tc->peer->natMTU);
1234                         tconn.error = htonl(tc->error);
1235                         tconn.flags = tc->flags;
1236                         tconn.type = tc->type;
1237                         tconn.securityIndex = tc->securityIndex;
1238                         if (tc->securityObject) {
1239                             RXS_GetStats(tc->securityObject, tc,
1240                                          &tconn.secStats);
1241 #define DOHTONL(a) (tconn.secStats.a = htonl(tconn.secStats.a))
1242 #define DOHTONS(a) (tconn.secStats.a = htons(tconn.secStats.a))
1243                             DOHTONL(flags);
1244                             DOHTONL(expires);
1245                             DOHTONL(packetsReceived);
1246                             DOHTONL(packetsSent);
1247                             DOHTONL(bytesReceived);
1248                             DOHTONL(bytesSent);
1249                             for (i = 0;
1250                                  i <
1251                                  sizeof(tconn.secStats.spares) /
1252                                  sizeof(short); i++)
1253                                 DOHTONS(spares[i]);
1254                             for (i = 0;
1255                                  i <
1256                                  sizeof(tconn.secStats.sparel) /
1257                                  sizeof(afs_int32); i++)
1258                                 DOHTONL(sparel[i]);
1259                         }
1260
1261                         MUTEX_EXIT(&rx_connHashTable_lock);
1262                         rx_packetwrite(ap, 0, sizeof(struct rx_debugConn),
1263                                        (char *)&tconn);
1264                         tl = ap->length;
1265                         ap->length = sizeof(struct rx_debugConn);
1266                         rxi_SendDebugPacket(ap, asocket, ahost, aport,
1267                                             istack);
1268                         ap->length = tl;
1269                         return ap;
1270                     }
1271                 }
1272                 MUTEX_EXIT(&rx_connHashTable_lock);
1273             }
1274             /* if we make it here, there are no interesting packets */
1275             tconn.cid = htonl(0xffffffff);      /* means end */
1276             rx_packetwrite(ap, 0, sizeof(struct rx_debugConn),
1277                            (char *)&tconn);
1278             tl = ap->length;
1279             ap->length = sizeof(struct rx_debugConn);
1280             rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1281             ap->length = tl;
1282             break;
1283         }
1284
1285         /*
1286          * Pass back all the peer structures we have available
1287          */
1288
1289     case RX_DEBUGI_GETPEER:{
1290             int i;
1291             register struct rx_peer *tp;
1292             struct rx_debugPeer tpeer;
1293
1294
1295             tl = sizeof(struct rx_debugPeer) - ap->length;
1296             if (tl > 0)
1297                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1298             if (tl > 0)
1299                 return ap;
1300
1301             memset((char *)&tpeer, 0, sizeof(tpeer));
1302             for (i = 0; i < rx_hashTableSize; i++) {
1303 #if !defined(KERNEL)
1304                 /* the time complexity of the algorithm used here
1305                  * exponentially increses with the number of peers.
1306                  *
1307                  * Yielding after processing each hash table entry
1308                  * and dropping rx_peerHashTable_lock.
1309                  * also increases the risk that we will miss a new
1310                  * entry - but we are willing to live with this
1311                  * limitation since this is meant for debugging only
1312                  */
1313 #ifdef AFS_PTHREAD_ENV
1314                 pthread_yield();
1315 #else
1316                 (void)IOMGR_Poll();
1317 #endif
1318 #endif
1319                 MUTEX_ENTER(&rx_peerHashTable_lock);
1320                 for (tp = rx_peerHashTable[i]; tp; tp = tp->next) {
1321                     if (tin.index-- <= 0) {
1322                         tpeer.host = tp->host;
1323                         tpeer.port = tp->port;
1324                         tpeer.ifMTU = htons(tp->ifMTU);
1325                         tpeer.idleWhen = htonl(tp->idleWhen);
1326                         tpeer.refCount = htons(tp->refCount);
1327                         tpeer.burstSize = tp->burstSize;
1328                         tpeer.burst = tp->burst;
1329                         tpeer.burstWait.sec = htonl(tp->burstWait.sec);
1330                         tpeer.burstWait.usec = htonl(tp->burstWait.usec);
1331                         tpeer.rtt = htonl(tp->rtt);
1332                         tpeer.rtt_dev = htonl(tp->rtt_dev);
1333                         tpeer.timeout.sec = htonl(tp->timeout.sec);
1334                         tpeer.timeout.usec = htonl(tp->timeout.usec);
1335                         tpeer.nSent = htonl(tp->nSent);
1336                         tpeer.reSends = htonl(tp->reSends);
1337                         tpeer.inPacketSkew = htonl(tp->inPacketSkew);
1338                         tpeer.outPacketSkew = htonl(tp->outPacketSkew);
1339                         tpeer.rateFlag = htonl(tp->rateFlag);
1340                         tpeer.natMTU = htons(tp->natMTU);
1341                         tpeer.maxMTU = htons(tp->maxMTU);
1342                         tpeer.maxDgramPackets = htons(tp->maxDgramPackets);
1343                         tpeer.ifDgramPackets = htons(tp->ifDgramPackets);
1344                         tpeer.MTU = htons(tp->MTU);
1345                         tpeer.cwind = htons(tp->cwind);
1346                         tpeer.nDgramPackets = htons(tp->nDgramPackets);
1347                         tpeer.congestSeq = htons(tp->congestSeq);
1348                         tpeer.bytesSent.high = htonl(tp->bytesSent.high);
1349                         tpeer.bytesSent.low = htonl(tp->bytesSent.low);
1350                         tpeer.bytesReceived.high =
1351                             htonl(tp->bytesReceived.high);
1352                         tpeer.bytesReceived.low =
1353                             htonl(tp->bytesReceived.low);
1354
1355                         MUTEX_EXIT(&rx_peerHashTable_lock);
1356                         rx_packetwrite(ap, 0, sizeof(struct rx_debugPeer),
1357                                        (char *)&tpeer);
1358                         tl = ap->length;
1359                         ap->length = sizeof(struct rx_debugPeer);
1360                         rxi_SendDebugPacket(ap, asocket, ahost, aport,
1361                                             istack);
1362                         ap->length = tl;
1363                         return ap;
1364                     }
1365                 }
1366                 MUTEX_EXIT(&rx_peerHashTable_lock);
1367             }
1368             /* if we make it here, there are no interesting packets */
1369             tpeer.host = htonl(0xffffffff);     /* means end */
1370             rx_packetwrite(ap, 0, sizeof(struct rx_debugPeer),
1371                            (char *)&tpeer);
1372             tl = ap->length;
1373             ap->length = sizeof(struct rx_debugPeer);
1374             rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1375             ap->length = tl;
1376             break;
1377         }
1378
1379     case RX_DEBUGI_RXSTATS:{
1380             int i;
1381             afs_int32 *s;
1382
1383             tl = sizeof(rx_stats) - ap->length;
1384             if (tl > 0)
1385                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1386             if (tl > 0)
1387                 return ap;
1388
1389             /* Since its all int32s convert to network order with a loop. */
1390             MUTEX_ENTER(&rx_stats_mutex);
1391             s = (afs_int32 *) & rx_stats;
1392             for (i = 0; i < sizeof(rx_stats) / sizeof(afs_int32); i++, s++)
1393                 rx_PutInt32(ap, i * sizeof(afs_int32), htonl(*s));
1394
1395             tl = ap->length;
1396             ap->length = sizeof(rx_stats);
1397             MUTEX_EXIT(&rx_stats_mutex);
1398             rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1399             ap->length = tl;
1400             break;
1401         }
1402
1403     default:
1404         /* error response packet */
1405         tin.type = htonl(RX_DEBUGI_BADTYPE);
1406         tin.index = tin.type;
1407         rx_packetwrite(ap, 0, sizeof(struct rx_debugIn), (char *)&tin);
1408         tl = ap->length;
1409         ap->length = sizeof(struct rx_debugIn);
1410         rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1411         ap->length = tl;
1412         break;
1413     }
1414     return ap;
1415 }
1416
1417 struct rx_packet *
1418 rxi_ReceiveVersionPacket(register struct rx_packet *ap, osi_socket asocket,
1419                          afs_int32 ahost, short aport, int istack)
1420 {
1421     afs_int32 tl;
1422
1423     /*
1424      * Only respond to client-initiated version requests, and
1425      * clear that flag in the response.
1426      */
1427     if (ap->header.flags & RX_CLIENT_INITIATED) {
1428         char buf[66];
1429
1430         ap->header.flags = ap->header.flags & ~RX_CLIENT_INITIATED;
1431         rxi_EncodePacketHeader(ap);
1432         memset(buf, 0, sizeof(buf));
1433         strncpy(buf, cml_version_number + 4, sizeof(buf) - 1);
1434         rx_packetwrite(ap, 0, 65, buf);
1435         tl = ap->length;
1436         ap->length = 65;
1437         rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1438         ap->length = tl;
1439     }
1440
1441     return ap;
1442 }
1443
1444
1445 /* send a debug packet back to the sender */
1446 static void
1447 rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
1448                     afs_int32 ahost, short aport, afs_int32 istack)
1449 {
1450     struct sockaddr_in taddr;
1451     int i;
1452     int nbytes;
1453     int saven = 0;
1454     size_t savelen = 0;
1455 #ifdef KERNEL
1456     int waslocked = ISAFS_GLOCK();
1457 #endif
1458
1459     taddr.sin_family = AF_INET;
1460     taddr.sin_port = aport;
1461     taddr.sin_addr.s_addr = ahost;
1462 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
1463     taddr.sin_len = sizeof(struct sockaddr_in);
1464 #endif
1465
1466     /* We need to trim the niovecs. */
1467     nbytes = apacket->length;
1468     for (i = 1; i < apacket->niovecs; i++) {
1469         if (nbytes <= apacket->wirevec[i].iov_len) {
1470             savelen = apacket->wirevec[i].iov_len;
1471             saven = apacket->niovecs;
1472             apacket->wirevec[i].iov_len = nbytes;
1473             apacket->niovecs = i + 1;   /* so condition fails because i == niovecs */
1474         } else
1475             nbytes -= apacket->wirevec[i].iov_len;
1476     }
1477     AFS_RXGUNLOCK();
1478 #ifdef KERNEL
1479 #ifdef RX_KERNEL_TRACE
1480     if (ICL_SETACTIVE(afs_iclSetp)) {
1481         if (!waslocked)
1482             AFS_GLOCK();
1483         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1484                    "before osi_NetSend()");
1485         AFS_GUNLOCK();
1486     } else
1487 #else
1488     if (waslocked)
1489         AFS_GUNLOCK();
1490 #endif
1491 #endif
1492     /* debug packets are not reliably delivered, hence the cast below. */
1493     (void)osi_NetSend(asocket, &taddr, apacket->wirevec, apacket->niovecs,
1494                       apacket->length + RX_HEADER_SIZE, istack);
1495 #ifdef KERNEL
1496 #ifdef RX_KERNEL_TRACE
1497     if (ICL_SETACTIVE(afs_iclSetp)) {
1498         AFS_GLOCK();
1499         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1500                    "after osi_NetSend()");
1501         if (!waslocked)
1502             AFS_GUNLOCK();
1503     } else
1504 #else
1505     if (waslocked)
1506         AFS_GLOCK();
1507 #endif
1508 #endif
1509     AFS_RXGLOCK();
1510     if (saven) {                /* means we truncated the packet above. */
1511         apacket->wirevec[i - 1].iov_len = savelen;
1512         apacket->niovecs = saven;
1513     }
1514
1515 }
1516
1517 /* Send the packet to appropriate destination for the specified
1518  * call.  The header is first encoded and placed in the packet.
1519  */
1520 void
1521 rxi_SendPacket(struct rx_call *call, struct rx_connection *conn,
1522                struct rx_packet *p, int istack)
1523 {
1524 #if defined(KERNEL)
1525     int waslocked;
1526 #endif
1527     int code;
1528     struct sockaddr_in addr;
1529     register struct rx_peer *peer = conn->peer;
1530     osi_socket socket;
1531 #ifdef RXDEBUG
1532     char deliveryType = 'S';
1533 #endif
1534     /* The address we're sending the packet to */
1535     memset(&addr, 0, sizeof(addr));
1536     addr.sin_family = AF_INET;
1537     addr.sin_port = peer->port;
1538     addr.sin_addr.s_addr = peer->host;
1539
1540     /* This stuff should be revamped, I think, so that most, if not
1541      * all, of the header stuff is always added here.  We could
1542      * probably do away with the encode/decode routines. XXXXX */
1543
1544     /* Stamp each packet with a unique serial number.  The serial
1545      * number is maintained on a connection basis because some types
1546      * of security may be based on the serial number of the packet,
1547      * and security is handled on a per authenticated-connection
1548      * basis. */
1549     /* Pre-increment, to guarantee no zero serial number; a zero
1550      * serial number means the packet was never sent. */
1551     MUTEX_ENTER(&conn->conn_data_lock);
1552     p->header.serial = ++conn->serial;
1553     MUTEX_EXIT(&conn->conn_data_lock);
1554     /* This is so we can adjust retransmit time-outs better in the face of 
1555      * rapidly changing round-trip times.  RTO estimation is not a la Karn.
1556      */
1557     if (p->firstSerial == 0) {
1558         p->firstSerial = p->header.serial;
1559     }
1560 #ifdef RXDEBUG
1561     /* If an output tracer function is defined, call it with the packet and
1562      * network address.  Note this function may modify its arguments. */
1563     if (rx_almostSent) {
1564         int drop = (*rx_almostSent) (p, &addr);
1565         /* drop packet if return value is non-zero? */
1566         if (drop)
1567             deliveryType = 'D'; /* Drop the packet */
1568     }
1569 #endif
1570
1571     /* Get network byte order header */
1572     rxi_EncodePacketHeader(p);  /* XXX in the event of rexmit, etc, don't need to 
1573                                  * touch ALL the fields */
1574
1575     /* Send the packet out on the same socket that related packets are being
1576      * received on */
1577     socket =
1578         (conn->type ==
1579          RX_CLIENT_CONNECTION ? rx_socket : conn->service->socket);
1580
1581 #ifdef RXDEBUG
1582     /* Possibly drop this packet,  for testing purposes */
1583     if ((deliveryType == 'D')
1584         || ((rx_intentionallyDroppedPacketsPer100 > 0)
1585             && (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
1586         deliveryType = 'D';     /* Drop the packet */
1587     } else {
1588         deliveryType = 'S';     /* Send the packet */
1589 #endif /* RXDEBUG */
1590
1591         /* Loop until the packet is sent.  We'd prefer just to use a
1592          * blocking socket, but unfortunately the interface doesn't
1593          * allow us to have the socket block in send mode, and not
1594          * block in receive mode */
1595         AFS_RXGUNLOCK();
1596 #ifdef KERNEL
1597         waslocked = ISAFS_GLOCK();
1598 #ifdef RX_KERNEL_TRACE
1599         if (ICL_SETACTIVE(afs_iclSetp)) {
1600             if (!waslocked)
1601                 AFS_GLOCK();
1602             afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1603                        "before osi_NetSend()");
1604             AFS_GUNLOCK();
1605         } else
1606 #else
1607         if (waslocked)
1608             AFS_GUNLOCK();
1609 #endif
1610 #endif
1611         if ((code =
1612              osi_NetSend(socket, &addr, p->wirevec, p->niovecs,
1613                          p->length + RX_HEADER_SIZE, istack)) != 0) {
1614             /* send failed, so let's hurry up the resend, eh? */
1615             MUTEX_ENTER(&rx_stats_mutex);
1616             rx_stats.netSendFailures++;
1617             MUTEX_EXIT(&rx_stats_mutex);
1618             p->retryTime = p->timeSent; /* resend it very soon */
1619             clock_Addmsec(&(p->retryTime),
1620                           10 + (((afs_uint32) p->backoff) << 8));
1621
1622 #if defined(KERNEL) && defined(AFS_LINUX20_ENV)
1623             /* Linux is nice -- it can tell us right away that we cannot
1624              * reach this recipient by returning an ENETUNREACH error
1625              * code.  So, when this happens let's "down" the host NOW so
1626              * we don't sit around waiting for this host to timeout later.
1627              */
1628             if (call && code == -ENETUNREACH)
1629                 call->lastReceiveTime = 0;
1630 #endif
1631         }
1632 #ifdef KERNEL
1633 #ifdef RX_KERNEL_TRACE
1634         if (ICL_SETACTIVE(afs_iclSetp)) {
1635             AFS_GLOCK();
1636             afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1637                        "after osi_NetSend()");
1638             if (!waslocked)
1639                 AFS_GUNLOCK();
1640         } else
1641 #else
1642         if (waslocked)
1643             AFS_GLOCK();
1644 #endif
1645 #endif
1646         AFS_RXGLOCK();
1647 #ifdef RXDEBUG
1648     }
1649     dpf(("%c %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %x resend %d.%0.3d len %d", deliveryType, p->header.serial, rx_packetTypes[p->header.type - 1], peer->host, peer->port, p->header.serial, p->header.epoch, p->header.cid, p->header.callNumber, p->header.seq, p->header.flags, (int)p, p->retryTime.sec, p->retryTime.usec / 1000, p->length));
1650 #endif
1651     MUTEX_ENTER(&rx_stats_mutex);
1652     rx_stats.packetsSent[p->header.type - 1]++;
1653     MUTEX_EXIT(&rx_stats_mutex);
1654     MUTEX_ENTER(&peer->peer_lock);
1655     hadd32(peer->bytesSent, p->length);
1656     MUTEX_EXIT(&peer->peer_lock);
1657 }
1658
1659 /* Send a list of packets to appropriate destination for the specified
1660  * connection.  The headers are first encoded and placed in the packets.
1661  */
1662 void
1663 rxi_SendPacketList(struct rx_call *call, struct rx_connection *conn,
1664                    struct rx_packet **list, int len, int istack)
1665 {
1666 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
1667     int waslocked;
1668 #endif
1669     struct sockaddr_in addr;
1670     register struct rx_peer *peer = conn->peer;
1671     osi_socket socket;
1672     struct rx_packet *p = NULL;
1673     struct iovec wirevec[RX_MAXIOVECS];
1674     int i, length, code;
1675     afs_uint32 serial;
1676     afs_uint32 temp;
1677     struct rx_jumboHeader *jp;
1678 #ifdef RXDEBUG
1679     char deliveryType = 'S';
1680 #endif
1681     /* The address we're sending the packet to */
1682     addr.sin_family = AF_INET;
1683     addr.sin_port = peer->port;
1684     addr.sin_addr.s_addr = peer->host;
1685
1686     if (len + 1 > RX_MAXIOVECS) {
1687         osi_Panic("rxi_SendPacketList, len > RX_MAXIOVECS\n");
1688     }
1689
1690     /*
1691      * Stamp the packets in this jumbogram with consecutive serial numbers
1692      */
1693     MUTEX_ENTER(&conn->conn_data_lock);
1694     serial = conn->serial;
1695     conn->serial += len;
1696     MUTEX_EXIT(&conn->conn_data_lock);
1697
1698
1699     /* This stuff should be revamped, I think, so that most, if not
1700      * all, of the header stuff is always added here.  We could
1701      * probably do away with the encode/decode routines. XXXXX */
1702
1703     jp = NULL;
1704     length = RX_HEADER_SIZE;
1705     wirevec[0].iov_base = (char *)(&list[0]->wirehead[0]);
1706     wirevec[0].iov_len = RX_HEADER_SIZE;
1707     for (i = 0; i < len; i++) {
1708         p = list[i];
1709
1710         /* The whole 3.5 jumbogram scheme relies on packets fitting
1711          * in a single packet buffer. */
1712         if (p->niovecs > 2) {
1713             osi_Panic("rxi_SendPacketList, niovecs > 2\n");
1714         }
1715
1716         /* Set the RX_JUMBO_PACKET flags in all but the last packets
1717          * in this chunk.  */
1718         if (i < len - 1) {
1719             if (p->length != RX_JUMBOBUFFERSIZE) {
1720                 osi_Panic("rxi_SendPacketList, length != jumbo size\n");
1721             }
1722             p->header.flags |= RX_JUMBO_PACKET;
1723             length += RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
1724             wirevec[i + 1].iov_len = RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
1725         } else {
1726             wirevec[i + 1].iov_len = p->length;
1727             length += p->length;
1728         }
1729         wirevec[i + 1].iov_base = (char *)(&p->localdata[0]);
1730         if (jp != NULL) {
1731             /* Convert jumbo packet header to network byte order */
1732             temp = (afs_uint32) (p->header.flags) << 24;
1733             temp |= (afs_uint32) (p->header.spare);
1734             *(afs_uint32 *) jp = htonl(temp);
1735         }
1736         jp = (struct rx_jumboHeader *)
1737             ((char *)(&p->localdata[0]) + RX_JUMBOBUFFERSIZE);
1738
1739         /* Stamp each packet with a unique serial number.  The serial
1740          * number is maintained on a connection basis because some types
1741          * of security may be based on the serial number of the packet,
1742          * and security is handled on a per authenticated-connection
1743          * basis. */
1744         /* Pre-increment, to guarantee no zero serial number; a zero
1745          * serial number means the packet was never sent. */
1746         p->header.serial = ++serial;
1747         /* This is so we can adjust retransmit time-outs better in the face of 
1748          * rapidly changing round-trip times.  RTO estimation is not a la Karn.
1749          */
1750         if (p->firstSerial == 0) {
1751             p->firstSerial = p->header.serial;
1752         }
1753 #ifdef RXDEBUG
1754         /* If an output tracer function is defined, call it with the packet and
1755          * network address.  Note this function may modify its arguments. */
1756         if (rx_almostSent) {
1757             int drop = (*rx_almostSent) (p, &addr);
1758             /* drop packet if return value is non-zero? */
1759             if (drop)
1760                 deliveryType = 'D';     /* Drop the packet */
1761         }
1762 #endif
1763
1764         /* Get network byte order header */
1765         rxi_EncodePacketHeader(p);      /* XXX in the event of rexmit, etc, don't need to 
1766                                          * touch ALL the fields */
1767     }
1768
1769     /* Send the packet out on the same socket that related packets are being
1770      * received on */
1771     socket =
1772         (conn->type ==
1773          RX_CLIENT_CONNECTION ? rx_socket : conn->service->socket);
1774
1775 #ifdef RXDEBUG
1776     /* Possibly drop this packet,  for testing purposes */
1777     if ((deliveryType == 'D')
1778         || ((rx_intentionallyDroppedPacketsPer100 > 0)
1779             && (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
1780         deliveryType = 'D';     /* Drop the packet */
1781     } else {
1782         deliveryType = 'S';     /* Send the packet */
1783 #endif /* RXDEBUG */
1784
1785         /* Loop until the packet is sent.  We'd prefer just to use a
1786          * blocking socket, but unfortunately the interface doesn't
1787          * allow us to have the socket block in send mode, and not
1788          * block in receive mode */
1789         AFS_RXGUNLOCK();
1790 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
1791         waslocked = ISAFS_GLOCK();
1792         if (!istack && waslocked)
1793             AFS_GUNLOCK();
1794 #endif
1795         if ((code =
1796              osi_NetSend(socket, &addr, &wirevec[0], len + 1, length,
1797                          istack)) != 0) {
1798             /* send failed, so let's hurry up the resend, eh? */
1799             MUTEX_ENTER(&rx_stats_mutex);
1800             rx_stats.netSendFailures++;
1801             MUTEX_EXIT(&rx_stats_mutex);
1802             for (i = 0; i < len; i++) {
1803                 p = list[i];
1804                 p->retryTime = p->timeSent;     /* resend it very soon */
1805                 clock_Addmsec(&(p->retryTime),
1806                               10 + (((afs_uint32) p->backoff) << 8));
1807             }
1808 #if defined(KERNEL) && defined(AFS_LINUX20_ENV)
1809             /* Linux is nice -- it can tell us right away that we cannot
1810              * reach this recipient by returning an ENETUNREACH error
1811              * code.  So, when this happens let's "down" the host NOW so
1812              * we don't sit around waiting for this host to timeout later.
1813              */
1814             if (call && code == -ENETUNREACH)
1815                 call->lastReceiveTime = 0;
1816 #endif
1817         }
1818 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
1819         if (!istack && waslocked)
1820             AFS_GLOCK();
1821 #endif
1822         AFS_RXGLOCK();
1823 #ifdef RXDEBUG
1824     }
1825
1826     assert(p != NULL);
1827
1828     dpf(("%c %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %x resend %d.%0.3d len %d", 
1829            deliveryType, p->header.serial, rx_packetTypes[p->header.type - 1], 
1830            peer->host, peer->port, p->header.serial, p->header.epoch, 
1831            p->header.cid, p->header.callNumber, p->header.seq, p->header.flags,
1832            (int)p, p->retryTime.sec, p->retryTime.usec / 1000, p->length));
1833
1834 #endif
1835     MUTEX_ENTER(&rx_stats_mutex);
1836     rx_stats.packetsSent[p->header.type - 1]++;
1837     MUTEX_EXIT(&rx_stats_mutex);
1838     MUTEX_ENTER(&peer->peer_lock);
1839
1840     hadd32(peer->bytesSent, p->length);
1841     MUTEX_EXIT(&peer->peer_lock);
1842 }
1843
1844
1845 /* Send a "special" packet to the peer connection.  If call is
1846  * specified, then the packet is directed to a specific call channel
1847  * associated with the connection, otherwise it is directed to the
1848  * connection only. Uses optionalPacket if it is supplied, rather than
1849  * allocating a new packet buffer.  Nbytes is the length of the data
1850  * portion of the packet.  If data is non-null, nbytes of data are
1851  * copied into the packet.  Type is the type of the packet, as defined
1852  * in rx.h.  Bug: there's a lot of duplication between this and other
1853  * routines.  This needs to be cleaned up. */
1854 struct rx_packet *
1855 rxi_SendSpecial(register struct rx_call *call,
1856                 register struct rx_connection *conn,
1857                 struct rx_packet *optionalPacket, int type, char *data,
1858                 int nbytes, int istack)
1859 {
1860     /* Some of the following stuff should be common code for all
1861      * packet sends (it's repeated elsewhere) */
1862     register struct rx_packet *p;
1863     unsigned int i = 0;
1864     int savelen = 0, saven = 0;
1865     int channel, callNumber;
1866     if (call) {
1867         channel = call->channel;
1868         callNumber = *call->callNumber;
1869         /* BUSY packets refer to the next call on this connection */
1870         if (type == RX_PACKET_TYPE_BUSY) {
1871             callNumber++;
1872         }
1873     } else {
1874         channel = 0;
1875         callNumber = 0;
1876     }
1877     p = optionalPacket;
1878     if (!p) {
1879         p = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL);
1880         if (!p)
1881             osi_Panic("rxi_SendSpecial failure");
1882     }
1883
1884     if (nbytes != -1)
1885         p->length = nbytes;
1886     else
1887         nbytes = p->length;
1888     p->header.serviceId = conn->serviceId;
1889     p->header.securityIndex = conn->securityIndex;
1890     p->header.cid = (conn->cid | channel);
1891     p->header.callNumber = callNumber;
1892     p->header.seq = 0;
1893     p->header.epoch = conn->epoch;
1894     p->header.type = type;
1895     p->header.flags = 0;
1896     if (conn->type == RX_CLIENT_CONNECTION)
1897         p->header.flags |= RX_CLIENT_INITIATED;
1898     if (data)
1899         rx_packetwrite(p, 0, nbytes, data);
1900
1901     for (i = 1; i < p->niovecs; i++) {
1902         if (nbytes <= p->wirevec[i].iov_len) {
1903             savelen = p->wirevec[i].iov_len;
1904             saven = p->niovecs;
1905             p->wirevec[i].iov_len = nbytes;
1906             p->niovecs = i + 1; /* so condition fails because i == niovecs */
1907         } else
1908             nbytes -= p->wirevec[i].iov_len;
1909     }
1910
1911     if (call)
1912         rxi_Send(call, p, istack);
1913     else
1914         rxi_SendPacket((struct rx_call *)0, conn, p, istack);
1915     if (saven) {                /* means we truncated the packet above.  We probably don't  */
1916         /* really need to do this, but it seems safer this way, given that  */
1917         /* sneaky optionalPacket... */
1918         p->wirevec[i - 1].iov_len = savelen;
1919         p->niovecs = saven;
1920     }
1921     if (!optionalPacket)
1922         rxi_FreePacket(p);
1923     return optionalPacket;
1924 }
1925
1926
1927 /* Encode the packet's header (from the struct header in the packet to
1928  * the net byte order representation in the wire representation of the
1929  * packet, which is what is actually sent out on the wire) */
1930 void
1931 rxi_EncodePacketHeader(register struct rx_packet *p)
1932 {
1933     register afs_uint32 *buf = (afs_uint32 *) (p->wirevec[0].iov_base); /* MTUXXX */
1934
1935     memset((char *)buf, 0, RX_HEADER_SIZE);
1936     *buf++ = htonl(p->header.epoch);
1937     *buf++ = htonl(p->header.cid);
1938     *buf++ = htonl(p->header.callNumber);
1939     *buf++ = htonl(p->header.seq);
1940     *buf++ = htonl(p->header.serial);
1941     *buf++ = htonl((((afs_uint32) p->header.type) << 24)
1942                    | (((afs_uint32) p->header.flags) << 16)
1943                    | (p->header.userStatus << 8) | p->header.securityIndex);
1944     /* Note: top 16 bits of this next word were reserved */
1945     *buf++ = htonl((p->header.spare << 16) | (p->header.serviceId & 0xffff));
1946 }
1947
1948 /* Decode the packet's header (from net byte order to a struct header) */
1949 void
1950 rxi_DecodePacketHeader(register struct rx_packet *p)
1951 {
1952     register afs_uint32 *buf = (afs_uint32 *) (p->wirevec[0].iov_base); /* MTUXXX */
1953     afs_uint32 temp;
1954
1955     p->header.epoch = ntohl(*buf);
1956     buf++;
1957     p->header.cid = ntohl(*buf);
1958     buf++;
1959     p->header.callNumber = ntohl(*buf);
1960     buf++;
1961     p->header.seq = ntohl(*buf);
1962     buf++;
1963     p->header.serial = ntohl(*buf);
1964     buf++;
1965
1966     temp = ntohl(*buf);
1967     buf++;
1968
1969     /* C will truncate byte fields to bytes for me */
1970     p->header.type = temp >> 24;
1971     p->header.flags = temp >> 16;
1972     p->header.userStatus = temp >> 8;
1973     p->header.securityIndex = temp >> 0;
1974
1975     temp = ntohl(*buf);
1976     buf++;
1977
1978     p->header.serviceId = (temp & 0xffff);
1979     p->header.spare = temp >> 16;
1980     /* Note: top 16 bits of this last word are the security checksum */
1981 }
1982
1983 void
1984 rxi_PrepareSendPacket(register struct rx_call *call,
1985                       register struct rx_packet *p, register int last)
1986 {
1987     register struct rx_connection *conn = call->conn;
1988     int i, j;
1989     ssize_t len;                /* len must be a signed type; it can go negative */
1990
1991     p->flags &= ~RX_PKTFLAG_ACKED;
1992     p->header.cid = (conn->cid | call->channel);
1993     p->header.serviceId = conn->serviceId;
1994     p->header.securityIndex = conn->securityIndex;
1995     p->header.callNumber = *call->callNumber;
1996     p->header.seq = call->tnext++;
1997     p->header.epoch = conn->epoch;
1998     p->header.type = RX_PACKET_TYPE_DATA;
1999     p->header.flags = 0;
2000     p->header.spare = 0;
2001     if (conn->type == RX_CLIENT_CONNECTION)
2002         p->header.flags |= RX_CLIENT_INITIATED;
2003
2004     if (last)
2005         p->header.flags |= RX_LAST_PACKET;
2006
2007     clock_Zero(&p->retryTime);  /* Never yet transmitted */
2008     clock_Zero(&p->firstSent);  /* Never yet transmitted */
2009     p->header.serial = 0;       /* Another way of saying never transmitted... */
2010     p->backoff = 0;
2011
2012     /* Now that we're sure this is the last data on the call, make sure
2013      * that the "length" and the sum of the iov_lens matches. */
2014     len = p->length + call->conn->securityHeaderSize;
2015
2016     for (i = 1; i < p->niovecs && len > 0; i++) {
2017         len -= p->wirevec[i].iov_len;
2018     }
2019     if (len > 0) {
2020         osi_Panic("PrepareSendPacket 1\n");     /* MTUXXX */
2021     } else {
2022         /* Free any extra elements in the wirevec */
2023         for (j = MAX(2, i); j < p->niovecs; j++) {
2024             rxi_freeCBuf(RX_CBUF_TO_PACKET(p->wirevec[j].iov_base, p));
2025         }
2026         p->niovecs = i;
2027         p->wirevec[i - 1].iov_len += len;
2028     }
2029     RXS_PreparePacket(conn->securityObject, call, p);
2030 }
2031
2032 /* Given an interface MTU size, calculate an adjusted MTU size that
2033  * will make efficient use of the RX buffers when the peer is sending
2034  * either AFS 3.4a jumbograms or AFS 3.5 jumbograms.  */
2035 int
2036 rxi_AdjustIfMTU(int mtu)
2037 {
2038     int adjMTU;
2039     int frags;
2040
2041     adjMTU = RX_HEADER_SIZE + RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2042     if (mtu <= adjMTU) {
2043         return mtu;
2044     }
2045     mtu -= adjMTU;
2046     if (mtu <= 0) {
2047         return adjMTU;
2048     }
2049     frags = mtu / (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE);
2050     return (adjMTU + (frags * (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE)));
2051 }
2052
2053 /* Given an interface MTU size, and the peer's advertised max receive
2054  * size, calculate an adjisted maxMTU size that makes efficient use
2055  * of our packet buffers when we are sending AFS 3.4a jumbograms. */
2056 int
2057 rxi_AdjustMaxMTU(int mtu, int peerMaxMTU)
2058 {
2059     int maxMTU = mtu * rxi_nSendFrags;
2060     maxMTU = MIN(maxMTU, peerMaxMTU);
2061     return rxi_AdjustIfMTU(maxMTU);
2062 }
2063
2064 /* Given a packet size, figure out how many datagram packet will fit.
2065  * The first buffer always contains RX_HEADER_SIZE+RX_JUMBOBUFFERSIZE+
2066  * RX_JUMBOHEADERSIZE, the middle buffers contain RX_JUMBOBUFFERSIZE+
2067  * RX_JUMBOHEADERSIZE, and the last buffer contains RX_JUMBOBUFFERSIZE */
2068 int
2069 rxi_AdjustDgramPackets(int frags, int mtu)
2070 {
2071     int maxMTU;
2072     if (mtu + IPv6_FRAG_HDR_SIZE < RX_JUMBOBUFFERSIZE + RX_HEADER_SIZE) {
2073         return 1;
2074     }
2075     maxMTU = (frags * (mtu + UDP_HDR_SIZE)) - UDP_HDR_SIZE;
2076     maxMTU = MIN(maxMTU, RX_MAX_PACKET_SIZE);
2077     /* subtract the size of the first and last packets */
2078     maxMTU -= RX_HEADER_SIZE + (2 * RX_JUMBOBUFFERSIZE) + RX_JUMBOHEADERSIZE;
2079     if (maxMTU < 0) {
2080         return 1;
2081     }
2082     return (2 + (maxMTU / (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE)));
2083 }