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