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