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