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