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