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