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