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