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