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