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