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