rx-preparesendpacket-avoid-double-free-20061205
[openafs.git] / src / rx / rx_packet.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #ifdef KERNEL
12 #include "afs/param.h"
13 #else
14 #include <afs/param.h>
15 #endif
16
17 RCSID
18     ("$Header$");
19
20 #ifdef KERNEL
21 #if defined(UKERNEL)
22 #include "afs/sysincludes.h"
23 #include "afsincludes.h"
24 #include "rx/rx_kcommon.h"
25 #include "rx/rx_clock.h"
26 #include "rx/rx_queue.h"
27 #include "rx/rx_packet.h"
28 #else /* defined(UKERNEL) */
29 #ifdef RX_KERNEL_TRACE
30 #include "../rx/rx_kcommon.h"
31 #endif
32 #include "h/types.h"
33 #ifndef AFS_LINUX20_ENV
34 #include "h/systm.h"
35 #endif
36 #if defined(AFS_SGI_ENV) || defined(AFS_HPUX110_ENV)
37 #include "afs/sysincludes.h"
38 #endif
39 #if defined(AFS_OBSD_ENV)
40 #include "h/proc.h"
41 #endif
42 #include "h/socket.h"
43 #if !defined(AFS_SUN5_ENV) &&  !defined(AFS_LINUX20_ENV) && !defined(AFS_HPUX110_ENV)
44 #if     !defined(AFS_OSF_ENV) && !defined(AFS_AIX41_ENV)
45 #include "sys/mount.h"          /* it gets pulled in by something later anyway */
46 #endif
47 #include "h/mbuf.h"
48 #endif
49 #include "netinet/in.h"
50 #include "afs/afs_osi.h"
51 #include "rx_kmutex.h"
52 #include "rx/rx_clock.h"
53 #include "rx/rx_queue.h"
54 #ifdef  AFS_SUN5_ENV
55 #include <sys/sysmacros.h>
56 #endif
57 #include "rx/rx_packet.h"
58 #endif /* defined(UKERNEL) */
59 #include "rx/rx_globals.h"
60 #else /* KERNEL */
61 #include "sys/types.h"
62 #include <sys/stat.h>
63 #include <errno.h>
64 #if defined(AFS_NT40_ENV) 
65 #ifdef AFS_NT40_ENV
66 #include <winsock2.h>
67 #ifndef EWOULDBLOCK
68 #define EWOULDBLOCK WSAEWOULDBLOCK
69 #endif
70 #else
71 #include <sys/socket.h>
72 #include <netinet/in.h>
73 #endif /* AFS_NT40_ENV */
74 #include "rx_user.h"
75 #include "rx_xmit_nt.h"
76 #include <stdlib.h>
77 #else
78 #include <sys/socket.h>
79 #include <netinet/in.h>
80 #endif
81 #include "rx_clock.h"
82 #include "rx.h"
83 #include "rx_queue.h"
84 #ifdef  AFS_SUN5_ENV
85 #include <sys/sysmacros.h>
86 #endif
87 #include "rx_packet.h"
88 #include "rx_globals.h"
89 #include <lwp.h>
90 #include <assert.h>
91 #ifdef HAVE_STRING_H
92 #include <string.h>
93 #else
94 #ifdef HAVE_STRINGS_H
95 #include <strings.h>
96 #endif
97 #endif
98 #ifdef HAVE_UNISTD_H
99 #include <unistd.h>
100 #endif
101 #endif /* KERNEL */
102
103 #ifdef RX_LOCKS_DB
104 /* rxdb_fileID is used to identify the lock location, along with line#. */
105 static int rxdb_fileID = RXDB_FILE_RX_PACKET;
106 #endif /* RX_LOCKS_DB */
107 struct rx_packet *rx_mallocedP = 0;
108
109 extern char cml_version_number[];
110 extern int (*rx_almostSent) ();
111
112 static int AllocPacketBufs(int class, int num_pkts, struct rx_queue *q);
113
114 static void rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
115                                 struct sockaddr_storage *saddr, int slen,
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,
1354                struct sockaddr_storage *saddr, int *slen)
1355 {
1356     int nbytes;
1357     afs_int32 rlen;
1358     register afs_int32 tlen, savelen;
1359     struct msghdr msg;
1360     rx_computelen(p, tlen);
1361     rx_SetDataSize(p, tlen);    /* this is the size of the user data area */
1362
1363     tlen += RX_HEADER_SIZE;     /* now this is the size of the entire packet */
1364     rlen = rx_maxJumboRecvSize; /* this is what I am advertising.  Only check
1365                                  * it once in order to avoid races.  */
1366     tlen = rlen - tlen;
1367     if (tlen > 0) {
1368         tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_SEND_CBUF);
1369         if (tlen > 0) {
1370             tlen = rlen - tlen;
1371         } else
1372             tlen = rlen;
1373     } else
1374         tlen = rlen;
1375
1376     /* Extend the last iovec for padding, it's just to make sure that the 
1377      * read doesn't return more data than we expect, and is done to get around
1378      * our problems caused by the lack of a length field in the rx header.
1379      * Use the extra buffer that follows the localdata in each packet
1380      * structure. */
1381     savelen = p->wirevec[p->niovecs - 1].iov_len;
1382     p->wirevec[p->niovecs - 1].iov_len += RX_EXTRABUFFERSIZE;
1383
1384     memset((char *)&msg, 0, sizeof(msg));
1385     msg.msg_name = (char *)saddr;
1386     msg.msg_namelen = *slen;
1387     msg.msg_iov = p->wirevec;
1388     msg.msg_iovlen = p->niovecs;
1389     nbytes = rxi_Recvmsg(socket, &msg, 0);
1390     *slen = msg.msg_namelen;
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 && errno == EWOULDBLOCK) {
1398             MUTEX_ENTER(&rx_stats_mutex);
1399             rx_stats.noPacketOnRead++;
1400             MUTEX_EXIT(&rx_stats_mutex);
1401         } else if (nbytes <= 0) {
1402             MUTEX_ENTER(&rx_stats_mutex);
1403             rx_stats.bogusPacketOnRead++;
1404             switch (rx_ssfamily(saddr)) {
1405                 case AF_INET:
1406                     rx_stats.bogusHost = rx_ss2sin(saddr)->sin_addr.s_addr;
1407                     break;
1408                 default:
1409 #ifdef AF_INET6
1410                 case AF_INET6:
1411 #endif /* AF_INET6 */
1412                     rx_stats.bogusHost = 0xffffffff;
1413                 break;
1414             }
1415             MUTEX_EXIT(&rx_stats_mutex);
1416             dpf(("B: bogus packet from [%x,%d] nb=%d",
1417                  ntohl(rx_ss2v4addr(saddr)), ntohs(rx_ss2pn(saddr)), nbytes));
1418         }
1419         return 0;
1420     } 
1421 #ifdef RXDEBUG
1422     else if ((rx_intentionallyDroppedOnReadPer100 > 0)
1423                 && (random() % 100 < rx_intentionallyDroppedOnReadPer100)) {
1424         rxi_DecodePacketHeader(p);
1425
1426         dpf(("Dropped %d %s: %x.%u.%u.%u.%u.%u.%u flags %d len %d",
1427               p->header.serial, rx_packetTypes[p->header.type - 1], ntohl(rx_ss2v4addr(saddr)), ntohs(rx_ss2pn(saddr)), p->header.serial, 
1428               p->header.epoch, p->header.cid, p->header.callNumber, p->header.seq, p->header.flags, 
1429               p->length));
1430         rxi_TrimDataBufs(p, 1);
1431         return 0;
1432     } 
1433 #endif
1434     else {
1435         /* Extract packet header. */
1436         rxi_DecodePacketHeader(p);
1437
1438         if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
1439             struct rx_peer *peer;
1440             MUTEX_ENTER(&rx_stats_mutex);
1441             rx_stats.packetsRead[p->header.type - 1]++;
1442             MUTEX_EXIT(&rx_stats_mutex);
1443             /*
1444              * Try to look up this peer structure.  If it doesn't exist,
1445              * don't create a new one - 
1446              * we don't keep count of the bytes sent/received if a peer
1447              * structure doesn't already exist.
1448              *
1449              * The peer/connection cleanup code assumes that there is 1 peer
1450              * per connection.  If we actually created a peer structure here
1451              * and this packet was an rxdebug packet, the peer structure would
1452              * never be cleaned up.
1453              */
1454             peer = rxi_FindPeer(saddr, *slen, SOCK_DGRAM, 0, 0);
1455             /* Since this may not be associated with a connection,
1456              * it may have no refCount, meaning we could race with
1457              * ReapConnections
1458              */
1459             if (peer && (peer->refCount > 0)) {
1460                 MUTEX_ENTER(&peer->peer_lock);
1461                 hadd32(peer->bytesReceived, p->length);
1462                 MUTEX_EXIT(&peer->peer_lock);
1463             }
1464         }
1465
1466         /* Free any empty packet buffers at the end of this packet */
1467         rxi_TrimDataBufs(p, 1);
1468
1469         return 1;
1470     }
1471 }
1472
1473 #endif /* !KERNEL || UKERNEL */
1474
1475 /* This function splits off the first packet in a jumbo packet.
1476  * As of AFS 3.5, jumbograms contain more than one fixed size
1477  * packet, and the RX_JUMBO_PACKET flag is set in all but the
1478  * last packet header. All packets (except the last) are padded to
1479  * fall on RX_CBUFFERSIZE boundaries.
1480  * HACK: We store the length of the first n-1 packets in the
1481  * last two pad bytes. */
1482
1483 struct rx_packet *
1484 rxi_SplitJumboPacket(register struct rx_packet *p,
1485                      struct sockaddr_storage *saddr, int slen, int first)
1486 {
1487     struct rx_packet *np;
1488     struct rx_jumboHeader *jp;
1489     int niov, i;
1490     struct iovec *iov;
1491     int length;
1492     afs_uint32 temp;
1493
1494     /* All but the last packet in each jumbogram are RX_JUMBOBUFFERSIZE
1495      * bytes in length. All but the first packet are preceded by
1496      * an abbreviated four byte header. The length of the last packet
1497      * is calculated from the size of the jumbogram. */
1498     length = RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
1499
1500     if ((int)p->length < length) {
1501         dpf(("rxi_SplitJumboPacket: bogus length %d\n", p->length));
1502         return NULL;
1503     }
1504     niov = p->niovecs - 2;
1505     if (niov < 1) {
1506         dpf(("rxi_SplitJumboPacket: bogus niovecs %d\n", p->niovecs));
1507         return NULL;
1508     }
1509     iov = &p->wirevec[2];
1510     np = RX_CBUF_TO_PACKET(iov->iov_base, p);
1511
1512     /* Get a pointer to the abbreviated packet header */
1513     jp = (struct rx_jumboHeader *)
1514         ((char *)(p->wirevec[1].iov_base) + RX_JUMBOBUFFERSIZE);
1515
1516     /* Set up the iovecs for the next packet */
1517     np->wirevec[0].iov_base = (char *)(&np->wirehead[0]);
1518     np->wirevec[0].iov_len = sizeof(struct rx_header);
1519     np->wirevec[1].iov_base = (char *)(&np->localdata[0]);
1520     np->wirevec[1].iov_len = length - RX_JUMBOHEADERSIZE;
1521     np->niovecs = niov + 1;
1522     for (i = 2, iov++; i <= niov; i++, iov++) {
1523         np->wirevec[i] = *iov;
1524     }
1525     np->length = p->length - length;
1526     p->length = RX_JUMBOBUFFERSIZE;
1527     p->niovecs = 2;
1528
1529     /* Convert the jumbo packet header to host byte order */
1530     temp = ntohl(*(afs_uint32 *) jp);
1531     jp->flags = (u_char) (temp >> 24);
1532     jp->cksum = (u_short) (temp);
1533
1534     /* Fill in the packet header */
1535     np->header = p->header;
1536     np->header.serial = p->header.serial + 1;
1537     np->header.seq = p->header.seq + 1;
1538     np->header.flags = jp->flags;
1539     np->header.spare = jp->cksum;
1540
1541     return np;
1542 }
1543
1544 #ifndef KERNEL
1545 /* Send a udp datagram */
1546 int
1547 osi_NetSend(osi_socket socket, void *addr, int addrlen, struct iovec *dvec,
1548             int nvecs, int length, int istack)
1549 {
1550     struct msghdr msg;
1551         int ret;
1552
1553     memset(&msg, 0, sizeof(msg));
1554     msg.msg_iov = dvec;
1555     msg.msg_iovlen = nvecs;
1556     msg.msg_name = addr;
1557     msg.msg_namelen = addrlen;
1558
1559     ret = rxi_Sendmsg(socket, &msg, 0);
1560
1561     return ret;
1562 }
1563 #elif !defined(UKERNEL)
1564 /*
1565  * message receipt is done in rxk_input or rx_put.
1566  */
1567
1568 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX110_ENV)
1569 /*
1570  * Copy an mblock to the contiguous area pointed to by cp.
1571  * MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
1572  * but it doesn't really.
1573  * Returns the number of bytes not transferred.
1574  * The message is NOT changed.
1575  */
1576 static int
1577 cpytoc(mblk_t * mp, register int off, register int len, register char *cp)
1578 {
1579     register int n;
1580
1581     for (; mp && len > 0; mp = mp->b_cont) {
1582         if (mp->b_datap->db_type != M_DATA) {
1583             return -1;
1584         }
1585         n = MIN(len, (mp->b_wptr - mp->b_rptr));
1586         memcpy(cp, (char *)mp->b_rptr, n);
1587         cp += n;
1588         len -= n;
1589         mp->b_rptr += n;
1590     }
1591     return (len);
1592 }
1593
1594 /* MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
1595  * but it doesn't really.  
1596  * This sucks, anyway, do it like m_cpy.... below 
1597  */
1598 static int
1599 cpytoiovec(mblk_t * mp, int off, int len, register struct iovec *iovs,
1600            int niovs)
1601 {
1602     register int m, n, o, t, i;
1603
1604     for (i = -1, t = 0; i < niovs && mp && len > 0; mp = mp->b_cont) {
1605         if (mp->b_datap->db_type != M_DATA) {
1606             return -1;
1607         }
1608         n = MIN(len, (mp->b_wptr - mp->b_rptr));
1609         len -= n;
1610         while (n) {
1611             if (!t) {
1612                 o = 0;
1613                 i++;
1614                 t = iovs[i].iov_len;
1615             }
1616             m = MIN(n, t);
1617             memcpy(iovs[i].iov_base + o, (char *)mp->b_rptr, m);
1618             mp->b_rptr += m;
1619             o += m;
1620             t -= m;
1621             n -= m;
1622         }
1623     }
1624     return (len);
1625 }
1626
1627 #define m_cpytoc(a, b, c, d)  cpytoc(a, b, c, d)
1628 #define m_cpytoiovec(a, b, c, d, e) cpytoiovec(a, b, c, d, e)
1629 #else
1630 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV)
1631 static int
1632 m_cpytoiovec(struct mbuf *m, int off, int len, struct iovec iovs[], int niovs)
1633 {
1634     caddr_t p1, p2;
1635     unsigned int l1, l2, i, t;
1636
1637     if (m == NULL || off < 0 || len < 0 || iovs == NULL)
1638         osi_Panic("m_cpytoiovec");      /* MTUXXX probably don't need this check */
1639
1640     while (off && m)
1641         if (m->m_len <= off) {
1642             off -= m->m_len;
1643             m = m->m_next;
1644             continue;
1645         } else
1646             break;
1647
1648     if (m == NULL)
1649         return len;
1650
1651     p1 = mtod(m, caddr_t) + off;
1652     l1 = m->m_len - off;
1653     i = 0;
1654     p2 = iovs[0].iov_base;
1655     l2 = iovs[0].iov_len;
1656
1657     while (len) {
1658         t = MIN(l1, MIN(l2, (unsigned int)len));
1659         memcpy(p2, p1, t);
1660         p1 += t;
1661         p2 += t;
1662         l1 -= t;
1663         l2 -= t;
1664         len -= t;
1665         if (!l1) {
1666             m = m->m_next;
1667             if (!m)
1668                 break;
1669             p1 = mtod(m, caddr_t);
1670             l1 = m->m_len;
1671         }
1672         if (!l2) {
1673             if (++i >= niovs)
1674                 break;
1675             p2 = iovs[i].iov_base;
1676             l2 = iovs[i].iov_len;
1677         }
1678
1679     }
1680
1681     return len;
1682 }
1683 #endif /* LINUX */
1684 #endif /* AFS_SUN5_ENV */
1685
1686 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV)
1687 int
1688 rx_mb_to_packet(amb, free, hdr_len, data_len, phandle)
1689 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX110_ENV)
1690      mblk_t *amb;
1691 #else
1692      struct mbuf *amb;
1693 #endif
1694      void (*free) ();
1695      struct rx_packet *phandle;
1696      int hdr_len, data_len;
1697 {
1698     register int code;
1699
1700     code =
1701         m_cpytoiovec(amb, hdr_len, data_len, phandle->wirevec,
1702                      phandle->niovecs);
1703     (*free) (amb);
1704
1705     return code;
1706 }
1707 #endif /* LINUX */
1708 #endif /*KERNEL && !UKERNEL */
1709
1710
1711 /* send a response to a debug packet */
1712
1713 struct rx_packet *
1714 rxi_ReceiveDebugPacket(register struct rx_packet *ap, osi_socket asocket,
1715                        struct sockaddr_storage *saddr, int slen, int istack)
1716 {
1717     struct rx_debugIn tin;
1718     afs_int32 tl;
1719     struct rx_serverQueueEntry *np, *nqe;
1720
1721     /*
1722      * Only respond to client-initiated Rx debug packets,
1723      * and clear the client flag in the response.
1724      */
1725     if (ap->header.flags & RX_CLIENT_INITIATED) {
1726         ap->header.flags = ap->header.flags & ~RX_CLIENT_INITIATED;
1727         rxi_EncodePacketHeader(ap);
1728     } else {
1729         return ap;
1730     }
1731
1732     rx_packetread(ap, 0, sizeof(struct rx_debugIn), (char *)&tin);
1733     /* all done with packet, now set length to the truth, so we can 
1734      * reuse this packet */
1735     rx_computelen(ap, ap->length);
1736
1737     tin.type = ntohl(tin.type);
1738     tin.index = ntohl(tin.index);
1739     switch (tin.type) {
1740     case RX_DEBUGI_GETSTATS:{
1741             struct rx_debugStats tstat;
1742
1743             /* get basic stats */
1744             memset((char *)&tstat, 0, sizeof(tstat));   /* make sure spares are zero */
1745             tstat.version = RX_DEBUGI_VERSION;
1746 #ifndef RX_ENABLE_LOCKS
1747             tstat.waitingForPackets = rx_waitingForPackets;
1748 #endif
1749             MUTEX_ENTER(&rx_serverPool_lock);
1750             tstat.nFreePackets = htonl(rx_nFreePackets);
1751             tstat.callsExecuted = htonl(rxi_nCalls);
1752             tstat.packetReclaims = htonl(rx_packetReclaims);
1753             tstat.usedFDs = CountFDs(64);
1754             tstat.nWaiting = htonl(rx_nWaiting);
1755             tstat.nWaited = htonl(rx_nWaited);
1756             queue_Count(&rx_idleServerQueue, np, nqe, rx_serverQueueEntry,
1757                         tstat.idleThreads);
1758             MUTEX_EXIT(&rx_serverPool_lock);
1759             tstat.idleThreads = htonl(tstat.idleThreads);
1760             tl = sizeof(struct rx_debugStats) - ap->length;
1761             if (tl > 0)
1762                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1763
1764             if (tl <= 0) {
1765                 rx_packetwrite(ap, 0, sizeof(struct rx_debugStats),
1766                                (char *)&tstat);
1767                 ap->length = sizeof(struct rx_debugStats);
1768                 rxi_SendDebugPacket(ap, asocket, saddr, slen, istack);
1769                 rx_computelen(ap, ap->length);
1770             }
1771             break;
1772         }
1773
1774     case RX_DEBUGI_GETALLCONN:
1775     case RX_DEBUGI_GETCONN:{
1776             int i, j;
1777             register struct rx_connection *tc;
1778             struct rx_call *tcall;
1779             struct rx_debugConn tconn;
1780             int all = (tin.type == RX_DEBUGI_GETALLCONN);
1781
1782
1783             tl = sizeof(struct rx_debugConn) - ap->length;
1784             if (tl > 0)
1785                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1786             if (tl > 0)
1787                 return ap;
1788
1789             memset((char *)&tconn, 0, sizeof(tconn));   /* make sure spares are zero */
1790             /* get N'th (maybe) "interesting" connection info */
1791             for (i = 0; i < rx_hashTableSize; i++) {
1792 #if !defined(KERNEL)
1793                 /* the time complexity of the algorithm used here
1794                  * exponentially increses with the number of connections.
1795                  */
1796 #ifdef AFS_PTHREAD_ENV
1797                 pthread_yield();
1798 #else
1799                 (void)IOMGR_Poll();
1800 #endif
1801 #endif
1802                 MUTEX_ENTER(&rx_connHashTable_lock);
1803                 /* We might be slightly out of step since we are not 
1804                  * locking each call, but this is only debugging output.
1805                  */
1806                 for (tc = rx_connHashTable[i]; tc; tc = tc->next) {
1807                     if ((all || rxi_IsConnInteresting(tc))
1808                         && tin.index-- <= 0) {
1809                         switch (rx_ssfamily(&tc->peer->saddr)) {
1810                         case AF_INET:
1811                             tconn.host = rx_ss2sin(&tc->peer->saddr)->sin_addr.s_addr;
1812                             break;
1813                         default:
1814 #ifdef AF_INET6
1815                         case AF_INET6:
1816 #endif /* AF_INET6 */
1817                             tconn.host = 0xffffffff;
1818                             break;
1819                         }
1820                         tconn.port = rx_ss2pn(&tc->peer->saddr);
1821                         tconn.cid = htonl(tc->cid);
1822                         tconn.epoch = htonl(tc->epoch);
1823                         tconn.serial = htonl(tc->serial);
1824                         for (j = 0; j < RX_MAXCALLS; j++) {
1825                             tconn.callNumber[j] = htonl(tc->callNumber[j]);
1826                             if ((tcall = tc->call[j])) {
1827                                 tconn.callState[j] = tcall->state;
1828                                 tconn.callMode[j] = tcall->mode;
1829                                 tconn.callFlags[j] = tcall->flags;
1830                                 if (queue_IsNotEmpty(&tcall->rq))
1831                                     tconn.callOther[j] |= RX_OTHER_IN;
1832                                 if (queue_IsNotEmpty(&tcall->tq))
1833                                     tconn.callOther[j] |= RX_OTHER_OUT;
1834                             } else
1835                                 tconn.callState[j] = RX_STATE_NOTINIT;
1836                         }
1837
1838                         tconn.natMTU = htonl(tc->peer->natMTU);
1839                         tconn.error = htonl(tc->error);
1840                         tconn.flags = tc->flags;
1841                         tconn.type = tc->type;
1842                         tconn.securityIndex = tc->securityIndex;
1843                         if (tc->securityObject) {
1844                             RXS_GetStats(tc->securityObject, tc,
1845                                          &tconn.secStats);
1846 #define DOHTONL(a) (tconn.secStats.a = htonl(tconn.secStats.a))
1847 #define DOHTONS(a) (tconn.secStats.a = htons(tconn.secStats.a))
1848                             DOHTONL(flags);
1849                             DOHTONL(expires);
1850                             DOHTONL(packetsReceived);
1851                             DOHTONL(packetsSent);
1852                             DOHTONL(bytesReceived);
1853                             DOHTONL(bytesSent);
1854                             for (i = 0;
1855                                  i <
1856                                  sizeof(tconn.secStats.spares) /
1857                                  sizeof(short); i++)
1858                                 DOHTONS(spares[i]);
1859                             for (i = 0;
1860                                  i <
1861                                  sizeof(tconn.secStats.sparel) /
1862                                  sizeof(afs_int32); i++)
1863                                 DOHTONL(sparel[i]);
1864                         }
1865
1866                         MUTEX_EXIT(&rx_connHashTable_lock);
1867                         rx_packetwrite(ap, 0, sizeof(struct rx_debugConn),
1868                                        (char *)&tconn);
1869                         tl = ap->length;
1870                         ap->length = sizeof(struct rx_debugConn);
1871                         rxi_SendDebugPacket(ap, asocket, saddr, slen,
1872                                             istack);
1873                         ap->length = tl;
1874                         return ap;
1875                     }
1876                 }
1877                 MUTEX_EXIT(&rx_connHashTable_lock);
1878             }
1879             /* if we make it here, there are no interesting packets */
1880             tconn.cid = htonl(0xffffffff);      /* means end */
1881             rx_packetwrite(ap, 0, sizeof(struct rx_debugConn),
1882                            (char *)&tconn);
1883             tl = ap->length;
1884             ap->length = sizeof(struct rx_debugConn);
1885             rxi_SendDebugPacket(ap, asocket, saddr, slen, istack);
1886             ap->length = tl;
1887             break;
1888         }
1889
1890         /*
1891          * Pass back all the peer structures we have available
1892          */
1893
1894     case RX_DEBUGI_GETPEER:{
1895             int i;
1896             register struct rx_peer *tp;
1897             struct rx_debugPeer tpeer;
1898
1899
1900             tl = sizeof(struct rx_debugPeer) - ap->length;
1901             if (tl > 0)
1902                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1903             if (tl > 0)
1904                 return ap;
1905
1906             memset((char *)&tpeer, 0, sizeof(tpeer));
1907             for (i = 0; i < rx_hashTableSize; i++) {
1908 #if !defined(KERNEL)
1909                 /* the time complexity of the algorithm used here
1910                  * exponentially increses with the number of peers.
1911                  *
1912                  * Yielding after processing each hash table entry
1913                  * and dropping rx_peerHashTable_lock.
1914                  * also increases the risk that we will miss a new
1915                  * entry - but we are willing to live with this
1916                  * limitation since this is meant for debugging only
1917                  */
1918 #ifdef AFS_PTHREAD_ENV
1919                 pthread_yield();
1920 #else
1921                 (void)IOMGR_Poll();
1922 #endif
1923 #endif
1924                 MUTEX_ENTER(&rx_peerHashTable_lock);
1925                 for (tp = rx_peerHashTable[i]; tp; tp = tp->next) {
1926                     if (tin.index-- <= 0) {
1927                         switch (rx_ssfamily(&tp->saddr)) {
1928                         case AF_INET:
1929                             tpeer.host = rx_ss2sin(&tp->saddr)->sin_addr.s_addr;
1930                             break;
1931                         default:
1932 #ifdef AF_INET6
1933                         case AF_INET6:
1934 #endif /* AF_INET6 */
1935                             tpeer.host = 0xffffffff;
1936                             break;
1937                         }
1938                         tpeer.port = rx_ss2pn(&tp->saddr);
1939                         tpeer.ifMTU = htons(tp->ifMTU);
1940                         tpeer.idleWhen = htonl(tp->idleWhen);
1941                         tpeer.refCount = htons(tp->refCount);
1942                         tpeer.burstSize = tp->burstSize;
1943                         tpeer.burst = tp->burst;
1944                         tpeer.burstWait.sec = htonl(tp->burstWait.sec);
1945                         tpeer.burstWait.usec = htonl(tp->burstWait.usec);
1946                         tpeer.rtt = htonl(tp->rtt);
1947                         tpeer.rtt_dev = htonl(tp->rtt_dev);
1948                         tpeer.timeout.sec = htonl(tp->timeout.sec);
1949                         tpeer.timeout.usec = htonl(tp->timeout.usec);
1950                         tpeer.nSent = htonl(tp->nSent);
1951                         tpeer.reSends = htonl(tp->reSends);
1952                         tpeer.inPacketSkew = htonl(tp->inPacketSkew);
1953                         tpeer.outPacketSkew = htonl(tp->outPacketSkew);
1954                         tpeer.rateFlag = htonl(tp->rateFlag);
1955                         tpeer.natMTU = htons(tp->natMTU);
1956                         tpeer.maxMTU = htons(tp->maxMTU);
1957                         tpeer.maxDgramPackets = htons(tp->maxDgramPackets);
1958                         tpeer.ifDgramPackets = htons(tp->ifDgramPackets);
1959                         tpeer.MTU = htons(tp->MTU);
1960                         tpeer.cwind = htons(tp->cwind);
1961                         tpeer.nDgramPackets = htons(tp->nDgramPackets);
1962                         tpeer.congestSeq = htons(tp->congestSeq);
1963                         tpeer.bytesSent.high = htonl(tp->bytesSent.high);
1964                         tpeer.bytesSent.low = htonl(tp->bytesSent.low);
1965                         tpeer.bytesReceived.high =
1966                             htonl(tp->bytesReceived.high);
1967                         tpeer.bytesReceived.low =
1968                             htonl(tp->bytesReceived.low);
1969
1970                         MUTEX_EXIT(&rx_peerHashTable_lock);
1971                         rx_packetwrite(ap, 0, sizeof(struct rx_debugPeer),
1972                                        (char *)&tpeer);
1973                         tl = ap->length;
1974                         ap->length = sizeof(struct rx_debugPeer);
1975                         rxi_SendDebugPacket(ap, asocket, saddr, slen,
1976                                             istack);
1977                         ap->length = tl;
1978                         return ap;
1979                     }
1980                 }
1981                 MUTEX_EXIT(&rx_peerHashTable_lock);
1982             }
1983             /* if we make it here, there are no interesting packets */
1984             tpeer.host = htonl(0xffffffff);     /* means end */
1985             rx_packetwrite(ap, 0, sizeof(struct rx_debugPeer),
1986                            (char *)&tpeer);
1987             tl = ap->length;
1988             ap->length = sizeof(struct rx_debugPeer);
1989             rxi_SendDebugPacket(ap, asocket, saddr, slen, istack);
1990             ap->length = tl;
1991             break;
1992         }
1993
1994     case RX_DEBUGI_RXSTATS:{
1995             int i;
1996             afs_int32 *s;
1997
1998             tl = sizeof(rx_stats) - ap->length;
1999             if (tl > 0)
2000                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
2001             if (tl > 0)
2002                 return ap;
2003
2004             /* Since its all int32s convert to network order with a loop. */
2005             MUTEX_ENTER(&rx_stats_mutex);
2006             s = (afs_int32 *) & rx_stats;
2007             for (i = 0; i < sizeof(rx_stats) / sizeof(afs_int32); i++, s++)
2008                 rx_PutInt32(ap, i * sizeof(afs_int32), htonl(*s));
2009
2010             tl = ap->length;
2011             ap->length = sizeof(rx_stats);
2012             MUTEX_EXIT(&rx_stats_mutex);
2013             rxi_SendDebugPacket(ap, asocket, saddr, slen, istack);
2014             ap->length = tl;
2015             break;
2016         }
2017
2018     default:
2019         /* error response packet */
2020         tin.type = htonl(RX_DEBUGI_BADTYPE);
2021         tin.index = tin.type;
2022         rx_packetwrite(ap, 0, sizeof(struct rx_debugIn), (char *)&tin);
2023         tl = ap->length;
2024         ap->length = sizeof(struct rx_debugIn);
2025         rxi_SendDebugPacket(ap, asocket, saddr, slen, istack);
2026         ap->length = tl;
2027         break;
2028     }
2029     return ap;
2030 }
2031
2032 struct rx_packet *
2033 rxi_ReceiveVersionPacket(register struct rx_packet *ap, osi_socket asocket,
2034                          struct sockaddr_storage *saddr, int slen, int istack)
2035 {
2036     afs_int32 tl;
2037
2038     /*
2039      * Only respond to client-initiated version requests, and
2040      * clear that flag in the response.
2041      */
2042     if (ap->header.flags & RX_CLIENT_INITIATED) {
2043         char buf[66];
2044
2045         ap->header.flags = ap->header.flags & ~RX_CLIENT_INITIATED;
2046         rxi_EncodePacketHeader(ap);
2047         memset(buf, 0, sizeof(buf));
2048         strncpy(buf, cml_version_number + 4, sizeof(buf) - 1);
2049         rx_packetwrite(ap, 0, 65, buf);
2050         tl = ap->length;
2051         ap->length = 65;
2052         rxi_SendDebugPacket(ap, asocket, saddr, slen, istack);
2053         ap->length = tl;
2054     }
2055
2056     return ap;
2057 }
2058
2059
2060 /* send a debug packet back to the sender */
2061 static void
2062 rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
2063                     struct sockaddr_storage *saddr, int slen, afs_int32 istack)
2064 {
2065     int i;
2066     int nbytes;
2067     int saven = 0;
2068     size_t savelen = 0;
2069 #ifdef KERNEL
2070     int waslocked = ISAFS_GLOCK();
2071 #endif
2072
2073     /* We need to trim the niovecs. */
2074     nbytes = apacket->length;
2075     for (i = 1; i < apacket->niovecs; i++) {
2076         if (nbytes <= apacket->wirevec[i].iov_len) {
2077             savelen = apacket->wirevec[i].iov_len;
2078             saven = apacket->niovecs;
2079             apacket->wirevec[i].iov_len = nbytes;
2080             apacket->niovecs = i + 1;   /* so condition fails because i == niovecs */
2081         } else
2082             nbytes -= apacket->wirevec[i].iov_len;
2083     }
2084 #ifdef KERNEL
2085 #ifdef RX_KERNEL_TRACE
2086     if (ICL_SETACTIVE(afs_iclSetp)) {
2087         if (!waslocked)
2088             AFS_GLOCK();
2089         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2090                    "before osi_NetSend()");
2091         AFS_GUNLOCK();
2092     } else
2093 #else
2094     if (waslocked)
2095         AFS_GUNLOCK();
2096 #endif
2097 #endif
2098     /* debug packets are not reliably delivered, hence the cast below. */
2099     (void)osi_NetSend(asocket, saddr, slen, apacket->wirevec, apacket->niovecs,
2100                       apacket->length + RX_HEADER_SIZE, istack);
2101 #ifdef KERNEL
2102 #ifdef RX_KERNEL_TRACE
2103     if (ICL_SETACTIVE(afs_iclSetp)) {
2104         AFS_GLOCK();
2105         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2106                    "after osi_NetSend()");
2107         if (!waslocked)
2108             AFS_GUNLOCK();
2109     } else
2110 #else
2111     if (waslocked)
2112         AFS_GLOCK();
2113 #endif
2114 #endif
2115     if (saven) {                /* means we truncated the packet above. */
2116         apacket->wirevec[i - 1].iov_len = savelen;
2117         apacket->niovecs = saven;
2118     }
2119
2120 }
2121
2122 /* Send the packet to appropriate destination for the specified
2123  * call.  The header is first encoded and placed in the packet.
2124  */
2125 void
2126 rxi_SendPacket(struct rx_call *call, struct rx_connection *conn,
2127                struct rx_packet *p, int istack)
2128 {
2129 #if defined(KERNEL)
2130     int waslocked;
2131 #endif
2132     int code;
2133     register struct rx_peer *peer = conn->peer;
2134     osi_socket socket;
2135 #ifdef RXDEBUG
2136     char deliveryType = 'S';
2137 #endif
2138     /* This stuff should be revamped, I think, so that most, if not
2139      * all, of the header stuff is always added here.  We could
2140      * probably do away with the encode/decode routines. XXXXX */
2141
2142     /* Stamp each packet with a unique serial number.  The serial
2143      * number is maintained on a connection basis because some types
2144      * of security may be based on the serial number of the packet,
2145      * and security is handled on a per authenticated-connection
2146      * basis. */
2147     /* Pre-increment, to guarantee no zero serial number; a zero
2148      * serial number means the packet was never sent. */
2149     MUTEX_ENTER(&conn->conn_data_lock);
2150     p->header.serial = ++conn->serial;
2151     MUTEX_EXIT(&conn->conn_data_lock);
2152     /* This is so we can adjust retransmit time-outs better in the face of 
2153      * rapidly changing round-trip times.  RTO estimation is not a la Karn.
2154      */
2155     if (p->firstSerial == 0) {
2156         p->firstSerial = p->header.serial;
2157     }
2158 #ifdef RXDEBUG
2159     /* If an output tracer function is defined, call it with the packet and
2160      * network address.  Note this function may modify its arguments. */
2161     if (rx_almostSent) {
2162         int drop = (*rx_almostSent) (p, &peer->saddr);
2163         /* drop packet if return value is non-zero? */
2164         if (drop)
2165             deliveryType = 'D'; /* Drop the packet */
2166     }
2167 #endif
2168
2169     /* Get network byte order header */
2170     rxi_EncodePacketHeader(p);  /* XXX in the event of rexmit, etc, don't need to 
2171                                  * touch ALL the fields */
2172
2173     /* Send the packet out on the same socket that related packets are being
2174      * received on */
2175     socket =
2176         (conn->type ==
2177          RX_CLIENT_CONNECTION ? rx_socket : conn->service->socket);
2178
2179 #ifdef RXDEBUG
2180     /* Possibly drop this packet,  for testing purposes */
2181     if ((deliveryType == 'D')
2182         || ((rx_intentionallyDroppedPacketsPer100 > 0)
2183             && (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
2184         deliveryType = 'D';     /* Drop the packet */
2185     } else {
2186         deliveryType = 'S';     /* Send the packet */
2187 #endif /* RXDEBUG */
2188
2189         /* Loop until the packet is sent.  We'd prefer just to use a
2190          * blocking socket, but unfortunately the interface doesn't
2191          * allow us to have the socket block in send mode, and not
2192          * block in receive mode */
2193 #ifdef KERNEL
2194         waslocked = ISAFS_GLOCK();
2195 #ifdef RX_KERNEL_TRACE
2196         if (ICL_SETACTIVE(afs_iclSetp)) {
2197             if (!waslocked)
2198                 AFS_GLOCK();
2199             afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2200                        "before osi_NetSend()");
2201             AFS_GUNLOCK();
2202         } else
2203 #else
2204         if (waslocked)
2205             AFS_GUNLOCK();
2206 #endif
2207 #endif
2208         if ((code =
2209              osi_NetSend(socket, &peer->saddr, peer->saddrlen, p->wirevec,
2210                          p->niovecs, p->length + RX_HEADER_SIZE,
2211                          istack)) != 0) {
2212             /* send failed, so let's hurry up the resend, eh? */
2213             MUTEX_ENTER(&rx_stats_mutex);
2214             rx_stats.netSendFailures++;
2215             MUTEX_EXIT(&rx_stats_mutex);
2216             p->retryTime = p->timeSent; /* resend it very soon */
2217             clock_Addmsec(&(p->retryTime),
2218                           10 + (((afs_uint32) p->backoff) << 8));
2219
2220 #ifdef AFS_NT40_ENV
2221             /* Windows is nice -- it can tell us right away that we cannot
2222              * reach this recipient by returning an WSAEHOSTUNREACH 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 == -1 && errno == WSAEHOSTUNREACH)
2227                         call->lastReceiveTime = 0;
2228 #endif
2229 #if defined(KERNEL) && defined(AFS_LINUX20_ENV)
2230             /* Linux is nice -- it can tell us right away that we cannot
2231              * reach this recipient by returning an ENETUNREACH error
2232              * code.  So, when this happens let's "down" the host NOW so
2233              * we don't sit around waiting for this host to timeout later.
2234              */
2235             if (call && code == -ENETUNREACH)
2236                 call->lastReceiveTime = 0;
2237 #endif
2238         }
2239 #ifdef KERNEL
2240 #ifdef RX_KERNEL_TRACE
2241         if (ICL_SETACTIVE(afs_iclSetp)) {
2242             AFS_GLOCK();
2243             afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2244                        "after osi_NetSend()");
2245             if (!waslocked)
2246                 AFS_GUNLOCK();
2247         } else
2248 #else
2249         if (waslocked)
2250             AFS_GLOCK();
2251 #endif
2252 #endif
2253 #ifdef RXDEBUG
2254     }
2255     dpf(("%c %d %s: %s.%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], rx_AddrStringOf(peer), ntohs(rx_PortOf(peer)), 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));
2256 #endif
2257     MUTEX_ENTER(&rx_stats_mutex);
2258     rx_stats.packetsSent[p->header.type - 1]++;
2259     MUTEX_EXIT(&rx_stats_mutex);
2260     MUTEX_ENTER(&peer->peer_lock);
2261     hadd32(peer->bytesSent, p->length);
2262     MUTEX_EXIT(&peer->peer_lock);
2263 }
2264
2265 /* Send a list of packets to appropriate destination for the specified
2266  * connection.  The headers are first encoded and placed in the packets.
2267  */
2268 void
2269 rxi_SendPacketList(struct rx_call *call, struct rx_connection *conn,
2270                    struct rx_packet **list, int len, int istack)
2271 {
2272 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
2273     int waslocked;
2274 #endif
2275     register struct rx_peer *peer = conn->peer;
2276     osi_socket socket;
2277     struct rx_packet *p = NULL;
2278     struct iovec wirevec[RX_MAXIOVECS];
2279     int i, length, code;
2280     afs_uint32 serial;
2281     afs_uint32 temp;
2282     struct rx_jumboHeader *jp;
2283 #ifdef RXDEBUG
2284     char deliveryType = 'S';
2285 #endif
2286
2287     if (len + 1 > RX_MAXIOVECS) {
2288         osi_Panic("rxi_SendPacketList, len > RX_MAXIOVECS\n");
2289     }
2290
2291     /*
2292      * Stamp the packets in this jumbogram with consecutive serial numbers
2293      */
2294     MUTEX_ENTER(&conn->conn_data_lock);
2295     serial = conn->serial;
2296     conn->serial += len;
2297     MUTEX_EXIT(&conn->conn_data_lock);
2298
2299
2300     /* This stuff should be revamped, I think, so that most, if not
2301      * all, of the header stuff is always added here.  We could
2302      * probably do away with the encode/decode routines. XXXXX */
2303
2304     jp = NULL;
2305     length = RX_HEADER_SIZE;
2306     wirevec[0].iov_base = (char *)(&list[0]->wirehead[0]);
2307     wirevec[0].iov_len = RX_HEADER_SIZE;
2308     for (i = 0; i < len; i++) {
2309         p = list[i];
2310
2311         /* The whole 3.5 jumbogram scheme relies on packets fitting
2312          * in a single packet buffer. */
2313         if (p->niovecs > 2) {
2314             osi_Panic("rxi_SendPacketList, niovecs > 2\n");
2315         }
2316
2317         /* Set the RX_JUMBO_PACKET flags in all but the last packets
2318          * in this chunk.  */
2319         if (i < len - 1) {
2320             if (p->length != RX_JUMBOBUFFERSIZE) {
2321                 osi_Panic("rxi_SendPacketList, length != jumbo size\n");
2322             }
2323             p->header.flags |= RX_JUMBO_PACKET;
2324             length += RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2325             wirevec[i + 1].iov_len = RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2326         } else {
2327             wirevec[i + 1].iov_len = p->length;
2328             length += p->length;
2329         }
2330         wirevec[i + 1].iov_base = (char *)(&p->localdata[0]);
2331         if (jp != NULL) {
2332             /* Convert jumbo packet header to network byte order */
2333             temp = (afs_uint32) (p->header.flags) << 24;
2334             temp |= (afs_uint32) (p->header.spare);
2335             *(afs_uint32 *) jp = htonl(temp);
2336         }
2337         jp = (struct rx_jumboHeader *)
2338             ((char *)(&p->localdata[0]) + RX_JUMBOBUFFERSIZE);
2339
2340         /* Stamp each packet with a unique serial number.  The serial
2341          * number is maintained on a connection basis because some types
2342          * of security may be based on the serial number of the packet,
2343          * and security is handled on a per authenticated-connection
2344          * basis. */
2345         /* Pre-increment, to guarantee no zero serial number; a zero
2346          * serial number means the packet was never sent. */
2347         p->header.serial = ++serial;
2348         /* This is so we can adjust retransmit time-outs better in the face of 
2349          * rapidly changing round-trip times.  RTO estimation is not a la Karn.
2350          */
2351         if (p->firstSerial == 0) {
2352             p->firstSerial = p->header.serial;
2353         }
2354 #ifdef RXDEBUG
2355         /* If an output tracer function is defined, call it with the packet and
2356          * network address.  Note this function may modify its arguments. */
2357         if (rx_almostSent) {
2358             int drop = (*rx_almostSent) (p, &peer->saddr);
2359             /* drop packet if return value is non-zero? */
2360             if (drop)
2361                 deliveryType = 'D';     /* Drop the packet */
2362         }
2363 #endif
2364
2365         /* Get network byte order header */
2366         rxi_EncodePacketHeader(p);      /* XXX in the event of rexmit, etc, don't need to 
2367                                          * touch ALL the fields */
2368     }
2369
2370     /* Send the packet out on the same socket that related packets are being
2371      * received on */
2372     socket =
2373         (conn->type ==
2374          RX_CLIENT_CONNECTION ? rx_socket : conn->service->socket);
2375
2376 #ifdef RXDEBUG
2377     /* Possibly drop this packet,  for testing purposes */
2378     if ((deliveryType == 'D')
2379         || ((rx_intentionallyDroppedPacketsPer100 > 0)
2380             && (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
2381         deliveryType = 'D';     /* Drop the packet */
2382     } else {
2383         deliveryType = 'S';     /* Send the packet */
2384 #endif /* RXDEBUG */
2385
2386         /* Loop until the packet is sent.  We'd prefer just to use a
2387          * blocking socket, but unfortunately the interface doesn't
2388          * allow us to have the socket block in send mode, and not
2389          * block in receive mode */
2390 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
2391         waslocked = ISAFS_GLOCK();
2392         if (!istack && waslocked)
2393             AFS_GUNLOCK();
2394 #endif
2395         if ((code =
2396              osi_NetSend(socket, &peer->saddr, peer->saddrlen, &wirevec[0],
2397                          len + 1, length, istack)) != 0) {
2398             /* send failed, so let's hurry up the resend, eh? */
2399             MUTEX_ENTER(&rx_stats_mutex);
2400             rx_stats.netSendFailures++;
2401             MUTEX_EXIT(&rx_stats_mutex);
2402             for (i = 0; i < len; i++) {
2403                 p = list[i];
2404                 p->retryTime = p->timeSent;     /* resend it very soon */
2405                 clock_Addmsec(&(p->retryTime),
2406                               10 + (((afs_uint32) p->backoff) << 8));
2407             }
2408 #ifdef AFS_NT40_ENV
2409             /* Windows is nice -- it can tell us right away that we cannot
2410              * reach this recipient by returning an WSAEHOSTUNREACH error
2411              * code.  So, when this happens let's "down" the host NOW so
2412              * we don't sit around waiting for this host to timeout later.
2413              */
2414             if (call && code == -1 && errno == WSAEHOSTUNREACH)
2415                 call->lastReceiveTime = 0;
2416 #endif
2417 #if defined(KERNEL) && defined(AFS_LINUX20_ENV)
2418             /* Linux is nice -- it can tell us right away that we cannot
2419              * reach this recipient by returning an ENETUNREACH error
2420              * code.  So, when this happens let's "down" the host NOW so
2421              * we don't sit around waiting for this host to timeout later.
2422              */
2423             if (call && code == -ENETUNREACH)
2424                 call->lastReceiveTime = 0;
2425 #endif
2426         }
2427 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
2428         if (!istack && waslocked)
2429             AFS_GLOCK();
2430 #endif
2431 #ifdef RXDEBUG
2432     }
2433
2434     assert(p != NULL);
2435
2436     dpf(("%c %d %s: %s.%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], rx_AddrStringOf(peer), ntohs(rx_PortOf(peer)), 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));
2437
2438 #endif
2439     MUTEX_ENTER(&rx_stats_mutex);
2440     rx_stats.packetsSent[p->header.type - 1]++;
2441     MUTEX_EXIT(&rx_stats_mutex);
2442     MUTEX_ENTER(&peer->peer_lock);
2443
2444     hadd32(peer->bytesSent, p->length);
2445     MUTEX_EXIT(&peer->peer_lock);
2446 }
2447
2448
2449 /* Send a "special" packet to the peer connection.  If call is
2450  * specified, then the packet is directed to a specific call channel
2451  * associated with the connection, otherwise it is directed to the
2452  * connection only. Uses optionalPacket if it is supplied, rather than
2453  * allocating a new packet buffer.  Nbytes is the length of the data
2454  * portion of the packet.  If data is non-null, nbytes of data are
2455  * copied into the packet.  Type is the type of the packet, as defined
2456  * in rx.h.  Bug: there's a lot of duplication between this and other
2457  * routines.  This needs to be cleaned up. */
2458 struct rx_packet *
2459 rxi_SendSpecial(register struct rx_call *call,
2460                 register struct rx_connection *conn,
2461                 struct rx_packet *optionalPacket, int type, char *data,
2462                 int nbytes, int istack)
2463 {
2464     /* Some of the following stuff should be common code for all
2465      * packet sends (it's repeated elsewhere) */
2466     register struct rx_packet *p;
2467     unsigned int i = 0;
2468     int savelen = 0, saven = 0;
2469     int channel, callNumber;
2470     if (call) {
2471         channel = call->channel;
2472         callNumber = *call->callNumber;
2473         /* BUSY packets refer to the next call on this connection */
2474         if (type == RX_PACKET_TYPE_BUSY) {
2475             callNumber++;
2476         }
2477     } else {
2478         channel = 0;
2479         callNumber = 0;
2480     }
2481     p = optionalPacket;
2482     if (!p) {
2483         p = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL);
2484         if (!p)
2485             osi_Panic("rxi_SendSpecial failure");
2486     }
2487
2488     if (nbytes != -1)
2489         p->length = nbytes;
2490     else
2491         nbytes = p->length;
2492     p->header.serviceId = conn->serviceId;
2493     p->header.securityIndex = conn->securityIndex;
2494     p->header.cid = (conn->cid | channel);
2495     p->header.callNumber = callNumber;
2496     p->header.seq = 0;
2497     p->header.epoch = conn->epoch;
2498     p->header.type = type;
2499     p->header.flags = 0;
2500     if (conn->type == RX_CLIENT_CONNECTION)
2501         p->header.flags |= RX_CLIENT_INITIATED;
2502     if (data)
2503         rx_packetwrite(p, 0, nbytes, data);
2504
2505     for (i = 1; i < p->niovecs; i++) {
2506         if (nbytes <= p->wirevec[i].iov_len) {
2507             savelen = p->wirevec[i].iov_len;
2508             saven = p->niovecs;
2509             p->wirevec[i].iov_len = nbytes;
2510             p->niovecs = i + 1; /* so condition fails because i == niovecs */
2511         } else
2512             nbytes -= p->wirevec[i].iov_len;
2513     }
2514
2515     if (call)
2516         rxi_Send(call, p, istack);
2517     else
2518         rxi_SendPacket((struct rx_call *)0, conn, p, istack);
2519     if (saven) {                /* means we truncated the packet above.  We probably don't  */
2520         /* really need to do this, but it seems safer this way, given that  */
2521         /* sneaky optionalPacket... */
2522         p->wirevec[i - 1].iov_len = savelen;
2523         p->niovecs = saven;
2524     }
2525     if (!optionalPacket)
2526         rxi_FreePacket(p);
2527     return optionalPacket;
2528 }
2529
2530
2531 /* Encode the packet's header (from the struct header in the packet to
2532  * the net byte order representation in the wire representation of the
2533  * packet, which is what is actually sent out on the wire) */
2534 void
2535 rxi_EncodePacketHeader(register struct rx_packet *p)
2536 {
2537     register afs_uint32 *buf = (afs_uint32 *) (p->wirevec[0].iov_base); /* MTUXXX */
2538
2539     memset((char *)buf, 0, RX_HEADER_SIZE);
2540     *buf++ = htonl(p->header.epoch);
2541     *buf++ = htonl(p->header.cid);
2542     *buf++ = htonl(p->header.callNumber);
2543     *buf++ = htonl(p->header.seq);
2544     *buf++ = htonl(p->header.serial);
2545     *buf++ = htonl((((afs_uint32) p->header.type) << 24)
2546                    | (((afs_uint32) p->header.flags) << 16)
2547                    | (p->header.userStatus << 8) | p->header.securityIndex);
2548     /* Note: top 16 bits of this next word were reserved */
2549     *buf++ = htonl((p->header.spare << 16) | (p->header.serviceId & 0xffff));
2550 }
2551
2552 /* Decode the packet's header (from net byte order to a struct header) */
2553 void
2554 rxi_DecodePacketHeader(register struct rx_packet *p)
2555 {
2556     register afs_uint32 *buf = (afs_uint32 *) (p->wirevec[0].iov_base); /* MTUXXX */
2557     afs_uint32 temp;
2558
2559     p->header.epoch = ntohl(*buf);
2560     buf++;
2561     p->header.cid = ntohl(*buf);
2562     buf++;
2563     p->header.callNumber = ntohl(*buf);
2564     buf++;
2565     p->header.seq = ntohl(*buf);
2566     buf++;
2567     p->header.serial = ntohl(*buf);
2568     buf++;
2569
2570     temp = ntohl(*buf);
2571     buf++;
2572
2573     /* C will truncate byte fields to bytes for me */
2574     p->header.type = temp >> 24;
2575     p->header.flags = temp >> 16;
2576     p->header.userStatus = temp >> 8;
2577     p->header.securityIndex = temp >> 0;
2578
2579     temp = ntohl(*buf);
2580     buf++;
2581
2582     p->header.serviceId = (temp & 0xffff);
2583     p->header.spare = temp >> 16;
2584     /* Note: top 16 bits of this last word are the security checksum */
2585 }
2586
2587 void
2588 rxi_PrepareSendPacket(register struct rx_call *call,
2589                       register struct rx_packet *p, register int last)
2590 {
2591     register struct rx_connection *conn = call->conn;
2592     int i, j;
2593     ssize_t len;                /* len must be a signed type; it can go negative */
2594
2595     p->flags &= ~RX_PKTFLAG_ACKED;
2596     p->header.cid = (conn->cid | call->channel);
2597     p->header.serviceId = conn->serviceId;
2598     p->header.securityIndex = conn->securityIndex;
2599
2600     /* No data packets on call 0. Where do these come from? */
2601     if (*call->callNumber == 0)
2602         *call->callNumber = 1;
2603
2604     p->header.callNumber = *call->callNumber;
2605     p->header.seq = call->tnext++;
2606     p->header.epoch = conn->epoch;
2607     p->header.type = RX_PACKET_TYPE_DATA;
2608     p->header.flags = 0;
2609     p->header.spare = 0;
2610     if (conn->type == RX_CLIENT_CONNECTION)
2611         p->header.flags |= RX_CLIENT_INITIATED;
2612
2613     if (last)
2614         p->header.flags |= RX_LAST_PACKET;
2615
2616     clock_Zero(&p->retryTime);  /* Never yet transmitted */
2617     clock_Zero(&p->firstSent);  /* Never yet transmitted */
2618     p->header.serial = 0;       /* Another way of saying never transmitted... */
2619     p->backoff = 0;
2620
2621     /* Now that we're sure this is the last data on the call, make sure
2622      * that the "length" and the sum of the iov_lens matches. */
2623     len = p->length + call->conn->securityHeaderSize;
2624
2625     for (i = 1; i < p->niovecs && len > 0; i++) {
2626         len -= p->wirevec[i].iov_len;
2627     }
2628     if (len > 0) {
2629         osi_Panic("PrepareSendPacket 1\n");     /* MTUXXX */
2630     } else {
2631         struct rx_queue q;
2632         int nb;
2633
2634         queue_Init(&q);
2635
2636         /* Free any extra elements in the wirevec */
2637         for (j = MAX(2, i), nb = p->niovecs - j; j < p->niovecs; j++) {
2638             queue_Append(&q,RX_CBUF_TO_PACKET(p->wirevec[j].iov_base, p));
2639         }
2640         if (nb)
2641             rxi_FreePackets(nb, &q);
2642
2643         p->niovecs = MAX(2, i);
2644         p->wirevec[MAX(2, i) - 1].iov_len += len;
2645     }
2646     RXS_PreparePacket(conn->securityObject, call, p);
2647 }
2648
2649 /* Given an interface MTU size, calculate an adjusted MTU size that
2650  * will make efficient use of the RX buffers when the peer is sending
2651  * either AFS 3.4a jumbograms or AFS 3.5 jumbograms.  */
2652 int
2653 rxi_AdjustIfMTU(int mtu)
2654 {
2655     int adjMTU;
2656     int frags;
2657
2658     adjMTU = RX_HEADER_SIZE + RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2659     if (mtu <= adjMTU) {
2660         return mtu;
2661     }
2662     mtu -= adjMTU;
2663     if (mtu <= 0) {
2664         return adjMTU;
2665     }
2666     frags = mtu / (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE);
2667     return (adjMTU + (frags * (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE)));
2668 }
2669
2670 /* Given an interface MTU size, and the peer's advertised max receive
2671  * size, calculate an adjisted maxMTU size that makes efficient use
2672  * of our packet buffers when we are sending AFS 3.4a jumbograms. */
2673 int
2674 rxi_AdjustMaxMTU(int mtu, int peerMaxMTU)
2675 {
2676     int maxMTU = mtu * rxi_nSendFrags;
2677     maxMTU = MIN(maxMTU, peerMaxMTU);
2678     return rxi_AdjustIfMTU(maxMTU);
2679 }
2680
2681 /* Given a packet size, figure out how many datagram packet will fit.
2682  * The first buffer always contains RX_HEADER_SIZE+RX_JUMBOBUFFERSIZE+
2683  * RX_JUMBOHEADERSIZE, the middle buffers contain RX_JUMBOBUFFERSIZE+
2684  * RX_JUMBOHEADERSIZE, and the last buffer contains RX_JUMBOBUFFERSIZE */
2685 int
2686 rxi_AdjustDgramPackets(int frags, int mtu)
2687 {
2688     int maxMTU;
2689     if (mtu + IPv6_FRAG_HDR_SIZE < RX_JUMBOBUFFERSIZE + RX_HEADER_SIZE) {
2690         return 1;
2691     }
2692     maxMTU = (frags * (mtu + UDP_HDR_SIZE)) - UDP_HDR_SIZE;
2693     maxMTU = MIN(maxMTU, RX_MAX_PACKET_SIZE);
2694     /* subtract the size of the first and last packets */
2695     maxMTU -= RX_HEADER_SIZE + (2 * RX_JUMBOBUFFERSIZE) + RX_JUMBOHEADERSIZE;
2696     if (maxMTU < 0) {
2697         return 1;
2698     }
2699     return (2 + (maxMTU / (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE)));
2700 }