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