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