94e7482203b60b0d1ed74ccf956e23a39cd8679c
[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 (rx_stats_active
1484             && p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
1485
1486                 rx_atomic_inc(&rx_stats.packetsRead[p->header.type - 1]);
1487         }
1488
1489 #ifdef RX_TRIMDATABUFS
1490         /* Free any empty packet buffers at the end of this packet */
1491         rxi_TrimDataBufs(p, 1);
1492 #endif
1493         return 1;
1494     }
1495 }
1496
1497 #endif /* !KERNEL || UKERNEL */
1498
1499 /* This function splits off the first packet in a jumbo packet.
1500  * As of AFS 3.5, jumbograms contain more than one fixed size
1501  * packet, and the RX_JUMBO_PACKET flag is set in all but the
1502  * last packet header. All packets (except the last) are padded to
1503  * fall on RX_CBUFFERSIZE boundaries.
1504  * HACK: We store the length of the first n-1 packets in the
1505  * last two pad bytes. */
1506
1507 struct rx_packet *
1508 rxi_SplitJumboPacket(struct rx_packet *p, afs_uint32 host, short port,
1509                      int first)
1510 {
1511     struct rx_packet *np;
1512     struct rx_jumboHeader *jp;
1513     int niov, i;
1514     struct iovec *iov;
1515     int length;
1516     afs_uint32 temp;
1517
1518     /* All but the last packet in each jumbogram are RX_JUMBOBUFFERSIZE
1519      * bytes in length. All but the first packet are preceded by
1520      * an abbreviated four byte header. The length of the last packet
1521      * is calculated from the size of the jumbogram. */
1522     length = RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
1523
1524     if ((int)p->length < length) {
1525         dpf(("rxi_SplitJumboPacket: bogus length %d\n", p->length));
1526         return NULL;
1527     }
1528     niov = p->niovecs - 2;
1529     if (niov < 1) {
1530         dpf(("rxi_SplitJumboPacket: bogus niovecs %d\n", p->niovecs));
1531         return NULL;
1532     }
1533     iov = &p->wirevec[2];
1534     np = RX_CBUF_TO_PACKET(iov->iov_base, p);
1535
1536     /* Get a pointer to the abbreviated packet header */
1537     jp = (struct rx_jumboHeader *)
1538         ((char *)(p->wirevec[1].iov_base) + RX_JUMBOBUFFERSIZE);
1539
1540     /* Set up the iovecs for the next packet */
1541     np->wirevec[0].iov_base = (char *)(&np->wirehead[0]);
1542     np->wirevec[0].iov_len = sizeof(struct rx_header);
1543     np->wirevec[1].iov_base = (char *)(&np->localdata[0]);
1544     np->wirevec[1].iov_len = length - RX_JUMBOHEADERSIZE;
1545     np->niovecs = niov + 1;
1546     for (i = 2, iov++; i <= niov; i++, iov++) {
1547         np->wirevec[i] = *iov;
1548     }
1549     np->length = p->length - length;
1550     p->length = RX_JUMBOBUFFERSIZE;
1551     p->niovecs = 2;
1552
1553     /* Convert the jumbo packet header to host byte order */
1554     temp = ntohl(*(afs_uint32 *) jp);
1555     jp->flags = (u_char) (temp >> 24);
1556     jp->cksum = (u_short) (temp);
1557
1558     /* Fill in the packet header */
1559     np->header = p->header;
1560     np->header.serial = p->header.serial + 1;
1561     np->header.seq = p->header.seq + 1;
1562     np->header.flags = jp->flags;
1563     np->header.spare = jp->cksum;
1564
1565     return np;
1566 }
1567
1568 #ifndef KERNEL
1569 /* Send a udp datagram */
1570 int
1571 osi_NetSend(osi_socket socket, void *addr, struct iovec *dvec, int nvecs,
1572             int length, int istack)
1573 {
1574     struct msghdr msg;
1575         int ret;
1576
1577     memset(&msg, 0, sizeof(msg));
1578     msg.msg_iov = dvec;
1579     msg.msg_iovlen = nvecs;
1580     msg.msg_name = addr;
1581     msg.msg_namelen = sizeof(struct sockaddr_in);
1582
1583     ret = rxi_Sendmsg(socket, &msg, 0);
1584
1585     return ret;
1586 }
1587 #elif !defined(UKERNEL)
1588 /*
1589  * message receipt is done in rxk_input or rx_put.
1590  */
1591
1592 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX110_ENV)
1593 /*
1594  * Copy an mblock to the contiguous area pointed to by cp.
1595  * MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
1596  * but it doesn't really.
1597  * Returns the number of bytes not transferred.
1598  * The message is NOT changed.
1599  */
1600 static int
1601 cpytoc(mblk_t * mp, int off, int len, char *cp)
1602 {
1603     int n;
1604
1605     for (; mp && len > 0; mp = mp->b_cont) {
1606         if (mp->b_datap->db_type != M_DATA) {
1607             return -1;
1608         }
1609         n = MIN(len, (mp->b_wptr - mp->b_rptr));
1610         memcpy(cp, (char *)mp->b_rptr, n);
1611         cp += n;
1612         len -= n;
1613         mp->b_rptr += n;
1614     }
1615     return (len);
1616 }
1617
1618 /* MTUXXX Supposed to skip <off> bytes and copy <len> bytes,
1619  * but it doesn't really.
1620  * This sucks, anyway, do it like m_cpy.... below
1621  */
1622 static int
1623 cpytoiovec(mblk_t * mp, int off, int len, struct iovec *iovs,
1624            int niovs)
1625 {
1626     int m, n, o, t, i;
1627
1628     for (i = -1, t = 0; i < niovs && mp && len > 0; mp = mp->b_cont) {
1629         if (mp->b_datap->db_type != M_DATA) {
1630             return -1;
1631         }
1632         n = MIN(len, (mp->b_wptr - mp->b_rptr));
1633         len -= n;
1634         while (n) {
1635             if (!t) {
1636                 o = 0;
1637                 i++;
1638                 t = iovs[i].iov_len;
1639             }
1640             m = MIN(n, t);
1641             memcpy(iovs[i].iov_base + o, (char *)mp->b_rptr, m);
1642             mp->b_rptr += m;
1643             o += m;
1644             t -= m;
1645             n -= m;
1646         }
1647     }
1648     return (len);
1649 }
1650
1651 #define m_cpytoc(a, b, c, d)  cpytoc(a, b, c, d)
1652 #define m_cpytoiovec(a, b, c, d, e) cpytoiovec(a, b, c, d, e)
1653 #else
1654 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV)
1655 static int
1656 m_cpytoiovec(struct mbuf *m, int off, int len, struct iovec iovs[], int niovs)
1657 {
1658     caddr_t p1, p2;
1659     unsigned int l1, l2, i, t;
1660
1661     if (m == NULL || off < 0 || len < 0 || iovs == NULL)
1662         osi_Panic("m_cpytoiovec");      /* MTUXXX probably don't need this check */
1663
1664     while (off && m)
1665         if (m->m_len <= off) {
1666             off -= m->m_len;
1667             m = m->m_next;
1668             continue;
1669         } else
1670             break;
1671
1672     if (m == NULL)
1673         return len;
1674
1675     p1 = mtod(m, caddr_t) + off;
1676     l1 = m->m_len - off;
1677     i = 0;
1678     p2 = iovs[0].iov_base;
1679     l2 = iovs[0].iov_len;
1680
1681     while (len) {
1682         t = MIN(l1, MIN(l2, (unsigned int)len));
1683         memcpy(p2, p1, t);
1684         p1 += t;
1685         p2 += t;
1686         l1 -= t;
1687         l2 -= t;
1688         len -= t;
1689         if (!l1) {
1690             m = m->m_next;
1691             if (!m)
1692                 break;
1693             p1 = mtod(m, caddr_t);
1694             l1 = m->m_len;
1695         }
1696         if (!l2) {
1697             if (++i >= niovs)
1698                 break;
1699             p2 = iovs[i].iov_base;
1700             l2 = iovs[i].iov_len;
1701         }
1702
1703     }
1704
1705     return len;
1706 }
1707 #endif /* LINUX */
1708 #endif /* AFS_SUN5_ENV */
1709
1710 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV)
1711 #if defined(AFS_NBSD_ENV)
1712 int
1713 rx_mb_to_packet(struct mbuf *amb, void (*free) (struct mbuf *), int hdr_len, int data_len, struct rx_packet *phandle)
1714 #else
1715 int
1716 rx_mb_to_packet(amb, free, hdr_len, data_len, phandle)
1717 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX110_ENV)
1718      mblk_t *amb;
1719 #else
1720      struct mbuf *amb;
1721 #endif
1722      void (*free) ();
1723      struct rx_packet *phandle;
1724      int hdr_len, data_len;
1725 #endif /* AFS_NBSD_ENV */
1726 {
1727     int code;
1728
1729     code =
1730         m_cpytoiovec(amb, hdr_len, data_len, phandle->wirevec,
1731                      phandle->niovecs);
1732     (*free) (amb);
1733
1734     return code;
1735 }
1736 #endif /* LINUX */
1737 #endif /*KERNEL && !UKERNEL */
1738
1739
1740 /* send a response to a debug packet */
1741
1742 struct rx_packet *
1743 rxi_ReceiveDebugPacket(struct rx_packet *ap, osi_socket asocket,
1744                        afs_uint32 ahost, short aport, int istack)
1745 {
1746     struct rx_debugIn tin;
1747     afs_int32 tl;
1748     struct rx_serverQueueEntry *np, *nqe;
1749
1750     /*
1751      * Only respond to client-initiated Rx debug packets,
1752      * and clear the client flag in the response.
1753      */
1754     if (ap->header.flags & RX_CLIENT_INITIATED) {
1755         ap->header.flags = ap->header.flags & ~RX_CLIENT_INITIATED;
1756         rxi_EncodePacketHeader(ap);
1757     } else {
1758         return ap;
1759     }
1760
1761     rx_packetread(ap, 0, sizeof(struct rx_debugIn), (char *)&tin);
1762     /* all done with packet, now set length to the truth, so we can
1763      * reuse this packet */
1764     rx_computelen(ap, ap->length);
1765
1766     tin.type = ntohl(tin.type);
1767     tin.index = ntohl(tin.index);
1768     switch (tin.type) {
1769     case RX_DEBUGI_GETSTATS:{
1770             struct rx_debugStats tstat;
1771
1772             /* get basic stats */
1773             memset(&tstat, 0, sizeof(tstat));   /* make sure spares are zero */
1774             tstat.version = RX_DEBUGI_VERSION;
1775 #ifndef RX_ENABLE_LOCKS
1776             tstat.waitingForPackets = rx_waitingForPackets;
1777 #endif
1778             MUTEX_ENTER(&rx_serverPool_lock);
1779             tstat.nFreePackets = htonl(rx_nFreePackets);
1780             tstat.nPackets = htonl(rx_nPackets);
1781             tstat.callsExecuted = htonl(rxi_nCalls);
1782             tstat.packetReclaims = htonl(rx_packetReclaims);
1783             tstat.usedFDs = CountFDs(64);
1784             tstat.nWaiting = htonl(rx_atomic_read(&rx_nWaiting));
1785             tstat.nWaited = htonl(rx_atomic_read(&rx_nWaited));
1786             queue_Count(&rx_idleServerQueue, np, nqe, rx_serverQueueEntry,
1787                         tstat.idleThreads);
1788             MUTEX_EXIT(&rx_serverPool_lock);
1789             tstat.idleThreads = htonl(tstat.idleThreads);
1790             tl = sizeof(struct rx_debugStats) - ap->length;
1791             if (tl > 0)
1792                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1793
1794             if (tl <= 0) {
1795                 rx_packetwrite(ap, 0, sizeof(struct rx_debugStats),
1796                                (char *)&tstat);
1797                 ap->length = sizeof(struct rx_debugStats);
1798                 rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1799                 rx_computelen(ap, ap->length);
1800             }
1801             break;
1802         }
1803
1804     case RX_DEBUGI_GETALLCONN:
1805     case RX_DEBUGI_GETCONN:{
1806             unsigned int i, j;
1807             struct rx_connection *tc;
1808             struct rx_call *tcall;
1809             struct rx_debugConn tconn;
1810             int all = (tin.type == RX_DEBUGI_GETALLCONN);
1811
1812
1813             tl = sizeof(struct rx_debugConn) - ap->length;
1814             if (tl > 0)
1815                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1816             if (tl > 0)
1817                 return ap;
1818
1819             memset(&tconn, 0, sizeof(tconn));   /* make sure spares are zero */
1820             /* get N'th (maybe) "interesting" connection info */
1821             for (i = 0; i < rx_hashTableSize; i++) {
1822 #if !defined(KERNEL)
1823                 /* the time complexity of the algorithm used here
1824                  * exponentially increses with the number of connections.
1825                  */
1826 #ifdef AFS_PTHREAD_ENV
1827                 pthread_yield();
1828 #else
1829                 (void)IOMGR_Poll();
1830 #endif
1831 #endif
1832                 MUTEX_ENTER(&rx_connHashTable_lock);
1833                 /* We might be slightly out of step since we are not
1834                  * locking each call, but this is only debugging output.
1835                  */
1836                 for (tc = rx_connHashTable[i]; tc; tc = tc->next) {
1837                     if ((all || rxi_IsConnInteresting(tc))
1838                         && tin.index-- <= 0) {
1839                         tconn.host = tc->peer->host;
1840                         tconn.port = tc->peer->port;
1841                         tconn.cid = htonl(tc->cid);
1842                         tconn.epoch = htonl(tc->epoch);
1843                         tconn.serial = htonl(tc->serial);
1844                         for (j = 0; j < RX_MAXCALLS; j++) {
1845                             tconn.callNumber[j] = htonl(tc->callNumber[j]);
1846                             if ((tcall = tc->call[j])) {
1847                                 tconn.callState[j] = tcall->state;
1848                                 tconn.callMode[j] = tcall->mode;
1849                                 tconn.callFlags[j] = tcall->flags;
1850                                 if (queue_IsNotEmpty(&tcall->rq))
1851                                     tconn.callOther[j] |= RX_OTHER_IN;
1852                                 if (queue_IsNotEmpty(&tcall->tq))
1853                                     tconn.callOther[j] |= RX_OTHER_OUT;
1854                             } else
1855                                 tconn.callState[j] = RX_STATE_NOTINIT;
1856                         }
1857
1858                         tconn.natMTU = htonl(tc->peer->natMTU);
1859                         tconn.error = htonl(tc->error);
1860                         tconn.flags = tc->flags;
1861                         tconn.type = tc->type;
1862                         tconn.securityIndex = tc->securityIndex;
1863                         if (tc->securityObject) {
1864                             RXS_GetStats(tc->securityObject, tc,
1865                                          &tconn.secStats);
1866 #define DOHTONL(a) (tconn.secStats.a = htonl(tconn.secStats.a))
1867 #define DOHTONS(a) (tconn.secStats.a = htons(tconn.secStats.a))
1868                             DOHTONL(flags);
1869                             DOHTONL(expires);
1870                             DOHTONL(packetsReceived);
1871                             DOHTONL(packetsSent);
1872                             DOHTONL(bytesReceived);
1873                             DOHTONL(bytesSent);
1874                             for (i = 0;
1875                                  i <
1876                                  sizeof(tconn.secStats.spares) /
1877                                  sizeof(short); i++)
1878                                 DOHTONS(spares[i]);
1879                             for (i = 0;
1880                                  i <
1881                                  sizeof(tconn.secStats.sparel) /
1882                                  sizeof(afs_int32); i++)
1883                                 DOHTONL(sparel[i]);
1884                         }
1885
1886                         MUTEX_EXIT(&rx_connHashTable_lock);
1887                         rx_packetwrite(ap, 0, sizeof(struct rx_debugConn),
1888                                        (char *)&tconn);
1889                         tl = ap->length;
1890                         ap->length = sizeof(struct rx_debugConn);
1891                         rxi_SendDebugPacket(ap, asocket, ahost, aport,
1892                                             istack);
1893                         ap->length = tl;
1894                         return ap;
1895                     }
1896                 }
1897                 MUTEX_EXIT(&rx_connHashTable_lock);
1898             }
1899             /* if we make it here, there are no interesting packets */
1900             tconn.cid = htonl(0xffffffff);      /* means end */
1901             rx_packetwrite(ap, 0, sizeof(struct rx_debugConn),
1902                            (char *)&tconn);
1903             tl = ap->length;
1904             ap->length = sizeof(struct rx_debugConn);
1905             rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
1906             ap->length = tl;
1907             break;
1908         }
1909
1910         /*
1911          * Pass back all the peer structures we have available
1912          */
1913
1914     case RX_DEBUGI_GETPEER:{
1915             unsigned int i;
1916             struct rx_peer *tp;
1917             struct rx_debugPeer tpeer;
1918
1919
1920             tl = sizeof(struct rx_debugPeer) - ap->length;
1921             if (tl > 0)
1922                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
1923             if (tl > 0)
1924                 return ap;
1925
1926             memset(&tpeer, 0, sizeof(tpeer));
1927             for (i = 0; i < rx_hashTableSize; i++) {
1928 #if !defined(KERNEL)
1929                 /* the time complexity of the algorithm used here
1930                  * exponentially increses with the number of peers.
1931                  *
1932                  * Yielding after processing each hash table entry
1933                  * and dropping rx_peerHashTable_lock.
1934                  * also increases the risk that we will miss a new
1935                  * entry - but we are willing to live with this
1936                  * limitation since this is meant for debugging only
1937                  */
1938 #ifdef AFS_PTHREAD_ENV
1939                 pthread_yield();
1940 #else
1941                 (void)IOMGR_Poll();
1942 #endif
1943 #endif
1944                 MUTEX_ENTER(&rx_peerHashTable_lock);
1945                 for (tp = rx_peerHashTable[i]; tp; tp = tp->next) {
1946                     if (tin.index-- <= 0) {
1947                         tp->refCount++;
1948                         MUTEX_EXIT(&rx_peerHashTable_lock);
1949
1950                         MUTEX_ENTER(&tp->peer_lock);
1951                         tpeer.host = tp->host;
1952                         tpeer.port = tp->port;
1953                         tpeer.ifMTU = htons(tp->ifMTU);
1954                         tpeer.idleWhen = htonl(tp->idleWhen);
1955                         tpeer.refCount = htons(tp->refCount);
1956                         tpeer.burstSize = 0;
1957                         tpeer.burst = 0;
1958                         tpeer.burstWait.sec = 0;
1959                         tpeer.burstWait.usec = 0;
1960                         tpeer.rtt = htonl(tp->rtt);
1961                         tpeer.rtt_dev = htonl(tp->rtt_dev);
1962                         tpeer.nSent = htonl(tp->nSent);
1963                         tpeer.reSends = htonl(tp->reSends);
1964                         tpeer.natMTU = htons(tp->natMTU);
1965                         tpeer.maxMTU = htons(tp->maxMTU);
1966                         tpeer.maxDgramPackets = htons(tp->maxDgramPackets);
1967                         tpeer.ifDgramPackets = htons(tp->ifDgramPackets);
1968                         tpeer.MTU = htons(tp->MTU);
1969                         tpeer.cwind = htons(tp->cwind);
1970                         tpeer.nDgramPackets = htons(tp->nDgramPackets);
1971                         tpeer.congestSeq = htons(tp->congestSeq);
1972                         tpeer.bytesSent.high = htonl(tp->bytesSent.high);
1973                         tpeer.bytesSent.low = htonl(tp->bytesSent.low);
1974                         tpeer.bytesReceived.high =
1975                             htonl(tp->bytesReceived.high);
1976                         tpeer.bytesReceived.low =
1977                             htonl(tp->bytesReceived.low);
1978                         MUTEX_EXIT(&tp->peer_lock);
1979
1980                         MUTEX_ENTER(&rx_peerHashTable_lock);
1981                         tp->refCount--;
1982                         MUTEX_EXIT(&rx_peerHashTable_lock);
1983
1984                         rx_packetwrite(ap, 0, sizeof(struct rx_debugPeer),
1985                                        (char *)&tpeer);
1986                         tl = ap->length;
1987                         ap->length = sizeof(struct rx_debugPeer);
1988                         rxi_SendDebugPacket(ap, asocket, ahost, aport,
1989                                             istack);
1990                         ap->length = tl;
1991                         return ap;
1992                     }
1993                 }
1994                 MUTEX_EXIT(&rx_peerHashTable_lock);
1995             }
1996             /* if we make it here, there are no interesting packets */
1997             tpeer.host = htonl(0xffffffff);     /* means end */
1998             rx_packetwrite(ap, 0, sizeof(struct rx_debugPeer),
1999                            (char *)&tpeer);
2000             tl = ap->length;
2001             ap->length = sizeof(struct rx_debugPeer);
2002             rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
2003             ap->length = tl;
2004             break;
2005         }
2006
2007     case RX_DEBUGI_RXSTATS:{
2008             int i;
2009             afs_int32 *s;
2010
2011             tl = sizeof(rx_stats) - ap->length;
2012             if (tl > 0)
2013                 tl = rxi_AllocDataBuf(ap, tl, RX_PACKET_CLASS_SEND_CBUF);
2014             if (tl > 0)
2015                 return ap;
2016
2017             /* Since its all int32s convert to network order with a loop. */
2018         if (rx_stats_active)
2019             MUTEX_ENTER(&rx_stats_mutex);
2020             s = (afs_int32 *) & rx_stats;
2021             for (i = 0; i < sizeof(rx_stats) / sizeof(afs_int32); i++, s++)
2022                 rx_PutInt32(ap, i * sizeof(afs_int32), htonl(*s));
2023
2024             tl = ap->length;
2025             ap->length = sizeof(rx_stats);
2026         if (rx_stats_active)
2027             MUTEX_EXIT(&rx_stats_mutex);
2028             rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
2029             ap->length = tl;
2030             break;
2031         }
2032
2033     default:
2034         /* error response packet */
2035         tin.type = htonl(RX_DEBUGI_BADTYPE);
2036         tin.index = tin.type;
2037         rx_packetwrite(ap, 0, sizeof(struct rx_debugIn), (char *)&tin);
2038         tl = ap->length;
2039         ap->length = sizeof(struct rx_debugIn);
2040         rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
2041         ap->length = tl;
2042         break;
2043     }
2044     return ap;
2045 }
2046
2047 struct rx_packet *
2048 rxi_ReceiveVersionPacket(struct rx_packet *ap, osi_socket asocket,
2049                          afs_uint32 ahost, short aport, int istack)
2050 {
2051     afs_int32 tl;
2052
2053     /*
2054      * Only respond to client-initiated version requests, and
2055      * clear that flag in the response.
2056      */
2057     if (ap->header.flags & RX_CLIENT_INITIATED) {
2058         char buf[66];
2059
2060         ap->header.flags = ap->header.flags & ~RX_CLIENT_INITIATED;
2061         rxi_EncodePacketHeader(ap);
2062         memset(buf, 0, sizeof(buf));
2063         strncpy(buf, cml_version_number + 4, sizeof(buf) - 1);
2064         rx_packetwrite(ap, 0, 65, buf);
2065         tl = ap->length;
2066         ap->length = 65;
2067         rxi_SendDebugPacket(ap, asocket, ahost, aport, istack);
2068         ap->length = tl;
2069     }
2070
2071     return ap;
2072 }
2073
2074
2075 /* send a debug packet back to the sender */
2076 static void
2077 rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
2078                     afs_uint32 ahost, short aport, afs_int32 istack)
2079 {
2080     struct sockaddr_in taddr;
2081     unsigned int i, nbytes, savelen = 0;
2082     int saven = 0;
2083 #ifdef KERNEL
2084     int waslocked = ISAFS_GLOCK();
2085 #endif
2086
2087     taddr.sin_family = AF_INET;
2088     taddr.sin_port = aport;
2089     taddr.sin_addr.s_addr = ahost;
2090 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
2091     taddr.sin_len = sizeof(struct sockaddr_in);
2092 #endif
2093
2094     /* We need to trim the niovecs. */
2095     nbytes = apacket->length;
2096     for (i = 1; i < apacket->niovecs; i++) {
2097         if (nbytes <= apacket->wirevec[i].iov_len) {
2098             savelen = apacket->wirevec[i].iov_len;
2099             saven = apacket->niovecs;
2100             apacket->wirevec[i].iov_len = nbytes;
2101             apacket->niovecs = i + 1;   /* so condition fails because i == niovecs */
2102         } else
2103             nbytes -= apacket->wirevec[i].iov_len;
2104     }
2105 #ifdef KERNEL
2106 #ifdef RX_KERNEL_TRACE
2107     if (ICL_SETACTIVE(afs_iclSetp)) {
2108         if (!waslocked)
2109             AFS_GLOCK();
2110         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2111                    "before osi_NetSend()");
2112         AFS_GUNLOCK();
2113     }
2114 #else
2115     if (waslocked)
2116         AFS_GUNLOCK();
2117 #endif
2118 #endif
2119     /* debug packets are not reliably delivered, hence the cast below. */
2120     (void)osi_NetSend(asocket, &taddr, apacket->wirevec, apacket->niovecs,
2121                       apacket->length + RX_HEADER_SIZE, istack);
2122 #ifdef KERNEL
2123 #ifdef RX_KERNEL_TRACE
2124     if (ICL_SETACTIVE(afs_iclSetp)) {
2125         AFS_GLOCK();
2126         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2127                    "after osi_NetSend()");
2128         if (!waslocked)
2129             AFS_GUNLOCK();
2130     }
2131 #else
2132     if (waslocked)
2133         AFS_GLOCK();
2134 #endif
2135 #endif
2136     if (saven) {                /* means we truncated the packet above. */
2137         apacket->wirevec[i - 1].iov_len = savelen;
2138         apacket->niovecs = saven;
2139     }
2140
2141 }
2142
2143 /* Send the packet to appropriate destination for the specified
2144  * call.  The header is first encoded and placed in the packet.
2145  */
2146 void
2147 rxi_SendPacket(struct rx_call *call, struct rx_connection *conn,
2148                struct rx_packet *p, int istack)
2149 {
2150 #if defined(KERNEL)
2151     int waslocked;
2152 #endif
2153     int code;
2154     struct sockaddr_in addr;
2155     struct rx_peer *peer = conn->peer;
2156     osi_socket socket;
2157 #ifdef RXDEBUG
2158     char deliveryType = 'S';
2159 #endif
2160     /* The address we're sending the packet to */
2161     memset(&addr, 0, sizeof(addr));
2162     addr.sin_family = AF_INET;
2163     addr.sin_port = peer->port;
2164     addr.sin_addr.s_addr = peer->host;
2165
2166     /* This stuff should be revamped, I think, so that most, if not
2167      * all, of the header stuff is always added here.  We could
2168      * probably do away with the encode/decode routines. XXXXX */
2169
2170     /* Stamp each packet with a unique serial number.  The serial
2171      * number is maintained on a connection basis because some types
2172      * of security may be based on the serial number of the packet,
2173      * and security is handled on a per authenticated-connection
2174      * basis. */
2175     /* Pre-increment, to guarantee no zero serial number; a zero
2176      * serial number means the packet was never sent. */
2177     MUTEX_ENTER(&conn->conn_data_lock);
2178     p->header.serial = ++conn->serial;
2179     if (p->length > conn->peer->maxPacketSize) {
2180         if ((p->header.type == RX_PACKET_TYPE_ACK) &&
2181             (p->header.flags & RX_REQUEST_ACK)) {
2182             conn->lastPingSize = p->length;
2183             conn->lastPingSizeSer = p->header.serial;
2184         } else if (p->header.seq != 0) {
2185             conn->lastPacketSize = p->length;
2186             conn->lastPacketSizeSeq = p->header.seq;
2187         }
2188     }
2189     MUTEX_EXIT(&conn->conn_data_lock);
2190     /* This is so we can adjust retransmit time-outs better in the face of
2191      * rapidly changing round-trip times.  RTO estimation is not a la Karn.
2192      */
2193     if (p->firstSerial == 0) {
2194         p->firstSerial = p->header.serial;
2195     }
2196 #ifdef RXDEBUG
2197     /* If an output tracer function is defined, call it with the packet and
2198      * network address.  Note this function may modify its arguments. */
2199     if (rx_almostSent) {
2200         int drop = (*rx_almostSent) (p, &addr);
2201         /* drop packet if return value is non-zero? */
2202         if (drop)
2203             deliveryType = 'D'; /* Drop the packet */
2204     }
2205 #endif
2206
2207     /* Get network byte order header */
2208     rxi_EncodePacketHeader(p);  /* XXX in the event of rexmit, etc, don't need to
2209                                  * touch ALL the fields */
2210
2211     /* Send the packet out on the same socket that related packets are being
2212      * received on */
2213     socket =
2214         (conn->type ==
2215          RX_CLIENT_CONNECTION ? rx_socket : conn->service->socket);
2216
2217 #ifdef RXDEBUG
2218     /* Possibly drop this packet,  for testing purposes */
2219     if ((deliveryType == 'D')
2220         || ((rx_intentionallyDroppedPacketsPer100 > 0)
2221             && (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
2222         deliveryType = 'D';     /* Drop the packet */
2223     } else {
2224         deliveryType = 'S';     /* Send the packet */
2225 #endif /* RXDEBUG */
2226
2227         /* Loop until the packet is sent.  We'd prefer just to use a
2228          * blocking socket, but unfortunately the interface doesn't
2229          * allow us to have the socket block in send mode, and not
2230          * block in receive mode */
2231 #ifdef KERNEL
2232         waslocked = ISAFS_GLOCK();
2233 #ifdef RX_KERNEL_TRACE
2234         if (ICL_SETACTIVE(afs_iclSetp)) {
2235             if (!waslocked)
2236                 AFS_GLOCK();
2237             afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2238                        "before osi_NetSend()");
2239             AFS_GUNLOCK();
2240         }
2241 #else
2242         if (waslocked)
2243             AFS_GUNLOCK();
2244 #endif
2245 #endif
2246         if ((code =
2247              osi_NetSend(socket, &addr, p->wirevec, p->niovecs,
2248                          p->length + RX_HEADER_SIZE, istack)) != 0) {
2249             /* send failed, so let's hurry up the resend, eh? */
2250             if (rx_stats_active)
2251                 rx_atomic_inc(&rx_stats.netSendFailures);
2252             p->flags &= ~RX_PKTFLAG_SENT; /* resend it very soon */
2253
2254             /* Some systems are nice and tell us right away that we cannot
2255              * reach this recipient by returning an error code.
2256              * So, when this happens let's "down" the host NOW so
2257              * we don't sit around waiting for this host to timeout later.
2258              */
2259             if (call &&
2260 #ifdef AFS_NT40_ENV
2261                 (code == -1 && WSAGetLastError() == WSAEHOSTUNREACH) || (code == -WSAEHOSTUNREACH)
2262 #elif defined(AFS_LINUX20_ENV)
2263                 code == -ENETUNREACH
2264 #elif defined(AFS_DARWIN_ENV)
2265                 code == EHOSTUNREACH
2266 #else
2267                 0
2268 #endif
2269                 )
2270                 call->lastReceiveTime = 0;
2271         }
2272 #ifdef KERNEL
2273 #ifdef RX_KERNEL_TRACE
2274         if (ICL_SETACTIVE(afs_iclSetp)) {
2275             AFS_GLOCK();
2276             afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
2277                        "after osi_NetSend()");
2278             if (!waslocked)
2279                 AFS_GUNLOCK();
2280         }
2281 #else
2282         if (waslocked)
2283             AFS_GLOCK();
2284 #endif
2285 #endif
2286 #ifdef RXDEBUG
2287     }
2288     dpf(("%c %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %"AFS_PTR_FMT" len %d\n",
2289           deliveryType, p->header.serial, rx_packetTypes[p->header.type - 1], ntohl(peer->host),
2290           ntohs(peer->port), p->header.serial, p->header.epoch, p->header.cid, p->header.callNumber,
2291           p->header.seq, p->header.flags, p, p->length));
2292 #endif
2293     if (rx_stats_active) {
2294         rx_atomic_inc(&rx_stats.packetsSent[p->header.type - 1]);
2295         MUTEX_ENTER(&peer->peer_lock);
2296         hadd32(peer->bytesSent, p->length);
2297         MUTEX_EXIT(&peer->peer_lock);
2298     }
2299 }
2300
2301 /* Send a list of packets to appropriate destination for the specified
2302  * connection.  The headers are first encoded and placed in the packets.
2303  */
2304 void
2305 rxi_SendPacketList(struct rx_call *call, struct rx_connection *conn,
2306                    struct rx_packet **list, int len, int istack)
2307 {
2308 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
2309     int waslocked;
2310 #endif
2311     struct sockaddr_in addr;
2312     struct rx_peer *peer = conn->peer;
2313     osi_socket socket;
2314     struct rx_packet *p = NULL;
2315     struct iovec wirevec[RX_MAXIOVECS];
2316     int i, length, code;
2317     afs_uint32 serial;
2318     afs_uint32 temp;
2319     struct rx_jumboHeader *jp;
2320 #ifdef RXDEBUG
2321     char deliveryType = 'S';
2322 #endif
2323     /* The address we're sending the packet to */
2324     addr.sin_family = AF_INET;
2325     addr.sin_port = peer->port;
2326     addr.sin_addr.s_addr = peer->host;
2327
2328     if (len + 1 > RX_MAXIOVECS) {
2329         osi_Panic("rxi_SendPacketList, len > RX_MAXIOVECS\n");
2330     }
2331
2332     /*
2333      * Stamp the packets in this jumbogram with consecutive serial numbers
2334      */
2335     MUTEX_ENTER(&conn->conn_data_lock);
2336     serial = conn->serial;
2337     conn->serial += len;
2338     for (i = 0; i < len; i++) {
2339         p = list[i];
2340         if (p->length > conn->peer->maxPacketSize) {
2341             /* a ping *or* a sequenced packet can count */
2342             if ((p->length > conn->peer->maxPacketSize)) {
2343                 if (((p->header.type == RX_PACKET_TYPE_ACK) &&
2344                      (p->header.flags & RX_REQUEST_ACK)) &&
2345                     ((i == 0) || (p->length >= conn->lastPingSize))) {
2346                     conn->lastPingSize = p->length;
2347                     conn->lastPingSizeSer = serial + i;
2348                 } else if ((p->header.seq != 0) &&
2349                            ((i == 0) || (p->length >= conn->lastPacketSize))) {
2350                     conn->lastPacketSize = p->length;
2351                     conn->lastPacketSizeSeq = p->header.seq;
2352                 }
2353             }
2354         }
2355     }
2356     MUTEX_EXIT(&conn->conn_data_lock);
2357
2358
2359     /* This stuff should be revamped, I think, so that most, if not
2360      * all, of the header stuff is always added here.  We could
2361      * probably do away with the encode/decode routines. XXXXX */
2362
2363     jp = NULL;
2364     length = RX_HEADER_SIZE;
2365     wirevec[0].iov_base = (char *)(&list[0]->wirehead[0]);
2366     wirevec[0].iov_len = RX_HEADER_SIZE;
2367     for (i = 0; i < len; i++) {
2368         p = list[i];
2369
2370         /* The whole 3.5 jumbogram scheme relies on packets fitting
2371          * in a single packet buffer. */
2372         if (p->niovecs > 2) {
2373             osi_Panic("rxi_SendPacketList, niovecs > 2\n");
2374         }
2375
2376         /* Set the RX_JUMBO_PACKET flags in all but the last packets
2377          * in this chunk.  */
2378         if (i < len - 1) {
2379             if (p->length != RX_JUMBOBUFFERSIZE) {
2380                 osi_Panic("rxi_SendPacketList, length != jumbo size\n");
2381             }
2382             p->header.flags |= RX_JUMBO_PACKET;
2383             length += RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2384             wirevec[i + 1].iov_len = RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2385         } else {
2386             wirevec[i + 1].iov_len = p->length;
2387             length += p->length;
2388         }
2389         wirevec[i + 1].iov_base = (char *)(&p->localdata[0]);
2390         if (jp != NULL) {
2391             /* Convert jumbo packet header to network byte order */
2392             temp = (afs_uint32) (p->header.flags) << 24;
2393             temp |= (afs_uint32) (p->header.spare);
2394             *(afs_uint32 *) jp = htonl(temp);
2395         }
2396         jp = (struct rx_jumboHeader *)
2397             ((char *)(&p->localdata[0]) + RX_JUMBOBUFFERSIZE);
2398
2399         /* Stamp each packet with a unique serial number.  The serial
2400          * number is maintained on a connection basis because some types
2401          * of security may be based on the serial number of the packet,
2402          * and security is handled on a per authenticated-connection
2403          * basis. */
2404         /* Pre-increment, to guarantee no zero serial number; a zero
2405          * serial number means the packet was never sent. */
2406         p->header.serial = ++serial;
2407         /* This is so we can adjust retransmit time-outs better in the face of
2408          * rapidly changing round-trip times.  RTO estimation is not a la Karn.
2409          */
2410         if (p->firstSerial == 0) {
2411             p->firstSerial = p->header.serial;
2412         }
2413 #ifdef RXDEBUG
2414         /* If an output tracer function is defined, call it with the packet and
2415          * network address.  Note this function may modify its arguments. */
2416         if (rx_almostSent) {
2417             int drop = (*rx_almostSent) (p, &addr);
2418             /* drop packet if return value is non-zero? */
2419             if (drop)
2420                 deliveryType = 'D';     /* Drop the packet */
2421         }
2422 #endif
2423
2424         /* Get network byte order header */
2425         rxi_EncodePacketHeader(p);      /* XXX in the event of rexmit, etc, don't need to
2426                                          * touch ALL the fields */
2427     }
2428
2429     /* Send the packet out on the same socket that related packets are being
2430      * received on */
2431     socket =
2432         (conn->type ==
2433          RX_CLIENT_CONNECTION ? rx_socket : conn->service->socket);
2434
2435 #ifdef RXDEBUG
2436     /* Possibly drop this packet,  for testing purposes */
2437     if ((deliveryType == 'D')
2438         || ((rx_intentionallyDroppedPacketsPer100 > 0)
2439             && (random() % 100 < rx_intentionallyDroppedPacketsPer100))) {
2440         deliveryType = 'D';     /* Drop the packet */
2441     } else {
2442         deliveryType = 'S';     /* Send the packet */
2443 #endif /* RXDEBUG */
2444
2445         /* Loop until the packet is sent.  We'd prefer just to use a
2446          * blocking socket, but unfortunately the interface doesn't
2447          * allow us to have the socket block in send mode, and not
2448          * block in receive mode */
2449 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
2450         waslocked = ISAFS_GLOCK();
2451         if (!istack && waslocked)
2452             AFS_GUNLOCK();
2453 #endif
2454         if ((code =
2455              osi_NetSend(socket, &addr, &wirevec[0], len + 1, length,
2456                          istack)) != 0) {
2457             /* send failed, so let's hurry up the resend, eh? */
2458             if (rx_stats_active)
2459                 rx_atomic_inc(&rx_stats.netSendFailures);
2460             for (i = 0; i < len; i++) {
2461                 p = list[i];
2462                 p->flags &= ~RX_PKTFLAG_SENT;  /* resend it very soon */
2463             }
2464             /* Some systems are nice and tell us right away that we cannot
2465              * reach this recipient by returning an error code.
2466              * So, when this happens let's "down" the host NOW so
2467              * we don't sit around waiting for this host to timeout later.
2468              */
2469             if (call &&
2470 #ifdef AFS_NT40_ENV
2471                 (code == -1 && WSAGetLastError() == WSAEHOSTUNREACH) || (code == -WSAEHOSTUNREACH)
2472 #elif defined(AFS_LINUX20_ENV)
2473                 code == -ENETUNREACH
2474 #elif defined(AFS_DARWIN_ENV)
2475                 code == EHOSTUNREACH
2476 #else
2477                 0
2478 #endif
2479                 )
2480                 call->lastReceiveTime = 0;
2481         }
2482 #if     defined(AFS_SUN5_ENV) && defined(KERNEL)
2483         if (!istack && waslocked)
2484             AFS_GLOCK();
2485 #endif
2486 #ifdef RXDEBUG
2487     }
2488
2489     osi_Assert(p != NULL);
2490
2491     dpf(("%c %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %"AFS_PTR_FMT" len %d\n",
2492           deliveryType, p->header.serial, rx_packetTypes[p->header.type - 1], ntohl(peer->host),
2493           ntohs(peer->port), p->header.serial, p->header.epoch, p->header.cid, p->header.callNumber,
2494           p->header.seq, p->header.flags, p, p->length));
2495
2496 #endif
2497     if (rx_stats_active) {
2498         rx_atomic_inc(&rx_stats.packetsSent[p->header.type - 1]);
2499         MUTEX_ENTER(&peer->peer_lock);
2500         hadd32(peer->bytesSent, p->length);
2501         MUTEX_EXIT(&peer->peer_lock);
2502     }
2503 }
2504
2505
2506 /* Send a "special" packet to the peer connection.  If call is
2507  * specified, then the packet is directed to a specific call channel
2508  * associated with the connection, otherwise it is directed to the
2509  * connection only. Uses optionalPacket if it is supplied, rather than
2510  * allocating a new packet buffer.  Nbytes is the length of the data
2511  * portion of the packet.  If data is non-null, nbytes of data are
2512  * copied into the packet.  Type is the type of the packet, as defined
2513  * in rx.h.  Bug: there's a lot of duplication between this and other
2514  * routines.  This needs to be cleaned up. */
2515 struct rx_packet *
2516 rxi_SendSpecial(struct rx_call *call,
2517                 struct rx_connection *conn,
2518                 struct rx_packet *optionalPacket, int type, char *data,
2519                 int nbytes, int istack)
2520 {
2521     /* Some of the following stuff should be common code for all
2522      * packet sends (it's repeated elsewhere) */
2523     struct rx_packet *p;
2524     unsigned int i = 0;
2525     int savelen = 0, saven = 0;
2526     int channel, callNumber;
2527     if (call) {
2528         channel = call->channel;
2529         callNumber = *call->callNumber;
2530         /* BUSY packets refer to the next call on this connection */
2531         if (type == RX_PACKET_TYPE_BUSY) {
2532             callNumber++;
2533         }
2534     } else {
2535         channel = 0;
2536         callNumber = 0;
2537     }
2538     p = optionalPacket;
2539     if (!p) {
2540         p = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL);
2541         if (!p)
2542             osi_Panic("rxi_SendSpecial failure");
2543     }
2544
2545     if (nbytes != -1)
2546         p->length = nbytes;
2547     else
2548         nbytes = p->length;
2549     p->header.serviceId = conn->serviceId;
2550     p->header.securityIndex = conn->securityIndex;
2551     p->header.cid = (conn->cid | channel);
2552     p->header.callNumber = callNumber;
2553     p->header.seq = 0;
2554     p->header.epoch = conn->epoch;
2555     p->header.type = type;
2556     p->header.flags = 0;
2557     if (conn->type == RX_CLIENT_CONNECTION)
2558         p->header.flags |= RX_CLIENT_INITIATED;
2559     if (data)
2560         rx_packetwrite(p, 0, nbytes, data);
2561
2562     for (i = 1; i < p->niovecs; i++) {
2563         if (nbytes <= p->wirevec[i].iov_len) {
2564             savelen = p->wirevec[i].iov_len;
2565             saven = p->niovecs;
2566             p->wirevec[i].iov_len = nbytes;
2567             p->niovecs = i + 1; /* so condition fails because i == niovecs */
2568         } else
2569             nbytes -= p->wirevec[i].iov_len;
2570     }
2571
2572     if (call)
2573         rxi_Send(call, p, istack);
2574     else
2575         rxi_SendPacket((struct rx_call *)0, conn, p, istack);
2576     if (saven) {                /* means we truncated the packet above.  We probably don't  */
2577         /* really need to do this, but it seems safer this way, given that  */
2578         /* sneaky optionalPacket... */
2579         p->wirevec[i - 1].iov_len = savelen;
2580         p->niovecs = saven;
2581     }
2582     if (!optionalPacket)
2583         rxi_FreePacket(p);
2584     return optionalPacket;
2585 }
2586
2587
2588 /* Encode the packet's header (from the struct header in the packet to
2589  * the net byte order representation in the wire representation of the
2590  * packet, which is what is actually sent out on the wire) */
2591 void
2592 rxi_EncodePacketHeader(struct rx_packet *p)
2593 {
2594     afs_uint32 *buf = (afs_uint32 *) (p->wirevec[0].iov_base);  /* MTUXXX */
2595
2596     memset(buf, 0, RX_HEADER_SIZE);
2597     *buf++ = htonl(p->header.epoch);
2598     *buf++ = htonl(p->header.cid);
2599     *buf++ = htonl(p->header.callNumber);
2600     *buf++ = htonl(p->header.seq);
2601     *buf++ = htonl(p->header.serial);
2602     *buf++ = htonl((((afs_uint32) p->header.type) << 24)
2603                    | (((afs_uint32) p->header.flags) << 16)
2604                    | (p->header.userStatus << 8) | p->header.securityIndex);
2605     /* Note: top 16 bits of this next word were reserved */
2606     *buf++ = htonl((p->header.spare << 16) | (p->header.serviceId & 0xffff));
2607 }
2608
2609 /* Decode the packet's header (from net byte order to a struct header) */
2610 void
2611 rxi_DecodePacketHeader(struct rx_packet *p)
2612 {
2613     afs_uint32 *buf = (afs_uint32 *) (p->wirevec[0].iov_base);  /* MTUXXX */
2614     afs_uint32 temp;
2615
2616     p->header.epoch = ntohl(*buf);
2617     buf++;
2618     p->header.cid = ntohl(*buf);
2619     buf++;
2620     p->header.callNumber = ntohl(*buf);
2621     buf++;
2622     p->header.seq = ntohl(*buf);
2623     buf++;
2624     p->header.serial = ntohl(*buf);
2625     buf++;
2626
2627     temp = ntohl(*buf);
2628     buf++;
2629
2630     /* C will truncate byte fields to bytes for me */
2631     p->header.type = temp >> 24;
2632     p->header.flags = temp >> 16;
2633     p->header.userStatus = temp >> 8;
2634     p->header.securityIndex = temp >> 0;
2635
2636     temp = ntohl(*buf);
2637     buf++;
2638
2639     p->header.serviceId = (temp & 0xffff);
2640     p->header.spare = temp >> 16;
2641     /* Note: top 16 bits of this last word are the security checksum */
2642 }
2643
2644 /*
2645  * LOCKS HELD: called with call->lock held.
2646  *
2647  * PrepareSendPacket is the only place in the code that
2648  * can increment call->tnext.  This could become an atomic
2649  * in the future.  Beyond that there is nothing in this
2650  * function that requires the call being locked.  This
2651  * function can only be called by the application thread.
2652  */
2653 void
2654 rxi_PrepareSendPacket(struct rx_call *call,
2655                       struct rx_packet *p, int last)
2656 {
2657     struct rx_connection *conn = call->conn;
2658     afs_uint32 seq = call->tnext++;
2659     unsigned int i;
2660     afs_int32 len;              /* len must be a signed type; it can go negative */
2661
2662     /* No data packets on call 0. Where do these come from? */
2663     if (*call->callNumber == 0)
2664         *call->callNumber = 1;
2665
2666     MUTEX_EXIT(&call->lock);
2667     p->flags &= ~(RX_PKTFLAG_ACKED | RX_PKTFLAG_SENT);
2668
2669     p->header.cid = (conn->cid | call->channel);
2670     p->header.serviceId = conn->serviceId;
2671     p->header.securityIndex = conn->securityIndex;
2672
2673     p->header.callNumber = *call->callNumber;
2674     p->header.seq = seq;
2675     p->header.epoch = conn->epoch;
2676     p->header.type = RX_PACKET_TYPE_DATA;
2677     p->header.flags = 0;
2678     p->header.spare = 0;
2679     if (conn->type == RX_CLIENT_CONNECTION)
2680         p->header.flags |= RX_CLIENT_INITIATED;
2681
2682     if (last)
2683         p->header.flags |= RX_LAST_PACKET;
2684
2685     clock_Zero(&p->firstSent);  /* Never yet transmitted */
2686     p->header.serial = 0;       /* Another way of saying never transmitted... */
2687
2688     /* Now that we're sure this is the last data on the call, make sure
2689      * that the "length" and the sum of the iov_lens matches. */
2690     len = p->length + call->conn->securityHeaderSize;
2691
2692     for (i = 1; i < p->niovecs && len > 0; i++) {
2693         len -= p->wirevec[i].iov_len;
2694     }
2695     if (len > 0) {
2696         osi_Panic("PrepareSendPacket 1\n");     /* MTUXXX */
2697     } else if (i < p->niovecs) {
2698         /* Free any extra elements in the wirevec */
2699 #if defined(RX_ENABLE_TSFPQ)
2700         rxi_FreeDataBufsTSFPQ(p, i, 1 /* allow global pool flush if overquota */);
2701 #else /* !RX_ENABLE_TSFPQ */
2702         MUTEX_ENTER(&rx_freePktQ_lock);
2703         rxi_FreeDataBufsNoLock(p, i);
2704         MUTEX_EXIT(&rx_freePktQ_lock);
2705 #endif /* !RX_ENABLE_TSFPQ */
2706
2707         p->niovecs = i;
2708     }
2709     if (len)
2710         p->wirevec[i - 1].iov_len += len;
2711     MUTEX_ENTER(&call->lock);
2712     RXS_PreparePacket(conn->securityObject, call, p);
2713 }
2714
2715 /* Given an interface MTU size, calculate an adjusted MTU size that
2716  * will make efficient use of the RX buffers when the peer is sending
2717  * either AFS 3.4a jumbograms or AFS 3.5 jumbograms.  */
2718 int
2719 rxi_AdjustIfMTU(int mtu)
2720 {
2721     int adjMTU;
2722     int frags;
2723
2724     if (rxi_nRecvFrags == 1 && rxi_nSendFrags == 1)
2725         return mtu;
2726     adjMTU = RX_HEADER_SIZE + RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE;
2727     if (mtu <= adjMTU) {
2728         return mtu;
2729     }
2730     mtu -= adjMTU;
2731     if (mtu <= 0) {
2732         return adjMTU;
2733     }
2734     frags = mtu / (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE);
2735     return (adjMTU + (frags * (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE)));
2736 }
2737
2738 /* Given an interface MTU size, and the peer's advertised max receive
2739  * size, calculate an adjisted maxMTU size that makes efficient use
2740  * of our packet buffers when we are sending AFS 3.4a jumbograms. */
2741 int
2742 rxi_AdjustMaxMTU(int mtu, int peerMaxMTU)
2743 {
2744     int maxMTU = mtu * rxi_nSendFrags;
2745     maxMTU = MIN(maxMTU, peerMaxMTU);
2746     return rxi_AdjustIfMTU(maxMTU);
2747 }
2748
2749 /* Given a packet size, figure out how many datagram packet will fit.
2750  * The first buffer always contains RX_HEADER_SIZE+RX_JUMBOBUFFERSIZE+
2751  * RX_JUMBOHEADERSIZE, the middle buffers contain RX_JUMBOBUFFERSIZE+
2752  * RX_JUMBOHEADERSIZE, and the last buffer contains RX_JUMBOBUFFERSIZE */
2753 int
2754 rxi_AdjustDgramPackets(int frags, int mtu)
2755 {
2756     int maxMTU;
2757     if (mtu + IPv6_FRAG_HDR_SIZE < RX_JUMBOBUFFERSIZE + RX_HEADER_SIZE) {
2758         return 1;
2759     }
2760     maxMTU = (frags * (mtu + UDP_HDR_SIZE)) - UDP_HDR_SIZE;
2761     maxMTU = MIN(maxMTU, RX_MAX_PACKET_SIZE);
2762     /* subtract the size of the first and last packets */
2763     maxMTU -= RX_HEADER_SIZE + (2 * RX_JUMBOBUFFERSIZE) + RX_JUMBOHEADERSIZE;
2764     if (maxMTU < 0) {
2765         return 1;
2766     }
2767     return (2 + (maxMTU / (RX_JUMBOBUFFERSIZE + RX_JUMBOHEADERSIZE)));
2768 }
2769
2770 #ifndef KERNEL
2771 /*
2772  * This function can be used by the Windows Cache Manager
2773  * to dump the list of all rx packets so that we can determine
2774  * where the packet leakage is.
2775  */
2776 int rx_DumpPackets(FILE *outputFile, char *cookie)
2777 {
2778 #ifdef RXDEBUG_PACKET
2779     struct rx_packet *p;
2780 #ifdef AFS_NT40_ENV
2781     int zilch;
2782     char output[2048];
2783 #define RXDPRINTF sprintf
2784 #define RXDPRINTOUT output
2785 #else
2786 #define RXDPRINTF fprintf
2787 #define RXDPRINTOUT outputFile
2788 #endif
2789
2790     NETPRI;
2791     MUTEX_ENTER(&rx_freePktQ_lock);
2792     RXDPRINTF(RXDPRINTOUT, "%s - Start dumping all Rx Packets - count=%u\r\n", cookie, rx_packet_id);
2793 #ifdef AFS_NT40_ENV
2794     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
2795 #endif
2796
2797     for (p = rx_mallocedP; p; p = p->allNextp) {
2798         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",
2799                 cookie, p, p->packetId, p->firstSent.sec, p->firstSent.usec, p->timeSent.sec, p->timeSent.usec,
2800                 p->firstSerial, p->niovecs, (afs_uint32)p->flags, (afs_uint32)p->length,
2801                 p->header.epoch, p->header.cid, p->header.callNumber, p->header.seq, p->header.serial,
2802                 (afs_uint32)p->header.type, (afs_uint32)p->header.flags, (afs_uint32)p->header.userStatus,
2803                 (afs_uint32)p->header.securityIndex, (afs_uint32)p->header.serviceId);
2804 #ifdef AFS_NT40_ENV
2805         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
2806 #endif
2807     }
2808
2809     RXDPRINTF(RXDPRINTOUT, "%s - End dumping all Rx Packets\r\n", cookie);
2810 #ifdef AFS_NT40_ENV
2811     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
2812 #endif
2813
2814     MUTEX_EXIT(&rx_freePktQ_lock);
2815     USERPRI;
2816 #endif /* RXDEBUG_PACKET */
2817     return 0;
2818 }
2819 #endif