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