2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* RX: Extended Remote Procedure Call */
12 #include <afsconfig.h>
13 #include <afs/param.h>
16 # include "afs/sysincludes.h"
17 # include "afsincludes.h"
22 # ifdef AFS_LINUX20_ENV
23 # include "h/socket.h"
25 # include "netinet/in.h"
27 # include "netinet/ip6.h"
28 # include "inet/common.h"
30 # include "inet/ip_ire.h"
32 # include "afs/afs_args.h"
33 # include "afs/afs_osi.h"
34 # ifdef RX_KERNEL_TRACE
35 # include "rx_kcommon.h"
37 # if defined(AFS_AIX_ENV)
41 # undef RXDEBUG /* turn off debugging */
43 # if defined(AFS_SGI_ENV)
44 # include "sys/debug.h"
47 # include "afs/sysincludes.h"
48 # include "afsincludes.h"
49 # endif /* !UKERNEL */
50 # include "afs/lock.h"
51 # include "rx_kmutex.h"
52 # include "rx_kernel.h"
53 # define AFSOP_STOP_RXCALLBACK 210 /* Stop CALLBACK process */
54 # define AFSOP_STOP_AFS 211 /* Stop AFS process */
55 # define AFSOP_STOP_BKG 212 /* Stop BKG process */
56 extern afs_int32 afs_termState
;
58 # include "sys/lockl.h"
59 # include "sys/lock_def.h"
60 # endif /* AFS_AIX41_ENV */
61 # include "afs/rxgen_consts.h"
66 # include <afs/afsutil.h>
67 # include <WINNT\afsreg.h>
75 #include <opr/queue.h>
76 #include <hcrypto/rand.h>
80 #include "rx_atomic.h"
81 #include "rx_globals.h"
83 #include "rx_internal.h"
90 #include "rx_packet.h"
91 #include "rx_server.h"
93 #include <afs/rxgen_consts.h>
96 #ifdef AFS_PTHREAD_ENV
98 int (*registerProgram
) (pid_t
, char *) = 0;
99 int (*swapNameProgram
) (pid_t
, const char *, char *) = 0;
102 int (*registerProgram
) (PROCESS
, char *) = 0;
103 int (*swapNameProgram
) (PROCESS
, const char *, char *) = 0;
107 /* Local static routines */
108 static void rxi_DestroyConnectionNoLock(struct rx_connection
*conn
);
109 static void rxi_ComputeRoundTripTime(struct rx_packet
*, struct rx_ackPacket
*,
110 struct rx_call
*, struct rx_peer
*,
112 static void rxi_Resend(struct rxevent
*event
, void *arg0
, void *arg1
,
114 static void rxi_SendDelayedAck(struct rxevent
*event
, void *call
,
115 void *dummy
, int dummy2
);
116 static void rxi_SendDelayedCallAbort(struct rxevent
*event
, void *arg1
,
117 void *dummy
, int dummy2
);
118 static void rxi_SendDelayedConnAbort(struct rxevent
*event
, void *arg1
,
119 void *unused
, int unused2
);
120 static void rxi_ReapConnections(struct rxevent
*unused
, void *unused1
,
121 void *unused2
, int unused3
);
122 static struct rx_packet
*rxi_SendCallAbort(struct rx_call
*call
,
123 struct rx_packet
*packet
,
124 int istack
, int force
);
125 static void rxi_AckAll(struct rx_call
*call
);
126 static struct rx_connection
127 *rxi_FindConnection(osi_socket socket
, afs_uint32 host
, u_short port
,
128 u_short serviceId
, afs_uint32 cid
,
129 afs_uint32 epoch
, int type
, u_int securityIndex
,
130 int *unknownService
);
131 static struct rx_packet
132 *rxi_ReceiveDataPacket(struct rx_call
*call
, struct rx_packet
*np
,
133 int istack
, osi_socket socket
,
134 afs_uint32 host
, u_short port
, int *tnop
,
135 struct rx_call
**newcallp
);
136 static struct rx_packet
137 *rxi_ReceiveAckPacket(struct rx_call
*call
, struct rx_packet
*np
,
139 static struct rx_packet
140 *rxi_ReceiveResponsePacket(struct rx_connection
*conn
,
141 struct rx_packet
*np
, int istack
);
142 static struct rx_packet
143 *rxi_ReceiveChallengePacket(struct rx_connection
*conn
,
144 struct rx_packet
*np
, int istack
);
145 static void rxi_AttachServerProc(struct rx_call
*call
, osi_socket socket
,
146 int *tnop
, struct rx_call
**newcallp
);
147 static void rxi_ClearTransmitQueue(struct rx_call
*call
, int force
);
148 static void rxi_ClearReceiveQueue(struct rx_call
*call
);
149 static void rxi_ResetCall(struct rx_call
*call
, int newcall
);
150 static void rxi_ScheduleKeepAliveEvent(struct rx_call
*call
);
151 static void rxi_ScheduleNatKeepAliveEvent(struct rx_connection
*conn
);
152 static void rxi_ScheduleGrowMTUEvent(struct rx_call
*call
, int secs
);
153 static void rxi_KeepAliveOn(struct rx_call
*call
);
154 static void rxi_GrowMTUOn(struct rx_call
*call
);
155 static void rxi_ChallengeOn(struct rx_connection
*conn
);
156 static int rxi_CheckCall(struct rx_call
*call
, int haveCTLock
);
157 static void rxi_AckAllInTransmitQueue(struct rx_call
*call
);
158 static void rxi_CancelKeepAliveEvent(struct rx_call
*call
);
159 static void rxi_CancelDelayedAbortEvent(struct rx_call
*call
);
160 static void rxi_CancelGrowMTUEvent(struct rx_call
*call
);
161 static void update_nextCid(void);
163 #ifdef RX_ENABLE_LOCKS
165 rx_atomic_t rxi_start_aborted
; /* rxi_start awoke after rxi_Send in error.*/
166 rx_atomic_t rxi_start_in_error
;
168 #endif /* RX_ENABLE_LOCKS */
170 /* Constant delay time before sending an acknowledge of the last packet
171 * received. This is to avoid sending an extra acknowledge when the
172 * client is about to make another call, anyway, or the server is
175 * The lastAckDelay may not exceeed 400ms without causing peers to
176 * unecessarily timeout.
178 struct clock rx_lastAckDelay
= {0, 400000};
180 /* Constant delay time before sending a soft ack when none was requested.
181 * This is to make sure we send soft acks before the sender times out,
182 * Normally we wait and send a hard ack when the receiver consumes the packet
184 * This value has been 100ms in all shipping versions of OpenAFS. Changing it
185 * will require changes to the peer's RTT calculations.
187 struct clock rx_softAckDelay
= {0, 100000};
190 * rxi_rpc_peer_stat_cnt counts the total number of peer stat structures
191 * currently allocated within rx. This number is used to allocate the
192 * memory required to return the statistics when queried.
193 * Protected by the rx_rpc_stats mutex.
196 static unsigned int rxi_rpc_peer_stat_cnt
;
199 * rxi_rpc_process_stat_cnt counts the total number of local process stat
200 * structures currently allocated within rx. The number is used to allocate
201 * the memory required to return the statistics when queried.
202 * Protected by the rx_rpc_stats mutex.
205 static unsigned int rxi_rpc_process_stat_cnt
;
207 rx_atomic_t rx_nWaiting
= RX_ATOMIC_INIT(0);
208 rx_atomic_t rx_nWaited
= RX_ATOMIC_INIT(0);
210 /* Incoming calls wait on this queue when there are no available
211 * server processes */
212 struct opr_queue rx_incomingCallQueue
;
214 /* Server processes wait on this queue when there are no appropriate
215 * calls to process */
216 struct opr_queue rx_idleServerQueue
;
218 #if !defined(offsetof)
219 #include <stddef.h> /* for definition of offsetof() */
222 #ifdef RX_ENABLE_LOCKS
223 afs_kmutex_t rx_atomic_mutex
;
226 /* Forward prototypes */
227 static struct rx_call
* rxi_NewCall(struct rx_connection
*, int);
230 putConnection (struct rx_connection
*conn
) {
231 MUTEX_ENTER(&rx_refcnt_mutex
);
233 MUTEX_EXIT(&rx_refcnt_mutex
);
236 #ifdef AFS_PTHREAD_ENV
239 * Use procedural initialization of mutexes/condition variables
243 extern afs_kmutex_t rx_quota_mutex
;
244 extern afs_kmutex_t rx_pthread_mutex
;
245 extern afs_kmutex_t rx_packets_mutex
;
246 extern afs_kmutex_t rx_refcnt_mutex
;
247 extern afs_kmutex_t des_init_mutex
;
248 extern afs_kmutex_t des_random_mutex
;
250 extern afs_kmutex_t rx_clock_mutex
;
251 extern afs_kmutex_t rxi_connCacheMutex
;
252 extern afs_kmutex_t event_handler_mutex
;
253 extern afs_kmutex_t listener_mutex
;
254 extern afs_kmutex_t rx_if_init_mutex
;
255 extern afs_kmutex_t rx_if_mutex
;
257 extern afs_kcondvar_t rx_event_handler_cond
;
258 extern afs_kcondvar_t rx_listener_cond
;
261 static afs_kmutex_t epoch_mutex
;
262 static afs_kmutex_t rx_init_mutex
;
263 static afs_kmutex_t rx_debug_mutex
;
264 static afs_kmutex_t rx_rpc_stats
;
267 rxi_InitPthread(void)
269 MUTEX_INIT(&rx_quota_mutex
, "quota", MUTEX_DEFAULT
, 0);
270 MUTEX_INIT(&rx_pthread_mutex
, "pthread", MUTEX_DEFAULT
, 0);
271 MUTEX_INIT(&rx_packets_mutex
, "packets", MUTEX_DEFAULT
, 0);
272 MUTEX_INIT(&rx_refcnt_mutex
, "refcnts", MUTEX_DEFAULT
, 0);
274 MUTEX_INIT(&rx_clock_mutex
, "clock", MUTEX_DEFAULT
, 0);
275 MUTEX_INIT(&rxi_connCacheMutex
, "conn cache", MUTEX_DEFAULT
, 0);
276 MUTEX_INIT(&event_handler_mutex
, "event handler", MUTEX_DEFAULT
, 0);
277 MUTEX_INIT(&listener_mutex
, "listener", MUTEX_DEFAULT
, 0);
278 MUTEX_INIT(&rx_if_init_mutex
, "if init", MUTEX_DEFAULT
, 0);
279 MUTEX_INIT(&rx_if_mutex
, "if", MUTEX_DEFAULT
, 0);
281 MUTEX_INIT(&rx_stats_mutex
, "stats", MUTEX_DEFAULT
, 0);
282 MUTEX_INIT(&rx_atomic_mutex
, "atomic", MUTEX_DEFAULT
, 0);
283 MUTEX_INIT(&epoch_mutex
, "epoch", MUTEX_DEFAULT
, 0);
284 MUTEX_INIT(&rx_init_mutex
, "init", MUTEX_DEFAULT
, 0);
285 MUTEX_INIT(&rx_debug_mutex
, "debug", MUTEX_DEFAULT
, 0);
288 CV_INIT(&rx_event_handler_cond
, "evhand", CV_DEFAULT
, 0);
289 CV_INIT(&rx_listener_cond
, "rxlisten", CV_DEFAULT
, 0);
292 osi_Assert(pthread_key_create(&rx_thread_id_key
, NULL
) == 0);
293 osi_Assert(pthread_key_create(&rx_ts_info_key
, NULL
) == 0);
295 MUTEX_INIT(&rx_rpc_stats
, "rx_rpc_stats", MUTEX_DEFAULT
, 0);
296 MUTEX_INIT(&rx_freePktQ_lock
, "rx_freePktQ_lock", MUTEX_DEFAULT
, 0);
297 MUTEX_INIT(&rx_mallocedPktQ_lock
, "rx_mallocedPktQ_lock", MUTEX_DEFAULT
,
300 #ifdef RX_ENABLE_LOCKS
303 #endif /* RX_LOCKS_DB */
304 MUTEX_INIT(&freeSQEList_lock
, "freeSQEList lock", MUTEX_DEFAULT
, 0);
305 MUTEX_INIT(&rx_freeCallQueue_lock
, "rx_freeCallQueue_lock", MUTEX_DEFAULT
,
307 CV_INIT(&rx_waitingForPackets_cv
, "rx_waitingForPackets_cv", CV_DEFAULT
,
309 MUTEX_INIT(&rx_peerHashTable_lock
, "rx_peerHashTable_lock", MUTEX_DEFAULT
,
311 MUTEX_INIT(&rx_connHashTable_lock
, "rx_connHashTable_lock", MUTEX_DEFAULT
,
313 MUTEX_INIT(&rx_serverPool_lock
, "rx_serverPool_lock", MUTEX_DEFAULT
, 0);
315 MUTEX_INIT(&rxi_keyCreate_lock
, "rxi_keyCreate_lock", MUTEX_DEFAULT
, 0);
317 #endif /* RX_ENABLE_LOCKS */
320 pthread_once_t rx_once_init
= PTHREAD_ONCE_INIT
;
321 #define INIT_PTHREAD_LOCKS osi_Assert(pthread_once(&rx_once_init, rxi_InitPthread)==0)
323 * The rx_stats_mutex mutex protects the following global variables:
324 * rxi_lowConnRefCount
325 * rxi_lowPeerRefCount
334 * The rx_quota_mutex mutex protects the following global variables:
342 * The rx_freePktQ_lock protects the following global variables:
347 * The rx_packets_mutex mutex protects the following global variables:
355 * The rx_pthread_mutex mutex protects the following global variables:
356 * rxi_fcfs_thread_num
359 #define INIT_PTHREAD_LOCKS
363 /* Variables for handling the minProcs implementation. availProcs gives the
364 * number of threads available in the pool at this moment (not counting dudes
365 * executing right now). totalMin gives the total number of procs required
366 * for handling all minProcs requests. minDeficit is a dynamic variable
367 * tracking the # of procs required to satisfy all of the remaining minProcs
369 * For fine grain locking to work, the quota check and the reservation of
370 * a server thread has to come while rxi_availProcs and rxi_minDeficit
371 * are locked. To this end, the code has been modified under #ifdef
372 * RX_ENABLE_LOCKS so that quota checks and reservation occur at the
373 * same time. A new function, ReturnToServerPool() returns the allocation.
375 * A call can be on several queue's (but only one at a time). When
376 * rxi_ResetCall wants to remove the call from a queue, it has to ensure
377 * that no one else is touching the queue. To this end, we store the address
378 * of the queue lock in the call structure (under the call lock) when we
379 * put the call on a queue, and we clear the call_queue_lock when the
380 * call is removed from a queue (once the call lock has been obtained).
381 * This allows rxi_ResetCall to safely synchronize with others wishing
382 * to manipulate the queue.
385 #if defined(RX_ENABLE_LOCKS)
386 static afs_kmutex_t rx_rpc_stats
;
389 /* We keep a "last conn pointer" in rxi_FindConnection. The odds are
390 ** pretty good that the next packet coming in is from the same connection
391 ** as the last packet, since we're send multiple packets in a transmit window.
393 struct rx_connection
*rxLastConn
= 0;
395 #ifdef RX_ENABLE_LOCKS
396 /* The locking hierarchy for rx fine grain locking is composed of these
399 * rx_connHashTable_lock - synchronizes conn creation, rx_connHashTable access
400 * also protects updates to rx_nextCid
401 * conn_call_lock - used to synchonize rx_EndCall and rx_NewCall
402 * call->lock - locks call data fields.
403 * These are independent of each other:
404 * rx_freeCallQueue_lock
409 * serverQueueEntry->lock
410 * rx_peerHashTable_lock - locked under rx_connHashTable_lock
412 * peer->lock - locks peer data fields.
413 * conn_data_lock - that more than one thread is not updating a conn data
414 * field at the same time.
425 * Do we need a lock to protect the peer field in the conn structure?
426 * conn->peer was previously a constant for all intents and so has no
427 * lock protecting this field. The multihomed client delta introduced
428 * a RX code change : change the peer field in the connection structure
429 * to that remote interface from which the last packet for this
430 * connection was sent out. This may become an issue if further changes
433 #define SET_CALL_QUEUE_LOCK(C, L) (C)->call_queue_lock = (L)
434 #define CLEAR_CALL_QUEUE_LOCK(C) (C)->call_queue_lock = NULL
436 /* rxdb_fileID is used to identify the lock location, along with line#. */
437 static int rxdb_fileID
= RXDB_FILE_RX
;
438 #endif /* RX_LOCKS_DB */
439 #else /* RX_ENABLE_LOCKS */
440 #define SET_CALL_QUEUE_LOCK(C, L)
441 #define CLEAR_CALL_QUEUE_LOCK(C)
442 #endif /* RX_ENABLE_LOCKS */
443 struct rx_serverQueueEntry
*rx_waitForPacket
= 0;
445 /* ------------Exported Interfaces------------- */
447 /* Initialize rx. A port number may be mentioned, in which case this
448 * becomes the default port number for any service installed later.
449 * If 0 is provided for the port number, a random port will be chosen
450 * by the kernel. Whether this will ever overlap anything in
451 * /etc/services is anybody's guess... Returns 0 on success, -1 on
453 #if !(defined(AFS_NT40_ENV) || defined(RXK_UPCALL_ENV))
456 rx_atomic_t rxinit_status
= RX_ATOMIC_INIT(1);
459 rx_InitHost(u_int host
, u_int port
)
466 char *htable
, *ptable
;
471 if (!rx_atomic_test_and_clear_bit(&rxinit_status
, 0))
472 return 0; /* already started */
478 if (afs_winsockInit() < 0)
484 * Initialize anything necessary to provide a non-premptive threading
487 rxi_InitializeThreadSupport();
490 /* Allocate and initialize a socket for client and perhaps server
493 rx_socket
= rxi_GetHostUDPSocket(host
, (u_short
) port
);
494 if (rx_socket
== OSI_NULLSOCKET
) {
497 #if defined(RX_ENABLE_LOCKS) && defined(KERNEL)
500 #endif /* RX_LOCKS_DB */
501 MUTEX_INIT(&rx_stats_mutex
, "rx_stats_mutex", MUTEX_DEFAULT
, 0);
502 MUTEX_INIT(&rx_quota_mutex
, "rx_quota_mutex", MUTEX_DEFAULT
, 0);
503 MUTEX_INIT(&rx_atomic_mutex
, "rx_atomic_mutex", MUTEX_DEFAULT
, 0);
504 MUTEX_INIT(&rx_pthread_mutex
, "rx_pthread_mutex", MUTEX_DEFAULT
, 0);
505 MUTEX_INIT(&rx_packets_mutex
, "rx_packets_mutex", MUTEX_DEFAULT
, 0);
506 MUTEX_INIT(&rx_refcnt_mutex
, "rx_refcnt_mutex", MUTEX_DEFAULT
, 0);
507 MUTEX_INIT(&rx_rpc_stats
, "rx_rpc_stats", MUTEX_DEFAULT
, 0);
508 MUTEX_INIT(&rx_freePktQ_lock
, "rx_freePktQ_lock", MUTEX_DEFAULT
, 0);
509 MUTEX_INIT(&freeSQEList_lock
, "freeSQEList lock", MUTEX_DEFAULT
, 0);
510 MUTEX_INIT(&rx_freeCallQueue_lock
, "rx_freeCallQueue_lock", MUTEX_DEFAULT
,
512 CV_INIT(&rx_waitingForPackets_cv
, "rx_waitingForPackets_cv", CV_DEFAULT
,
514 MUTEX_INIT(&rx_peerHashTable_lock
, "rx_peerHashTable_lock", MUTEX_DEFAULT
,
516 MUTEX_INIT(&rx_connHashTable_lock
, "rx_connHashTable_lock", MUTEX_DEFAULT
,
518 MUTEX_INIT(&rx_serverPool_lock
, "rx_serverPool_lock", MUTEX_DEFAULT
, 0);
519 MUTEX_INIT(&rx_mallocedPktQ_lock
, "rx_mallocedPktQ_lock", MUTEX_DEFAULT
,
522 #if defined(AFS_HPUX110_ENV)
524 rx_sleepLock
= alloc_spinlock(LAST_HELD_ORDER
- 10, "rx_sleepLock");
525 #endif /* AFS_HPUX110_ENV */
526 #endif /* RX_ENABLE_LOCKS && KERNEL */
529 rx_connDeadTime
= 12;
530 rx_tranquil
= 0; /* reset flag */
531 rxi_ResetStatistics();
532 htable
= osi_Alloc(rx_hashTableSize
* sizeof(struct rx_connection
*));
533 PIN(htable
, rx_hashTableSize
* sizeof(struct rx_connection
*)); /* XXXXX */
534 memset(htable
, 0, rx_hashTableSize
* sizeof(struct rx_connection
*));
535 ptable
= osi_Alloc(rx_hashTableSize
* sizeof(struct rx_peer
*));
536 PIN(ptable
, rx_hashTableSize
* sizeof(struct rx_peer
*)); /* XXXXX */
537 memset(ptable
, 0, rx_hashTableSize
* sizeof(struct rx_peer
*));
539 /* Malloc up a bunch of packets & buffers */
541 opr_queue_Init(&rx_freePacketQueue
);
542 rxi_NeedMorePackets
= FALSE
;
543 rx_nPackets
= 0; /* rx_nPackets is managed by rxi_MorePackets* */
544 opr_queue_Init(&rx_mallocedPacketQueue
);
546 /* enforce a minimum number of allocated packets */
547 if (rx_extraPackets
< rxi_nSendFrags
* rx_maxSendWindow
)
548 rx_extraPackets
= rxi_nSendFrags
* rx_maxSendWindow
;
550 /* allocate the initial free packet pool */
551 #ifdef RX_ENABLE_TSFPQ
552 rxi_MorePacketsTSFPQ(rx_extraPackets
+ RX_MAX_QUOTA
+ 2, RX_TS_FPQ_FLUSH_GLOBAL
, 0);
553 #else /* RX_ENABLE_TSFPQ */
554 rxi_MorePackets(rx_extraPackets
+ RX_MAX_QUOTA
+ 2); /* fudge */
555 #endif /* RX_ENABLE_TSFPQ */
562 #if defined(AFS_NT40_ENV) && !defined(AFS_PTHREAD_ENV)
563 tv
.tv_sec
= clock_now
.sec
;
564 tv
.tv_usec
= clock_now
.usec
;
565 srand((unsigned int)tv
.tv_usec
);
572 #if defined(KERNEL) && !defined(UKERNEL)
573 /* Really, this should never happen in a real kernel */
576 struct sockaddr_in addr
;
578 int addrlen
= sizeof(addr
);
580 socklen_t addrlen
= sizeof(addr
);
582 if (getsockname((intptr_t)rx_socket
, (struct sockaddr
*)&addr
, &addrlen
)) {
584 osi_Free(htable
, rx_hashTableSize
* sizeof(struct rx_connection
*));
587 rx_port
= addr
.sin_port
;
590 rx_stats
.minRtt
.sec
= 9999999;
591 if (RAND_bytes(&rx_epoch
, sizeof(rx_epoch
)) != 1)
593 rx_epoch
= (rx_epoch
& ~0x40000000) | 0x80000000;
594 if (RAND_bytes(&rx_nextCid
, sizeof(rx_nextCid
)) != 1)
596 rx_nextCid
&= RX_CIDMASK
;
597 MUTEX_ENTER(&rx_quota_mutex
);
598 rxi_dataQuota
+= rx_extraQuota
; /* + extra pkts caller asked to rsrv */
599 MUTEX_EXIT(&rx_quota_mutex
);
600 /* *Slightly* random start time for the cid. This is just to help
601 * out with the hashing function at the peer */
602 rx_nextCid
= ((tv
.tv_sec
^ tv
.tv_usec
) << RX_CIDSHIFT
);
603 rx_connHashTable
= (struct rx_connection
**)htable
;
604 rx_peerHashTable
= (struct rx_peer
**)ptable
;
606 rx_hardAckDelay
.sec
= 0;
607 rx_hardAckDelay
.usec
= 100000; /* 100 milliseconds */
609 rxevent_Init(20, rxi_ReScheduleEvents
);
611 /* Initialize various global queues */
612 opr_queue_Init(&rx_idleServerQueue
);
613 opr_queue_Init(&rx_incomingCallQueue
);
614 opr_queue_Init(&rx_freeCallQueue
);
616 #if defined(AFS_NT40_ENV) && !defined(KERNEL)
617 /* Initialize our list of usable IP addresses. */
621 /* Start listener process (exact function is dependent on the
622 * implementation environment--kernel or user space) */
626 rx_atomic_clear_bit(&rxinit_status
, 0);
633 return rx_InitHost(htonl(INADDR_ANY
), port
);
639 * The rxi_rto functions implement a TCP (RFC2988) style algorithm for
640 * maintaing the round trip timer.
645 * Start a new RTT timer for a given call and packet.
647 * There must be no resendEvent already listed for this call, otherwise this
648 * will leak events - intended for internal use within the RTO code only
651 * the RX call to start the timer for
652 * @param[in] lastPacket
653 * a flag indicating whether the last packet has been sent or not
655 * @pre call must be locked before calling this function
659 rxi_rto_startTimer(struct rx_call
*call
, int lastPacket
, int istack
)
661 struct clock now
, retryTime
;
666 clock_Add(&retryTime
, &call
->rto
);
668 /* If we're sending the last packet, and we're the client, then the server
669 * may wait for an additional 400ms before returning the ACK, wait for it
670 * rather than hitting a timeout */
671 if (lastPacket
&& call
->conn
->type
== RX_CLIENT_CONNECTION
)
672 clock_Addmsec(&retryTime
, 400);
674 CALL_HOLD(call
, RX_CALL_REFCOUNT_RESEND
);
675 call
->resendEvent
= rxevent_Post(&retryTime
, &now
, rxi_Resend
,
680 * Cancel an RTT timer for a given call.
684 * the RX call to cancel the timer for
686 * @pre call must be locked before calling this function
691 rxi_rto_cancel(struct rx_call
*call
)
693 if (call
->resendEvent
!= NULL
) {
694 rxevent_Cancel(&call
->resendEvent
);
695 CALL_RELE(call
, RX_CALL_REFCOUNT_RESEND
);
700 * Tell the RTO timer that we have sent a packet.
702 * If the timer isn't already running, then start it. If the timer is running,
706 * the RX call that the packet has been sent on
707 * @param[in] lastPacket
708 * A flag which is true if this is the last packet for the call
710 * @pre The call must be locked before calling this function
715 rxi_rto_packet_sent(struct rx_call
*call
, int lastPacket
, int istack
)
717 if (call
->resendEvent
)
720 rxi_rto_startTimer(call
, lastPacket
, istack
);
724 * Tell the RTO timer that we have received an new ACK message
726 * This function should be called whenever a call receives an ACK that
727 * acknowledges new packets. Whatever happens, we stop the current timer.
728 * If there are unacked packets in the queue which have been sent, then
729 * we restart the timer from now. Otherwise, we leave it stopped.
732 * the RX call that the ACK has been received on
736 rxi_rto_packet_acked(struct rx_call
*call
, int istack
)
738 struct opr_queue
*cursor
;
740 rxi_rto_cancel(call
);
742 if (opr_queue_IsEmpty(&call
->tq
))
745 for (opr_queue_Scan(&call
->tq
, cursor
)) {
746 struct rx_packet
*p
= opr_queue_Entry(cursor
, struct rx_packet
, entry
);
747 if (p
->header
.seq
> call
->tfirst
+ call
->twind
)
750 if (!(p
->flags
& RX_PKTFLAG_ACKED
) && p
->flags
& RX_PKTFLAG_SENT
) {
751 rxi_rto_startTimer(call
, p
->header
.flags
& RX_LAST_PACKET
, istack
);
759 * Set an initial round trip timeout for a peer connection
761 * @param[in] secs The timeout to set in seconds
765 rx_rto_setPeerTimeoutSecs(struct rx_peer
*peer
, int secs
) {
766 peer
->rtt
= secs
* 8000;
770 * Set a delayed ack event on the specified call for the given time
772 * @param[in] call - the call on which to set the event
773 * @param[in] offset - the delay from now after which the event fires
776 rxi_PostDelayedAckEvent(struct rx_call
*call
, struct clock
*offset
)
778 struct clock now
, when
;
782 clock_Add(&when
, offset
);
784 if (call
->delayedAckEvent
&& clock_Gt(&call
->delayedAckTime
, &when
)) {
785 /* The event we're cancelling already has a reference, so we don't
787 rxevent_Cancel(&call
->delayedAckEvent
);
788 call
->delayedAckEvent
= rxevent_Post(&when
, &now
, rxi_SendDelayedAck
,
791 call
->delayedAckTime
= when
;
792 } else if (!call
->delayedAckEvent
) {
793 CALL_HOLD(call
, RX_CALL_REFCOUNT_DELAY
);
794 call
->delayedAckEvent
= rxevent_Post(&when
, &now
,
797 call
->delayedAckTime
= when
;
802 rxi_CancelDelayedAckEvent(struct rx_call
*call
)
804 if (call
->delayedAckEvent
) {
805 rxevent_Cancel(&call
->delayedAckEvent
);
806 CALL_RELE(call
, RX_CALL_REFCOUNT_DELAY
);
810 /* called with unincremented nRequestsRunning to see if it is OK to start
811 * a new thread in this service. Could be "no" for two reasons: over the
812 * max quota, or would prevent others from reaching their min quota.
814 #ifdef RX_ENABLE_LOCKS
815 /* This verion of QuotaOK reserves quota if it's ok while the
816 * rx_serverPool_lock is held. Return quota using ReturnToServerPool().
819 QuotaOK(struct rx_service
*aservice
)
821 /* check if over max quota */
822 if (aservice
->nRequestsRunning
>= aservice
->maxProcs
) {
826 /* under min quota, we're OK */
827 /* otherwise, can use only if there are enough to allow everyone
828 * to go to their min quota after this guy starts.
831 MUTEX_ENTER(&rx_quota_mutex
);
832 if ((aservice
->nRequestsRunning
< aservice
->minProcs
)
833 || (rxi_availProcs
> rxi_minDeficit
)) {
834 aservice
->nRequestsRunning
++;
835 /* just started call in minProcs pool, need fewer to maintain
837 if (aservice
->nRequestsRunning
<= aservice
->minProcs
)
840 MUTEX_EXIT(&rx_quota_mutex
);
843 MUTEX_EXIT(&rx_quota_mutex
);
849 ReturnToServerPool(struct rx_service
*aservice
)
851 aservice
->nRequestsRunning
--;
852 MUTEX_ENTER(&rx_quota_mutex
);
853 if (aservice
->nRequestsRunning
< aservice
->minProcs
)
856 MUTEX_EXIT(&rx_quota_mutex
);
859 #else /* RX_ENABLE_LOCKS */
861 QuotaOK(struct rx_service
*aservice
)
864 /* under min quota, we're OK */
865 if (aservice
->nRequestsRunning
< aservice
->minProcs
)
868 /* check if over max quota */
869 if (aservice
->nRequestsRunning
>= aservice
->maxProcs
)
872 /* otherwise, can use only if there are enough to allow everyone
873 * to go to their min quota after this guy starts.
875 MUTEX_ENTER(&rx_quota_mutex
);
876 if (rxi_availProcs
> rxi_minDeficit
)
878 MUTEX_EXIT(&rx_quota_mutex
);
881 #endif /* RX_ENABLE_LOCKS */
884 /* Called by rx_StartServer to start up lwp's to service calls.
885 NExistingProcs gives the number of procs already existing, and which
886 therefore needn't be created. */
888 rxi_StartServerProcs(int nExistingProcs
)
890 struct rx_service
*service
;
895 /* For each service, reserve N processes, where N is the "minimum"
896 * number of processes that MUST be able to execute a request in parallel,
897 * at any time, for that process. Also compute the maximum difference
898 * between any service's maximum number of processes that can run
899 * (i.e. the maximum number that ever will be run, and a guarantee
900 * that this number will run if other services aren't running), and its
901 * minimum number. The result is the extra number of processes that
902 * we need in order to provide the latter guarantee */
903 for (i
= 0; i
< RX_MAX_SERVICES
; i
++) {
905 service
= rx_services
[i
];
906 if (service
== (struct rx_service
*)0)
908 nProcs
+= service
->minProcs
;
909 diff
= service
->maxProcs
- service
->minProcs
;
913 nProcs
+= maxdiff
; /* Extra processes needed to allow max number requested to run in any given service, under good conditions */
914 nProcs
-= nExistingProcs
; /* Subtract the number of procs that were previously created for use as server procs */
915 for (i
= 0; i
< nProcs
; i
++) {
916 rxi_StartServerProc(rx_ServerProc
, rx_stackSize
);
922 /* This routine is only required on Windows */
924 rx_StartClientThread(void)
926 #ifdef AFS_PTHREAD_ENV
928 pid
= pthread_self();
929 #endif /* AFS_PTHREAD_ENV */
931 #endif /* AFS_NT40_ENV */
933 /* This routine must be called if any services are exported. If the
934 * donateMe flag is set, the calling process is donated to the server
937 rx_StartServer(int donateMe
)
939 struct rx_service
*service
;
945 /* Start server processes, if necessary (exact function is dependent
946 * on the implementation environment--kernel or user space). DonateMe
947 * will be 1 if there is 1 pre-existing proc, i.e. this one. In this
948 * case, one less new proc will be created rx_StartServerProcs.
950 rxi_StartServerProcs(donateMe
);
952 /* count up the # of threads in minProcs, and add set the min deficit to
953 * be that value, too.
955 for (i
= 0; i
< RX_MAX_SERVICES
; i
++) {
956 service
= rx_services
[i
];
957 if (service
== (struct rx_service
*)0)
959 MUTEX_ENTER(&rx_quota_mutex
);
960 rxi_totalMin
+= service
->minProcs
;
961 /* below works even if a thread is running, since minDeficit would
962 * still have been decremented and later re-incremented.
964 rxi_minDeficit
+= service
->minProcs
;
965 MUTEX_EXIT(&rx_quota_mutex
);
968 /* Turn on reaping of idle server connections */
969 rxi_ReapConnections(NULL
, NULL
, NULL
, 0);
978 #ifdef AFS_PTHREAD_ENV
980 pid
= afs_pointer_to_int(pthread_self());
981 #else /* AFS_PTHREAD_ENV */
983 LWP_CurrentProcess(&pid
);
984 #endif /* AFS_PTHREAD_ENV */
986 sprintf(name
, "srv_%d", ++nProcs
);
988 (*registerProgram
) (pid
, name
);
990 #endif /* AFS_NT40_ENV */
991 rx_ServerProc(NULL
); /* Never returns */
993 #ifdef RX_ENABLE_TSFPQ
994 /* no use leaving packets around in this thread's local queue if
995 * it isn't getting donated to the server thread pool.
997 rxi_FlushLocalPacketsTSFPQ();
998 #endif /* RX_ENABLE_TSFPQ */
1002 /* Create a new client connection to the specified service, using the
1003 * specified security object to implement the security model for this
1005 struct rx_connection
*
1006 rx_NewConnection(afs_uint32 shost
, u_short sport
, u_short sservice
,
1007 struct rx_securityClass
*securityObject
,
1008 int serviceSecurityIndex
)
1011 struct rx_connection
*conn
;
1016 dpf(("rx_NewConnection(host %x, port %u, service %u, securityObject %p, "
1017 "serviceSecurityIndex %d)\n",
1018 ntohl(shost
), ntohs(sport
), sservice
, securityObject
,
1019 serviceSecurityIndex
));
1021 /* Vasilsi said: "NETPRI protects Cid and Alloc", but can this be true in
1022 * the case of kmem_alloc? */
1023 conn
= rxi_AllocConnection();
1024 #ifdef RX_ENABLE_LOCKS
1025 MUTEX_INIT(&conn
->conn_call_lock
, "conn call lock", MUTEX_DEFAULT
, 0);
1026 MUTEX_INIT(&conn
->conn_data_lock
, "conn data lock", MUTEX_DEFAULT
, 0);
1027 CV_INIT(&conn
->conn_call_cv
, "conn call cv", CV_DEFAULT
, 0);
1030 MUTEX_ENTER(&rx_connHashTable_lock
);
1031 conn
->type
= RX_CLIENT_CONNECTION
;
1032 conn
->epoch
= rx_epoch
;
1033 conn
->cid
= rx_nextCid
;
1035 conn
->peer
= rxi_FindPeer(shost
, sport
, 1);
1036 conn
->serviceId
= sservice
;
1037 conn
->securityObject
= securityObject
;
1038 conn
->securityData
= (void *) 0;
1039 conn
->securityIndex
= serviceSecurityIndex
;
1040 rx_SetConnDeadTime(conn
, rx_connDeadTime
);
1041 rx_SetConnSecondsUntilNatPing(conn
, 0);
1042 conn
->ackRate
= RX_FAST_ACK_RATE
;
1043 conn
->nSpecific
= 0;
1044 conn
->specific
= NULL
;
1045 conn
->challengeEvent
= NULL
;
1046 conn
->delayedAbortEvent
= NULL
;
1047 conn
->abortCount
= 0;
1049 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
1050 conn
->twind
[i
] = rx_initSendWindow
;
1051 conn
->rwind
[i
] = rx_initReceiveWindow
;
1052 conn
->lastBusy
[i
] = 0;
1055 RXS_NewConnection(securityObject
, conn
);
1057 CONN_HASH(shost
, sport
, conn
->cid
, conn
->epoch
, RX_CLIENT_CONNECTION
);
1059 conn
->refCount
++; /* no lock required since only this thread knows... */
1060 conn
->next
= rx_connHashTable
[hashindex
];
1061 rx_connHashTable
[hashindex
] = conn
;
1062 if (rx_stats_active
)
1063 rx_atomic_inc(&rx_stats
.nClientConns
);
1064 MUTEX_EXIT(&rx_connHashTable_lock
);
1070 * Ensure a connection's timeout values are valid.
1072 * @param[in] conn The connection to check
1074 * @post conn->secondUntilDead <= conn->idleDeadTime <= conn->hardDeadTime,
1075 * unless idleDeadTime and/or hardDeadTime are not set
1079 rxi_CheckConnTimeouts(struct rx_connection
*conn
)
1081 /* a connection's timeouts must have the relationship
1082 * deadTime <= idleDeadTime <= hardDeadTime. Otherwise, for example, a
1083 * total loss of network to a peer may cause an idle timeout instead of a
1084 * dead timeout, simply because the idle timeout gets hit first. Also set
1085 * a minimum deadTime of 6, just to ensure it doesn't get set too low. */
1086 /* this logic is slightly complicated by the fact that
1087 * idleDeadTime/hardDeadTime may not be set at all, but it's not too bad.
1089 conn
->secondsUntilDead
= MAX(conn
->secondsUntilDead
, 6);
1090 if (conn
->idleDeadTime
) {
1091 conn
->idleDeadTime
= MAX(conn
->idleDeadTime
, conn
->secondsUntilDead
);
1093 if (conn
->hardDeadTime
) {
1094 if (conn
->idleDeadTime
) {
1095 conn
->hardDeadTime
= MAX(conn
->idleDeadTime
, conn
->hardDeadTime
);
1097 conn
->hardDeadTime
= MAX(conn
->secondsUntilDead
, conn
->hardDeadTime
);
1103 rx_SetConnDeadTime(struct rx_connection
*conn
, int seconds
)
1105 /* The idea is to set the dead time to a value that allows several
1106 * keepalives to be dropped without timing out the connection. */
1107 conn
->secondsUntilDead
= seconds
;
1108 rxi_CheckConnTimeouts(conn
);
1109 conn
->secondsUntilPing
= conn
->secondsUntilDead
/ 6;
1113 rx_SetConnHardDeadTime(struct rx_connection
*conn
, int seconds
)
1115 conn
->hardDeadTime
= seconds
;
1116 rxi_CheckConnTimeouts(conn
);
1120 rx_SetConnIdleDeadTime(struct rx_connection
*conn
, int seconds
)
1122 conn
->idleDeadTime
= seconds
;
1123 rxi_CheckConnTimeouts(conn
);
1126 int rxi_lowPeerRefCount
= 0;
1127 int rxi_lowConnRefCount
= 0;
1130 * Cleanup a connection that was destroyed in rxi_DestroyConnectioNoLock.
1131 * NOTE: must not be called with rx_connHashTable_lock held.
1134 rxi_CleanupConnection(struct rx_connection
*conn
)
1136 /* Notify the service exporter, if requested, that this connection
1137 * is being destroyed */
1138 if (conn
->type
== RX_SERVER_CONNECTION
&& conn
->service
->destroyConnProc
)
1139 (*conn
->service
->destroyConnProc
) (conn
);
1141 /* Notify the security module that this connection is being destroyed */
1142 RXS_DestroyConnection(conn
->securityObject
, conn
);
1144 /* If this is the last connection using the rx_peer struct, set its
1145 * idle time to now. rxi_ReapConnections will reap it if it's still
1146 * idle (refCount == 0) after rx_idlePeerTime (60 seconds) have passed.
1148 MUTEX_ENTER(&rx_peerHashTable_lock
);
1149 if (conn
->peer
->refCount
< 2) {
1150 conn
->peer
->idleWhen
= clock_Sec();
1151 if (conn
->peer
->refCount
< 1) {
1152 conn
->peer
->refCount
= 1;
1153 if (rx_stats_active
) {
1154 MUTEX_ENTER(&rx_stats_mutex
);
1155 rxi_lowPeerRefCount
++;
1156 MUTEX_EXIT(&rx_stats_mutex
);
1160 conn
->peer
->refCount
--;
1161 MUTEX_EXIT(&rx_peerHashTable_lock
);
1163 if (rx_stats_active
)
1165 if (conn
->type
== RX_SERVER_CONNECTION
)
1166 rx_atomic_dec(&rx_stats
.nServerConns
);
1168 rx_atomic_dec(&rx_stats
.nClientConns
);
1171 if (conn
->specific
) {
1173 for (i
= 0; i
< conn
->nSpecific
; i
++) {
1174 if (conn
->specific
[i
] && rxi_keyCreate_destructor
[i
])
1175 (*rxi_keyCreate_destructor
[i
]) (conn
->specific
[i
]);
1176 conn
->specific
[i
] = NULL
;
1178 free(conn
->specific
);
1180 conn
->specific
= NULL
;
1181 conn
->nSpecific
= 0;
1182 #endif /* !KERNEL */
1184 MUTEX_DESTROY(&conn
->conn_call_lock
);
1185 MUTEX_DESTROY(&conn
->conn_data_lock
);
1186 CV_DESTROY(&conn
->conn_call_cv
);
1188 rxi_FreeConnection(conn
);
1191 /* Destroy the specified connection */
1193 rxi_DestroyConnection(struct rx_connection
*conn
)
1195 MUTEX_ENTER(&rx_connHashTable_lock
);
1196 rxi_DestroyConnectionNoLock(conn
);
1197 /* conn should be at the head of the cleanup list */
1198 if (conn
== rx_connCleanup_list
) {
1199 rx_connCleanup_list
= rx_connCleanup_list
->next
;
1200 MUTEX_EXIT(&rx_connHashTable_lock
);
1201 rxi_CleanupConnection(conn
);
1203 #ifdef RX_ENABLE_LOCKS
1205 MUTEX_EXIT(&rx_connHashTable_lock
);
1207 #endif /* RX_ENABLE_LOCKS */
1211 rxi_DestroyConnectionNoLock(struct rx_connection
*conn
)
1213 struct rx_connection
**conn_ptr
;
1215 struct rx_packet
*packet
;
1222 MUTEX_ENTER(&conn
->conn_data_lock
);
1223 MUTEX_ENTER(&rx_refcnt_mutex
);
1224 if (conn
->refCount
> 0)
1227 if (rx_stats_active
) {
1228 MUTEX_ENTER(&rx_stats_mutex
);
1229 rxi_lowConnRefCount
++;
1230 MUTEX_EXIT(&rx_stats_mutex
);
1234 if ((conn
->refCount
> 0) || (conn
->flags
& RX_CONN_BUSY
)) {
1235 /* Busy; wait till the last guy before proceeding */
1236 MUTEX_EXIT(&rx_refcnt_mutex
);
1237 MUTEX_EXIT(&conn
->conn_data_lock
);
1242 /* If the client previously called rx_NewCall, but it is still
1243 * waiting, treat this as a running call, and wait to destroy the
1244 * connection later when the call completes. */
1245 if ((conn
->type
== RX_CLIENT_CONNECTION
)
1246 && (conn
->flags
& (RX_CONN_MAKECALL_WAITING
|RX_CONN_MAKECALL_ACTIVE
))) {
1247 conn
->flags
|= RX_CONN_DESTROY_ME
;
1248 MUTEX_EXIT(&conn
->conn_data_lock
);
1252 MUTEX_EXIT(&rx_refcnt_mutex
);
1253 MUTEX_EXIT(&conn
->conn_data_lock
);
1255 /* Check for extant references to this connection */
1256 MUTEX_ENTER(&conn
->conn_call_lock
);
1257 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
1258 struct rx_call
*call
= conn
->call
[i
];
1261 if (conn
->type
== RX_CLIENT_CONNECTION
) {
1262 MUTEX_ENTER(&call
->lock
);
1263 if (call
->delayedAckEvent
) {
1264 /* Push the final acknowledgment out now--there
1265 * won't be a subsequent call to acknowledge the
1266 * last reply packets */
1267 rxi_CancelDelayedAckEvent(call
);
1268 if (call
->state
== RX_STATE_PRECALL
1269 || call
->state
== RX_STATE_ACTIVE
) {
1270 rxi_SendAck(call
, 0, 0, RX_ACK_DELAY
, 0);
1275 MUTEX_EXIT(&call
->lock
);
1279 MUTEX_EXIT(&conn
->conn_call_lock
);
1281 #ifdef RX_ENABLE_LOCKS
1283 if (MUTEX_TRYENTER(&conn
->conn_data_lock
)) {
1284 MUTEX_EXIT(&conn
->conn_data_lock
);
1286 /* Someone is accessing a packet right now. */
1290 #endif /* RX_ENABLE_LOCKS */
1293 /* Don't destroy the connection if there are any call
1294 * structures still in use */
1295 MUTEX_ENTER(&conn
->conn_data_lock
);
1296 conn
->flags
|= RX_CONN_DESTROY_ME
;
1297 MUTEX_EXIT(&conn
->conn_data_lock
);
1302 if (conn
->natKeepAliveEvent
) {
1303 rxi_NatKeepAliveOff(conn
);
1306 if (conn
->delayedAbortEvent
) {
1307 rxevent_Cancel(&conn
->delayedAbortEvent
);
1308 packet
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
);
1310 MUTEX_ENTER(&conn
->conn_data_lock
);
1311 rxi_SendConnectionAbort(conn
, packet
, 0, 1);
1312 MUTEX_EXIT(&conn
->conn_data_lock
);
1313 rxi_FreePacket(packet
);
1317 /* Remove from connection hash table before proceeding */
1319 &rx_connHashTable
[CONN_HASH
1320 (peer
->host
, peer
->port
, conn
->cid
, conn
->epoch
,
1322 for (; *conn_ptr
; conn_ptr
= &(*conn_ptr
)->next
) {
1323 if (*conn_ptr
== conn
) {
1324 *conn_ptr
= conn
->next
;
1328 /* if the conn that we are destroying was the last connection, then we
1329 * clear rxLastConn as well */
1330 if (rxLastConn
== conn
)
1333 /* Make sure the connection is completely reset before deleting it. */
1334 /* get rid of pending events that could zap us later */
1335 rxevent_Cancel(&conn
->challengeEvent
);
1336 rxevent_Cancel(&conn
->checkReachEvent
);
1337 rxevent_Cancel(&conn
->natKeepAliveEvent
);
1339 /* Add the connection to the list of destroyed connections that
1340 * need to be cleaned up. This is necessary to avoid deadlocks
1341 * in the routines we call to inform others that this connection is
1342 * being destroyed. */
1343 conn
->next
= rx_connCleanup_list
;
1344 rx_connCleanup_list
= conn
;
1347 /* Externally available version */
1349 rx_DestroyConnection(struct rx_connection
*conn
)
1354 rxi_DestroyConnection(conn
);
1359 rx_GetConnection(struct rx_connection
*conn
)
1364 MUTEX_ENTER(&rx_refcnt_mutex
);
1366 MUTEX_EXIT(&rx_refcnt_mutex
);
1370 #ifdef RX_ENABLE_LOCKS
1371 /* Wait for the transmit queue to no longer be busy.
1372 * requires the call->lock to be held */
1374 rxi_WaitforTQBusy(struct rx_call
*call
) {
1375 while (!call
->error
&& (call
->flags
& RX_CALL_TQ_BUSY
)) {
1376 call
->flags
|= RX_CALL_TQ_WAIT
;
1378 MUTEX_ASSERT(&call
->lock
);
1379 CV_WAIT(&call
->cv_tq
, &call
->lock
);
1381 if (call
->tqWaiters
== 0) {
1382 call
->flags
&= ~RX_CALL_TQ_WAIT
;
1389 rxi_WakeUpTransmitQueue(struct rx_call
*call
)
1391 if (call
->tqWaiters
|| (call
->flags
& RX_CALL_TQ_WAIT
)) {
1392 dpf(("call %"AFS_PTR_FMT
" has %d waiters and flags %d\n",
1393 call
, call
->tqWaiters
, call
->flags
));
1394 #ifdef RX_ENABLE_LOCKS
1395 MUTEX_ASSERT(&call
->lock
);
1396 CV_BROADCAST(&call
->cv_tq
);
1397 #else /* RX_ENABLE_LOCKS */
1398 osi_rxWakeup(&call
->tq
);
1399 #endif /* RX_ENABLE_LOCKS */
1403 /* Start a new rx remote procedure call, on the specified connection.
1404 * If wait is set to 1, wait for a free call channel; otherwise return
1405 * 0. Maxtime gives the maximum number of seconds this call may take,
1406 * after rx_NewCall returns. After this time interval, a call to any
1407 * of rx_SendData, rx_ReadData, etc. will fail with RX_CALL_TIMEOUT.
1408 * For fine grain locking, we hold the conn_call_lock in order to
1409 * to ensure that we don't get signalle after we found a call in an active
1410 * state and before we go to sleep.
1413 rx_NewCall(struct rx_connection
*conn
)
1415 int i
, wait
, ignoreBusy
= 1;
1416 struct rx_call
*call
;
1417 struct clock queueTime
;
1418 afs_uint32 leastBusy
= 0;
1422 dpf(("rx_NewCall(conn %"AFS_PTR_FMT
")\n", conn
));
1425 clock_GetTime(&queueTime
);
1427 * Check if there are others waiting for a new call.
1428 * If so, let them go first to avoid starving them.
1429 * This is a fairly simple scheme, and might not be
1430 * a complete solution for large numbers of waiters.
1432 * makeCallWaiters keeps track of the number of
1433 * threads waiting to make calls and the
1434 * RX_CONN_MAKECALL_WAITING flag bit is used to
1435 * indicate that there are indeed calls waiting.
1436 * The flag is set when the waiter is incremented.
1437 * It is only cleared when makeCallWaiters is 0.
1438 * This prevents us from accidently destroying the
1439 * connection while it is potentially about to be used.
1441 MUTEX_ENTER(&conn
->conn_call_lock
);
1442 MUTEX_ENTER(&conn
->conn_data_lock
);
1443 while (conn
->flags
& RX_CONN_MAKECALL_ACTIVE
) {
1444 conn
->flags
|= RX_CONN_MAKECALL_WAITING
;
1445 conn
->makeCallWaiters
++;
1446 MUTEX_EXIT(&conn
->conn_data_lock
);
1448 #ifdef RX_ENABLE_LOCKS
1449 CV_WAIT(&conn
->conn_call_cv
, &conn
->conn_call_lock
);
1453 MUTEX_ENTER(&conn
->conn_data_lock
);
1454 conn
->makeCallWaiters
--;
1455 if (conn
->makeCallWaiters
== 0)
1456 conn
->flags
&= ~RX_CONN_MAKECALL_WAITING
;
1459 /* We are now the active thread in rx_NewCall */
1460 conn
->flags
|= RX_CONN_MAKECALL_ACTIVE
;
1461 MUTEX_EXIT(&conn
->conn_data_lock
);
1466 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
1467 call
= conn
->call
[i
];
1469 if (!ignoreBusy
&& conn
->lastBusy
[i
] != leastBusy
) {
1470 /* we're not ignoring busy call slots; only look at the
1471 * call slot that is the "least" busy */
1475 if (call
->state
== RX_STATE_DALLY
) {
1476 MUTEX_ENTER(&call
->lock
);
1477 if (call
->state
== RX_STATE_DALLY
) {
1478 if (ignoreBusy
&& conn
->lastBusy
[i
]) {
1479 /* if we're ignoring busy call slots, skip any ones that
1480 * have lastBusy set */
1481 if (leastBusy
== 0 || conn
->lastBusy
[i
] < leastBusy
) {
1482 leastBusy
= conn
->lastBusy
[i
];
1484 MUTEX_EXIT(&call
->lock
);
1489 * We are setting the state to RX_STATE_RESET to
1490 * ensure that no one else will attempt to use this
1491 * call once we drop the conn->conn_call_lock and
1492 * call->lock. We must drop the conn->conn_call_lock
1493 * before calling rxi_ResetCall because the process
1494 * of clearing the transmit queue can block for an
1495 * extended period of time. If we block while holding
1496 * the conn->conn_call_lock, then all rx_EndCall
1497 * processing will block as well. This has a detrimental
1498 * effect on overall system performance.
1500 call
->state
= RX_STATE_RESET
;
1501 (*call
->callNumber
)++;
1502 MUTEX_EXIT(&conn
->conn_call_lock
);
1503 CALL_HOLD(call
, RX_CALL_REFCOUNT_BEGIN
);
1504 rxi_ResetCall(call
, 0);
1505 if (MUTEX_TRYENTER(&conn
->conn_call_lock
))
1509 * If we failed to be able to safely obtain the
1510 * conn->conn_call_lock we will have to drop the
1511 * call->lock to avoid a deadlock. When the call->lock
1512 * is released the state of the call can change. If it
1513 * is no longer RX_STATE_RESET then some other thread is
1516 MUTEX_EXIT(&call
->lock
);
1517 MUTEX_ENTER(&conn
->conn_call_lock
);
1518 MUTEX_ENTER(&call
->lock
);
1520 if (call
->state
== RX_STATE_RESET
)
1524 * If we get here it means that after dropping
1525 * the conn->conn_call_lock and call->lock that
1526 * the call is no longer ours. If we can't find
1527 * a free call in the remaining slots we should
1528 * not go immediately to RX_CONN_MAKECALL_WAITING
1529 * because by dropping the conn->conn_call_lock
1530 * we have given up synchronization with rx_EndCall.
1531 * Instead, cycle through one more time to see if
1532 * we can find a call that can call our own.
1534 CALL_RELE(call
, RX_CALL_REFCOUNT_BEGIN
);
1537 MUTEX_EXIT(&call
->lock
);
1540 if (ignoreBusy
&& conn
->lastBusy
[i
]) {
1541 /* if we're ignoring busy call slots, skip any ones that
1542 * have lastBusy set */
1543 if (leastBusy
== 0 || conn
->lastBusy
[i
] < leastBusy
) {
1544 leastBusy
= conn
->lastBusy
[i
];
1549 /* rxi_NewCall returns with mutex locked */
1550 call
= rxi_NewCall(conn
, i
);
1551 CALL_HOLD(call
, RX_CALL_REFCOUNT_BEGIN
);
1555 if (i
< RX_MAXCALLS
) {
1556 conn
->lastBusy
[i
] = 0;
1561 if (leastBusy
&& ignoreBusy
) {
1562 /* we didn't find a useable call slot, but we did see at least one
1563 * 'busy' slot; look again and only use a slot with the 'least
1569 MUTEX_ENTER(&conn
->conn_data_lock
);
1570 conn
->flags
|= RX_CONN_MAKECALL_WAITING
;
1571 conn
->makeCallWaiters
++;
1572 MUTEX_EXIT(&conn
->conn_data_lock
);
1574 #ifdef RX_ENABLE_LOCKS
1575 CV_WAIT(&conn
->conn_call_cv
, &conn
->conn_call_lock
);
1579 MUTEX_ENTER(&conn
->conn_data_lock
);
1580 conn
->makeCallWaiters
--;
1581 if (conn
->makeCallWaiters
== 0)
1582 conn
->flags
&= ~RX_CONN_MAKECALL_WAITING
;
1583 MUTEX_EXIT(&conn
->conn_data_lock
);
1585 /* Client is initially in send mode */
1586 call
->state
= RX_STATE_ACTIVE
;
1587 call
->error
= conn
->error
;
1589 call
->app
.mode
= RX_MODE_ERROR
;
1591 call
->app
.mode
= RX_MODE_SENDING
;
1593 #ifdef AFS_RXERRQ_ENV
1594 /* remember how many network errors the peer has when we started, so if
1595 * more errors are encountered after the call starts, we know the other endpoint won't be
1596 * responding to us */
1597 call
->neterr_gen
= rx_atomic_read(&conn
->peer
->neterrs
);
1600 /* remember start time for call in case we have hard dead time limit */
1601 call
->queueTime
= queueTime
;
1602 clock_GetTime(&call
->startTime
);
1603 call
->app
.bytesSent
= 0;
1604 call
->app
.bytesRcvd
= 0;
1606 /* Turn on busy protocol. */
1607 rxi_KeepAliveOn(call
);
1609 /* Attempt MTU discovery */
1610 rxi_GrowMTUOn(call
);
1613 * We are no longer the active thread in rx_NewCall
1615 MUTEX_ENTER(&conn
->conn_data_lock
);
1616 conn
->flags
&= ~RX_CONN_MAKECALL_ACTIVE
;
1617 MUTEX_EXIT(&conn
->conn_data_lock
);
1620 * Wake up anyone else who might be giving us a chance to
1621 * run (see code above that avoids resource starvation).
1623 #ifdef RX_ENABLE_LOCKS
1624 if (call
->flags
& (RX_CALL_TQ_BUSY
| RX_CALL_TQ_CLEARME
)) {
1625 osi_Panic("rx_NewCall call about to be used without an empty tq");
1628 CV_BROADCAST(&conn
->conn_call_cv
);
1632 MUTEX_EXIT(&conn
->conn_call_lock
);
1633 MUTEX_EXIT(&call
->lock
);
1636 dpf(("rx_NewCall(call %"AFS_PTR_FMT
")\n", call
));
1641 rxi_HasActiveCalls(struct rx_connection
*aconn
)
1644 struct rx_call
*tcall
;
1648 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
1649 if ((tcall
= aconn
->call
[i
])) {
1650 if ((tcall
->state
== RX_STATE_ACTIVE
)
1651 || (tcall
->state
== RX_STATE_PRECALL
)) {
1662 rxi_GetCallNumberVector(struct rx_connection
*aconn
,
1663 afs_int32
* aint32s
)
1666 struct rx_call
*tcall
;
1670 MUTEX_ENTER(&aconn
->conn_call_lock
);
1671 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
1672 if ((tcall
= aconn
->call
[i
]) && (tcall
->state
== RX_STATE_DALLY
))
1673 aint32s
[i
] = aconn
->callNumber
[i
] + 1;
1675 aint32s
[i
] = aconn
->callNumber
[i
];
1677 MUTEX_EXIT(&aconn
->conn_call_lock
);
1683 rxi_SetCallNumberVector(struct rx_connection
*aconn
,
1684 afs_int32
* aint32s
)
1687 struct rx_call
*tcall
;
1691 MUTEX_ENTER(&aconn
->conn_call_lock
);
1692 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
1693 if ((tcall
= aconn
->call
[i
]) && (tcall
->state
== RX_STATE_DALLY
))
1694 aconn
->callNumber
[i
] = aint32s
[i
] - 1;
1696 aconn
->callNumber
[i
] = aint32s
[i
];
1698 MUTEX_EXIT(&aconn
->conn_call_lock
);
1703 /* Advertise a new service. A service is named locally by a UDP port
1704 * number plus a 16-bit service id. Returns (struct rx_service *) 0
1707 char *serviceName; Name for identification purposes (e.g. the
1708 service name might be used for probing for
1711 rx_NewServiceHost(afs_uint32 host
, u_short port
, u_short serviceId
,
1712 char *serviceName
, struct rx_securityClass
**securityObjects
,
1713 int nSecurityObjects
,
1714 afs_int32(*serviceProc
) (struct rx_call
* acall
))
1716 osi_socket socket
= OSI_NULLSOCKET
;
1717 struct rx_service
*tservice
;
1723 if (serviceId
== 0) {
1725 "rx_NewService: service id for service %s is not non-zero.\n",
1732 "rx_NewService: A non-zero port must be specified on this call if a non-zero port was not provided at Rx initialization (service %s).\n",
1740 tservice
= rxi_AllocService();
1743 MUTEX_INIT(&tservice
->svc_data_lock
, "svc data lock", MUTEX_DEFAULT
, 0);
1745 for (i
= 0; i
< RX_MAX_SERVICES
; i
++) {
1746 struct rx_service
*service
= rx_services
[i
];
1748 if (port
== service
->servicePort
&& host
== service
->serviceHost
) {
1749 if (service
->serviceId
== serviceId
) {
1750 /* The identical service has already been
1751 * installed; if the caller was intending to
1752 * change the security classes used by this
1753 * service, he/she loses. */
1755 "rx_NewService: tried to install service %s with service id %d, which is already in use for service %s\n",
1756 serviceName
, serviceId
, service
->serviceName
);
1758 rxi_FreeService(tservice
);
1761 /* Different service, same port: re-use the socket
1762 * which is bound to the same port */
1763 socket
= service
->socket
;
1766 if (socket
== OSI_NULLSOCKET
) {
1767 /* If we don't already have a socket (from another
1768 * service on same port) get a new one */
1769 socket
= rxi_GetHostUDPSocket(host
, port
);
1770 if (socket
== OSI_NULLSOCKET
) {
1772 rxi_FreeService(tservice
);
1777 service
->socket
= socket
;
1778 service
->serviceHost
= host
;
1779 service
->servicePort
= port
;
1780 service
->serviceId
= serviceId
;
1781 service
->serviceName
= serviceName
;
1782 service
->nSecurityObjects
= nSecurityObjects
;
1783 service
->securityObjects
= securityObjects
;
1784 service
->minProcs
= 0;
1785 service
->maxProcs
= 1;
1786 service
->idleDeadTime
= 60;
1787 service
->connDeadTime
= rx_connDeadTime
;
1788 service
->executeRequestProc
= serviceProc
;
1789 service
->checkReach
= 0;
1790 service
->nSpecific
= 0;
1791 service
->specific
= NULL
;
1792 rx_services
[i
] = service
; /* not visible until now */
1798 rxi_FreeService(tservice
);
1799 (osi_Msg
"rx_NewService: cannot support > %d services\n",
1804 /* Set configuration options for all of a service's security objects */
1807 rx_SetSecurityConfiguration(struct rx_service
*service
,
1808 rx_securityConfigVariables type
,
1812 for (i
= 0; i
<service
->nSecurityObjects
; i
++) {
1813 if (service
->securityObjects
[i
]) {
1814 RXS_SetConfiguration(service
->securityObjects
[i
], NULL
, type
,
1822 rx_NewService(u_short port
, u_short serviceId
, char *serviceName
,
1823 struct rx_securityClass
**securityObjects
, int nSecurityObjects
,
1824 afs_int32(*serviceProc
) (struct rx_call
* acall
))
1826 return rx_NewServiceHost(htonl(INADDR_ANY
), port
, serviceId
, serviceName
, securityObjects
, nSecurityObjects
, serviceProc
);
1829 /* Generic request processing loop. This routine should be called
1830 * by the implementation dependent rx_ServerProc. If socketp is
1831 * non-null, it will be set to the file descriptor that this thread
1832 * is now listening on. If socketp is null, this routine will never
1835 rxi_ServerProc(int threadID
, struct rx_call
*newcall
, osi_socket
* socketp
)
1837 struct rx_call
*call
;
1839 struct rx_service
*tservice
= NULL
;
1846 call
= rx_GetCall(threadID
, tservice
, socketp
);
1847 if (socketp
&& *socketp
!= OSI_NULLSOCKET
) {
1848 /* We are now a listener thread */
1854 if (afs_termState
== AFSOP_STOP_RXCALLBACK
) {
1855 #ifdef RX_ENABLE_LOCKS
1857 #endif /* RX_ENABLE_LOCKS */
1858 afs_termState
= AFSOP_STOP_AFS
;
1859 afs_osi_Wakeup(&afs_termState
);
1860 #ifdef RX_ENABLE_LOCKS
1862 #endif /* RX_ENABLE_LOCKS */
1867 /* if server is restarting( typically smooth shutdown) then do not
1868 * allow any new calls.
1871 if (rx_tranquil
&& (call
!= NULL
)) {
1875 MUTEX_ENTER(&call
->lock
);
1877 rxi_CallError(call
, RX_RESTARTING
);
1878 rxi_SendCallAbort(call
, (struct rx_packet
*)0, 0, 0);
1880 MUTEX_EXIT(&call
->lock
);
1885 tservice
= call
->conn
->service
;
1887 if (tservice
->beforeProc
)
1888 (*tservice
->beforeProc
) (call
);
1890 code
= tservice
->executeRequestProc(call
);
1892 if (tservice
->afterProc
)
1893 (*tservice
->afterProc
) (call
, code
);
1895 rx_EndCall(call
, code
);
1897 if (tservice
->postProc
)
1898 (*tservice
->postProc
) (code
);
1900 if (rx_stats_active
) {
1901 MUTEX_ENTER(&rx_stats_mutex
);
1903 MUTEX_EXIT(&rx_stats_mutex
);
1910 rx_WakeupServerProcs(void)
1912 struct rx_serverQueueEntry
*np
, *tqp
;
1913 struct opr_queue
*cursor
;
1917 MUTEX_ENTER(&rx_serverPool_lock
);
1919 #ifdef RX_ENABLE_LOCKS
1920 if (rx_waitForPacket
)
1921 CV_BROADCAST(&rx_waitForPacket
->cv
);
1922 #else /* RX_ENABLE_LOCKS */
1923 if (rx_waitForPacket
)
1924 osi_rxWakeup(rx_waitForPacket
);
1925 #endif /* RX_ENABLE_LOCKS */
1926 MUTEX_ENTER(&freeSQEList_lock
);
1927 for (np
= rx_FreeSQEList
; np
; np
= tqp
) {
1928 tqp
= *(struct rx_serverQueueEntry
**)np
;
1929 #ifdef RX_ENABLE_LOCKS
1930 CV_BROADCAST(&np
->cv
);
1931 #else /* RX_ENABLE_LOCKS */
1933 #endif /* RX_ENABLE_LOCKS */
1935 MUTEX_EXIT(&freeSQEList_lock
);
1936 for (opr_queue_Scan(&rx_idleServerQueue
, cursor
)) {
1937 np
= opr_queue_Entry(cursor
, struct rx_serverQueueEntry
, entry
);
1938 #ifdef RX_ENABLE_LOCKS
1939 CV_BROADCAST(&np
->cv
);
1940 #else /* RX_ENABLE_LOCKS */
1942 #endif /* RX_ENABLE_LOCKS */
1944 MUTEX_EXIT(&rx_serverPool_lock
);
1949 * One thing that seems to happen is that all the server threads get
1950 * tied up on some empty or slow call, and then a whole bunch of calls
1951 * arrive at once, using up the packet pool, so now there are more
1952 * empty calls. The most critical resources here are server threads
1953 * and the free packet pool. The "doreclaim" code seems to help in
1954 * general. I think that eventually we arrive in this state: there
1955 * are lots of pending calls which do have all their packets present,
1956 * so they won't be reclaimed, are multi-packet calls, so they won't
1957 * be scheduled until later, and thus are tying up most of the free
1958 * packet pool for a very long time.
1960 * 1. schedule multi-packet calls if all the packets are present.
1961 * Probably CPU-bound operation, useful to return packets to pool.
1962 * Do what if there is a full window, but the last packet isn't here?
1963 * 3. preserve one thread which *only* runs "best" calls, otherwise
1964 * it sleeps and waits for that type of call.
1965 * 4. Don't necessarily reserve a whole window for each thread. In fact,
1966 * the current dataquota business is badly broken. The quota isn't adjusted
1967 * to reflect how many packets are presently queued for a running call.
1968 * So, when we schedule a queued call with a full window of packets queued
1969 * up for it, that *should* free up a window full of packets for other 2d-class
1970 * calls to be able to use from the packet pool. But it doesn't.
1972 * NB. Most of the time, this code doesn't run -- since idle server threads
1973 * sit on the idle server queue and are assigned by "...ReceivePacket" as soon
1974 * as a new call arrives.
1976 /* Sleep until a call arrives. Returns a pointer to the call, ready
1977 * for an rx_Read. */
1978 #ifdef RX_ENABLE_LOCKS
1980 rx_GetCall(int tno
, struct rx_service
*cur_service
, osi_socket
* socketp
)
1982 struct rx_serverQueueEntry
*sq
;
1983 struct rx_call
*call
= (struct rx_call
*)0;
1984 struct rx_service
*service
= NULL
;
1986 MUTEX_ENTER(&freeSQEList_lock
);
1988 if ((sq
= rx_FreeSQEList
)) {
1989 rx_FreeSQEList
= *(struct rx_serverQueueEntry
**)sq
;
1990 MUTEX_EXIT(&freeSQEList_lock
);
1991 } else { /* otherwise allocate a new one and return that */
1992 MUTEX_EXIT(&freeSQEList_lock
);
1993 sq
= rxi_Alloc(sizeof(struct rx_serverQueueEntry
));
1994 MUTEX_INIT(&sq
->lock
, "server Queue lock", MUTEX_DEFAULT
, 0);
1995 CV_INIT(&sq
->cv
, "server Queue lock", CV_DEFAULT
, 0);
1998 MUTEX_ENTER(&rx_serverPool_lock
);
1999 if (cur_service
!= NULL
) {
2000 ReturnToServerPool(cur_service
);
2003 if (!opr_queue_IsEmpty(&rx_incomingCallQueue
)) {
2004 struct rx_call
*tcall
, *choice2
= NULL
;
2005 struct opr_queue
*cursor
;
2007 /* Scan for eligible incoming calls. A call is not eligible
2008 * if the maximum number of calls for its service type are
2009 * already executing */
2010 /* One thread will process calls FCFS (to prevent starvation),
2011 * while the other threads may run ahead looking for calls which
2012 * have all their input data available immediately. This helps
2013 * keep threads from blocking, waiting for data from the client. */
2014 for (opr_queue_Scan(&rx_incomingCallQueue
, cursor
)) {
2015 tcall
= opr_queue_Entry(cursor
, struct rx_call
, entry
);
2017 service
= tcall
->conn
->service
;
2018 if (!QuotaOK(service
)) {
2021 MUTEX_ENTER(&rx_pthread_mutex
);
2022 if (tno
== rxi_fcfs_thread_num
2023 || opr_queue_IsEnd(&rx_incomingCallQueue
, cursor
)) {
2024 MUTEX_EXIT(&rx_pthread_mutex
);
2025 /* If we're the fcfs thread , then we'll just use
2026 * this call. If we haven't been able to find an optimal
2027 * choice, and we're at the end of the list, then use a
2028 * 2d choice if one has been identified. Otherwise... */
2029 call
= (choice2
? choice2
: tcall
);
2030 service
= call
->conn
->service
;
2032 MUTEX_EXIT(&rx_pthread_mutex
);
2033 if (!opr_queue_IsEmpty(&tcall
->rq
)) {
2034 struct rx_packet
*rp
;
2035 rp
= opr_queue_First(&tcall
->rq
, struct rx_packet
,
2037 if (rp
->header
.seq
== 1) {
2039 || (rp
->header
.flags
& RX_LAST_PACKET
)) {
2041 } else if (rxi_2dchoice
&& !choice2
2042 && !(tcall
->flags
& RX_CALL_CLEARED
)
2043 && (tcall
->rprev
> rxi_HardAckRate
)) {
2053 ReturnToServerPool(service
);
2059 opr_queue_Remove(&call
->entry
);
2060 MUTEX_EXIT(&rx_serverPool_lock
);
2061 MUTEX_ENTER(&call
->lock
);
2063 if (call
->flags
& RX_CALL_WAIT_PROC
) {
2064 call
->flags
&= ~RX_CALL_WAIT_PROC
;
2065 rx_atomic_dec(&rx_nWaiting
);
2068 if (call
->state
!= RX_STATE_PRECALL
|| call
->error
) {
2069 MUTEX_EXIT(&call
->lock
);
2070 MUTEX_ENTER(&rx_serverPool_lock
);
2071 ReturnToServerPool(service
);
2076 if (opr_queue_IsEmpty(&call
->rq
)
2077 || opr_queue_First(&call
->rq
, struct rx_packet
, entry
)->header
.seq
!= 1)
2078 rxi_SendAck(call
, 0, 0, RX_ACK_DELAY
, 0);
2080 CLEAR_CALL_QUEUE_LOCK(call
);
2083 /* If there are no eligible incoming calls, add this process
2084 * to the idle server queue, to wait for one */
2088 *socketp
= OSI_NULLSOCKET
;
2090 sq
->socketp
= socketp
;
2091 opr_queue_Append(&rx_idleServerQueue
, &sq
->entry
);
2092 #ifndef AFS_AIX41_ENV
2093 rx_waitForPacket
= sq
;
2094 #endif /* AFS_AIX41_ENV */
2096 CV_WAIT(&sq
->cv
, &rx_serverPool_lock
);
2098 if (afs_termState
== AFSOP_STOP_RXCALLBACK
) {
2099 MUTEX_EXIT(&rx_serverPool_lock
);
2100 return (struct rx_call
*)0;
2103 } while (!(call
= sq
->newcall
)
2104 && !(socketp
&& *socketp
!= OSI_NULLSOCKET
));
2105 MUTEX_EXIT(&rx_serverPool_lock
);
2107 MUTEX_ENTER(&call
->lock
);
2113 MUTEX_ENTER(&freeSQEList_lock
);
2114 *(struct rx_serverQueueEntry
**)sq
= rx_FreeSQEList
;
2115 rx_FreeSQEList
= sq
;
2116 MUTEX_EXIT(&freeSQEList_lock
);
2119 clock_GetTime(&call
->startTime
);
2120 call
->state
= RX_STATE_ACTIVE
;
2121 call
->app
.mode
= RX_MODE_RECEIVING
;
2122 #ifdef RX_KERNEL_TRACE
2123 if (ICL_SETACTIVE(afs_iclSetp
)) {
2124 int glockOwner
= ISAFS_GLOCK();
2127 afs_Trace3(afs_iclSetp
, CM_TRACE_WASHERE
, ICL_TYPE_STRING
,
2128 __FILE__
, ICL_TYPE_INT32
, __LINE__
, ICL_TYPE_POINTER
,
2135 rxi_calltrace(RX_CALL_START
, call
);
2136 dpf(("rx_GetCall(port=%d, service=%d) ==> call %"AFS_PTR_FMT
"\n",
2137 call
->conn
->service
->servicePort
, call
->conn
->service
->serviceId
,
2140 MUTEX_EXIT(&call
->lock
);
2141 CALL_HOLD(call
, RX_CALL_REFCOUNT_BEGIN
);
2143 dpf(("rx_GetCall(socketp=%p, *socketp=0x%x)\n", socketp
, *socketp
));
2148 #else /* RX_ENABLE_LOCKS */
2150 rx_GetCall(int tno
, struct rx_service
*cur_service
, osi_socket
* socketp
)
2152 struct rx_serverQueueEntry
*sq
;
2153 struct rx_call
*call
= (struct rx_call
*)0, *choice2
;
2154 struct rx_service
*service
= NULL
;
2158 MUTEX_ENTER(&freeSQEList_lock
);
2160 if ((sq
= rx_FreeSQEList
)) {
2161 rx_FreeSQEList
= *(struct rx_serverQueueEntry
**)sq
;
2162 MUTEX_EXIT(&freeSQEList_lock
);
2163 } else { /* otherwise allocate a new one and return that */
2164 MUTEX_EXIT(&freeSQEList_lock
);
2165 sq
= rxi_Alloc(sizeof(struct rx_serverQueueEntry
));
2166 MUTEX_INIT(&sq
->lock
, "server Queue lock", MUTEX_DEFAULT
, 0);
2167 CV_INIT(&sq
->cv
, "server Queue lock", CV_DEFAULT
, 0);
2169 MUTEX_ENTER(&sq
->lock
);
2171 if (cur_service
!= NULL
) {
2172 cur_service
->nRequestsRunning
--;
2173 MUTEX_ENTER(&rx_quota_mutex
);
2174 if (cur_service
->nRequestsRunning
< cur_service
->minProcs
)
2177 MUTEX_EXIT(&rx_quota_mutex
);
2179 if (!opr_queue_IsEmpty(&rx_incomingCallQueue
)) {
2180 struct rx_call
*tcall
;
2181 struct opr_queue
*cursor
;
2182 /* Scan for eligible incoming calls. A call is not eligible
2183 * if the maximum number of calls for its service type are
2184 * already executing */
2185 /* One thread will process calls FCFS (to prevent starvation),
2186 * while the other threads may run ahead looking for calls which
2187 * have all their input data available immediately. This helps
2188 * keep threads from blocking, waiting for data from the client. */
2189 choice2
= (struct rx_call
*)0;
2190 for (opr_queue_Scan(&rx_incomingCallQueue
, cursor
)) {
2191 tcall
= opr_queue_Entry(cursor
, struct rx_call
, entry
);
2192 service
= tcall
->conn
->service
;
2193 if (QuotaOK(service
)) {
2194 MUTEX_ENTER(&rx_pthread_mutex
);
2195 /* XXX - If tcall->entry.next is NULL, then we're no longer
2196 * on a queue at all. This shouldn't happen. */
2197 if (tno
== rxi_fcfs_thread_num
|| !tcall
->entry
.next
) {
2198 MUTEX_EXIT(&rx_pthread_mutex
);
2199 /* If we're the fcfs thread, then we'll just use
2200 * this call. If we haven't been able to find an optimal
2201 * choice, and we're at the end of the list, then use a
2202 * 2d choice if one has been identified. Otherwise... */
2203 call
= (choice2
? choice2
: tcall
);
2204 service
= call
->conn
->service
;
2206 MUTEX_EXIT(&rx_pthread_mutex
);
2207 if (!opr_queue_IsEmpty(&tcall
->rq
)) {
2208 struct rx_packet
*rp
;
2209 rp
= opr_queue_First(&tcall
->rq
, struct rx_packet
,
2211 if (rp
->header
.seq
== 1
2213 || (rp
->header
.flags
& RX_LAST_PACKET
))) {
2215 } else if (rxi_2dchoice
&& !choice2
2216 && !(tcall
->flags
& RX_CALL_CLEARED
)
2217 && (tcall
->rprev
> rxi_HardAckRate
)) {
2230 opr_queue_Remove(&call
->entry
);
2231 /* we can't schedule a call if there's no data!!! */
2232 /* send an ack if there's no data, if we're missing the
2233 * first packet, or we're missing something between first
2234 * and last -- there's a "hole" in the incoming data. */
2235 if (opr_queue_IsEmpty(&call
->rq
)
2236 || opr_queue_First(&call
->rq
, struct rx_packet
, entry
)->header
.seq
!= 1
2237 || call
->rprev
!= opr_queue_Last(&call
->rq
, struct rx_packet
, entry
)->header
.seq
)
2238 rxi_SendAck(call
, 0, 0, RX_ACK_DELAY
, 0);
2240 call
->flags
&= (~RX_CALL_WAIT_PROC
);
2241 service
->nRequestsRunning
++;
2242 /* just started call in minProcs pool, need fewer to maintain
2244 MUTEX_ENTER(&rx_quota_mutex
);
2245 if (service
->nRequestsRunning
<= service
->minProcs
)
2248 MUTEX_EXIT(&rx_quota_mutex
);
2249 rx_atomic_dec(&rx_nWaiting
);
2250 /* MUTEX_EXIT(&call->lock); */
2252 /* If there are no eligible incoming calls, add this process
2253 * to the idle server queue, to wait for one */
2256 *socketp
= OSI_NULLSOCKET
;
2258 sq
->socketp
= socketp
;
2259 opr_queue_Append(&rx_idleServerQueue
, &sq
->entry
);
2263 if (afs_termState
== AFSOP_STOP_RXCALLBACK
) {
2265 rxi_Free(sq
, sizeof(struct rx_serverQueueEntry
));
2266 return (struct rx_call
*)0;
2269 } while (!(call
= sq
->newcall
)
2270 && !(socketp
&& *socketp
!= OSI_NULLSOCKET
));
2272 MUTEX_EXIT(&sq
->lock
);
2274 MUTEX_ENTER(&freeSQEList_lock
);
2275 *(struct rx_serverQueueEntry
**)sq
= rx_FreeSQEList
;
2276 rx_FreeSQEList
= sq
;
2277 MUTEX_EXIT(&freeSQEList_lock
);
2280 clock_GetTime(&call
->startTime
);
2281 call
->state
= RX_STATE_ACTIVE
;
2282 call
->app
.mode
= RX_MODE_RECEIVING
;
2283 #ifdef RX_KERNEL_TRACE
2284 if (ICL_SETACTIVE(afs_iclSetp
)) {
2285 int glockOwner
= ISAFS_GLOCK();
2288 afs_Trace3(afs_iclSetp
, CM_TRACE_WASHERE
, ICL_TYPE_STRING
,
2289 __FILE__
, ICL_TYPE_INT32
, __LINE__
, ICL_TYPE_POINTER
,
2296 rxi_calltrace(RX_CALL_START
, call
);
2297 dpf(("rx_GetCall(port=%d, service=%d) ==> call %p\n",
2298 call
->conn
->service
->servicePort
, call
->conn
->service
->serviceId
,
2301 dpf(("rx_GetCall(socketp=%p, *socketp=0x%x)\n", socketp
, *socketp
));
2308 #endif /* RX_ENABLE_LOCKS */
2312 /* Establish a procedure to be called when a packet arrives for a
2313 * call. This routine will be called at most once after each call,
2314 * and will also be called if there is an error condition on the or
2315 * the call is complete. Used by multi rx to build a selection
2316 * function which determines which of several calls is likely to be a
2317 * good one to read from.
2318 * NOTE: the way this is currently implemented it is probably only a
2319 * good idea to (1) use it immediately after a newcall (clients only)
2320 * and (2) only use it once. Other uses currently void your warranty
2323 rx_SetArrivalProc(struct rx_call
*call
,
2324 void (*proc
) (struct rx_call
* call
,
2327 void * handle
, int arg
)
2329 call
->arrivalProc
= proc
;
2330 call
->arrivalProcHandle
= handle
;
2331 call
->arrivalProcArg
= arg
;
2334 /* Call is finished (possibly prematurely). Return rc to the peer, if
2335 * appropriate, and return the final error code from the conversation
2339 rx_EndCall(struct rx_call
*call
, afs_int32 rc
)
2341 struct rx_connection
*conn
= call
->conn
;
2345 dpf(("rx_EndCall(call %"AFS_PTR_FMT
" rc %d error %d abortCode %d)\n",
2346 call
, rc
, call
->error
, call
->abortCode
));
2349 MUTEX_ENTER(&call
->lock
);
2351 if (rc
== 0 && call
->error
== 0) {
2352 call
->abortCode
= 0;
2353 call
->abortCount
= 0;
2356 call
->arrivalProc
= (void (*)())0;
2357 if (rc
&& call
->error
== 0) {
2358 rxi_CallError(call
, rc
);
2359 call
->app
.mode
= RX_MODE_ERROR
;
2360 /* Send an abort message to the peer if this error code has
2361 * only just been set. If it was set previously, assume the
2362 * peer has already been sent the error code or will request it
2364 rxi_SendCallAbort(call
, (struct rx_packet
*)0, 0, 0);
2366 if (conn
->type
== RX_SERVER_CONNECTION
) {
2367 /* Make sure reply or at least dummy reply is sent */
2368 if (call
->app
.mode
== RX_MODE_RECEIVING
) {
2369 MUTEX_EXIT(&call
->lock
);
2370 rxi_WriteProc(call
, 0, 0);
2371 MUTEX_ENTER(&call
->lock
);
2373 if (call
->app
.mode
== RX_MODE_SENDING
) {
2374 rxi_FlushWriteLocked(call
);
2376 rxi_calltrace(RX_CALL_END
, call
);
2377 /* Call goes to hold state until reply packets are acknowledged */
2378 if (call
->tfirst
+ call
->nSoftAcked
< call
->tnext
) {
2379 call
->state
= RX_STATE_HOLD
;
2381 call
->state
= RX_STATE_DALLY
;
2382 rxi_ClearTransmitQueue(call
, 0);
2383 rxi_rto_cancel(call
);
2384 rxi_CancelKeepAliveEvent(call
);
2386 } else { /* Client connection */
2388 /* Make sure server receives input packets, in the case where
2389 * no reply arguments are expected */
2391 if ((call
->app
.mode
== RX_MODE_SENDING
)
2392 || (call
->app
.mode
== RX_MODE_RECEIVING
&& call
->rnext
== 1)) {
2393 MUTEX_EXIT(&call
->lock
);
2394 (void)rxi_ReadProc(call
, &dummy
, 1);
2395 MUTEX_ENTER(&call
->lock
);
2398 /* If we had an outstanding delayed ack, be nice to the server
2399 * and force-send it now.
2401 if (call
->delayedAckEvent
) {
2402 rxi_CancelDelayedAckEvent(call
);
2403 rxi_SendDelayedAck(NULL
, call
, NULL
, 0);
2406 /* We need to release the call lock since it's lower than the
2407 * conn_call_lock and we don't want to hold the conn_call_lock
2408 * over the rx_ReadProc call. The conn_call_lock needs to be held
2409 * here for the case where rx_NewCall is perusing the calls on
2410 * the connection structure. We don't want to signal until
2411 * rx_NewCall is in a stable state. Otherwise, rx_NewCall may
2412 * have checked this call, found it active and by the time it
2413 * goes to sleep, will have missed the signal.
2415 MUTEX_EXIT(&call
->lock
);
2416 MUTEX_ENTER(&conn
->conn_call_lock
);
2417 MUTEX_ENTER(&call
->lock
);
2420 /* While there are some circumstances where a call with an error is
2421 * obviously not on a "busy" channel, be conservative (clearing
2422 * lastBusy is just best-effort to possibly speed up rx_NewCall).
2423 * The call channel is definitely not busy if we just successfully
2424 * completed a call on it. */
2425 conn
->lastBusy
[call
->channel
] = 0;
2427 } else if (call
->error
== RX_CALL_TIMEOUT
) {
2428 /* The call is still probably running on the server side, so try to
2429 * avoid this call channel in the future. */
2430 conn
->lastBusy
[call
->channel
] = clock_Sec();
2433 MUTEX_ENTER(&conn
->conn_data_lock
);
2434 conn
->flags
|= RX_CONN_BUSY
;
2435 if (conn
->flags
& RX_CONN_MAKECALL_WAITING
) {
2436 MUTEX_EXIT(&conn
->conn_data_lock
);
2437 #ifdef RX_ENABLE_LOCKS
2438 CV_BROADCAST(&conn
->conn_call_cv
);
2443 #ifdef RX_ENABLE_LOCKS
2445 MUTEX_EXIT(&conn
->conn_data_lock
);
2447 #endif /* RX_ENABLE_LOCKS */
2448 call
->state
= RX_STATE_DALLY
;
2450 error
= call
->error
;
2452 /* currentPacket, nLeft, and NFree must be zeroed here, because
2453 * ResetCall cannot: ResetCall may be called at splnet(), in the
2454 * kernel version, and may interrupt the macros rx_Read or
2455 * rx_Write, which run at normal priority for efficiency. */
2456 if (call
->app
.currentPacket
) {
2457 #ifdef RX_TRACK_PACKETS
2458 call
->app
.currentPacket
->flags
&= ~RX_PKTFLAG_CP
;
2460 rxi_FreePacket(call
->app
.currentPacket
);
2461 call
->app
.currentPacket
= (struct rx_packet
*)0;
2464 call
->app
.nLeft
= call
->app
.nFree
= call
->app
.curlen
= 0;
2466 /* Free any packets from the last call to ReadvProc/WritevProc */
2467 #ifdef RXDEBUG_PACKET
2469 #endif /* RXDEBUG_PACKET */
2470 rxi_FreePackets(0, &call
->app
.iovq
);
2471 MUTEX_EXIT(&call
->lock
);
2473 CALL_RELE(call
, RX_CALL_REFCOUNT_BEGIN
);
2474 if (conn
->type
== RX_CLIENT_CONNECTION
) {
2475 MUTEX_ENTER(&conn
->conn_data_lock
);
2476 conn
->flags
&= ~RX_CONN_BUSY
;
2477 MUTEX_EXIT(&conn
->conn_data_lock
);
2478 MUTEX_EXIT(&conn
->conn_call_lock
);
2482 * Map errors to the local host's errno.h format.
2484 error
= ntoh_syserr_conv(error
);
2486 /* If the caller said the call failed with some error, we had better
2487 * return an error code. */
2488 osi_Assert(!rc
|| error
);
2492 #if !defined(KERNEL)
2494 /* Call this routine when shutting down a server or client (especially
2495 * clients). This will allow Rx to gracefully garbage collect server
2496 * connections, and reduce the number of retries that a server might
2497 * make to a dead client.
2498 * This is not quite right, since some calls may still be ongoing and
2499 * we can't lock them to destroy them. */
2503 struct rx_connection
**conn_ptr
, **conn_end
;
2506 if (rx_atomic_test_and_set_bit(&rxinit_status
, 0))
2507 return; /* Already shutdown. */
2509 rxi_DeleteCachedConnections();
2510 if (rx_connHashTable
) {
2511 MUTEX_ENTER(&rx_connHashTable_lock
);
2512 for (conn_ptr
= &rx_connHashTable
[0], conn_end
=
2513 &rx_connHashTable
[rx_hashTableSize
]; conn_ptr
< conn_end
;
2515 struct rx_connection
*conn
, *next
;
2516 for (conn
= *conn_ptr
; conn
; conn
= next
) {
2518 if (conn
->type
== RX_CLIENT_CONNECTION
) {
2519 MUTEX_ENTER(&rx_refcnt_mutex
);
2521 MUTEX_EXIT(&rx_refcnt_mutex
);
2522 #ifdef RX_ENABLE_LOCKS
2523 rxi_DestroyConnectionNoLock(conn
);
2524 #else /* RX_ENABLE_LOCKS */
2525 rxi_DestroyConnection(conn
);
2526 #endif /* RX_ENABLE_LOCKS */
2530 #ifdef RX_ENABLE_LOCKS
2531 while (rx_connCleanup_list
) {
2532 struct rx_connection
*conn
;
2533 conn
= rx_connCleanup_list
;
2534 rx_connCleanup_list
= rx_connCleanup_list
->next
;
2535 MUTEX_EXIT(&rx_connHashTable_lock
);
2536 rxi_CleanupConnection(conn
);
2537 MUTEX_ENTER(&rx_connHashTable_lock
);
2539 MUTEX_EXIT(&rx_connHashTable_lock
);
2540 #endif /* RX_ENABLE_LOCKS */
2545 afs_winsockCleanup();
2551 /* if we wakeup packet waiter too often, can get in loop with two
2552 AllocSendPackets each waking each other up (from ReclaimPacket calls) */
2554 rxi_PacketsUnWait(void)
2556 if (!rx_waitingForPackets
) {
2560 if (rxi_OverQuota(RX_PACKET_CLASS_SEND
)) {
2561 return; /* still over quota */
2564 rx_waitingForPackets
= 0;
2565 #ifdef RX_ENABLE_LOCKS
2566 CV_BROADCAST(&rx_waitingForPackets_cv
);
2568 osi_rxWakeup(&rx_waitingForPackets
);
2574 /* ------------------Internal interfaces------------------------- */
2576 /* Return this process's service structure for the
2577 * specified socket and service */
2578 static struct rx_service
*
2579 rxi_FindService(osi_socket socket
, u_short serviceId
)
2581 struct rx_service
**sp
;
2582 for (sp
= &rx_services
[0]; *sp
; sp
++) {
2583 if ((*sp
)->serviceId
== serviceId
&& (*sp
)->socket
== socket
)
2589 #ifdef RXDEBUG_PACKET
2590 #ifdef KDUMP_RX_LOCK
2591 static struct rx_call_rx_lock
*rx_allCallsp
= 0;
2593 static struct rx_call
*rx_allCallsp
= 0;
2595 #endif /* RXDEBUG_PACKET */
2597 /* Allocate a call structure, for the indicated channel of the
2598 * supplied connection. The mode and state of the call must be set by
2599 * the caller. Returns the call with mutex locked. */
2600 static struct rx_call
*
2601 rxi_NewCall(struct rx_connection
*conn
, int channel
)
2603 struct rx_call
*call
;
2604 #ifdef RX_ENABLE_LOCKS
2605 struct rx_call
*cp
; /* Call pointer temp */
2606 struct opr_queue
*cursor
;
2609 dpf(("rxi_NewCall(conn %"AFS_PTR_FMT
", channel %d)\n", conn
, channel
));
2611 /* Grab an existing call structure, or allocate a new one.
2612 * Existing call structures are assumed to have been left reset by
2614 MUTEX_ENTER(&rx_freeCallQueue_lock
);
2616 #ifdef RX_ENABLE_LOCKS
2618 * EXCEPT that the TQ might not yet be cleared out.
2619 * Skip over those with in-use TQs.
2622 for (opr_queue_Scan(&rx_freeCallQueue
, cursor
)) {
2623 cp
= opr_queue_Entry(cursor
, struct rx_call
, entry
);
2624 if (!(cp
->flags
& RX_CALL_TQ_BUSY
)) {
2630 #else /* RX_ENABLE_LOCKS */
2631 if (!opr_queue_IsEmpty(&rx_freeCallQueue
)) {
2632 call
= opr_queue_First(&rx_freeCallQueue
, struct rx_call
, entry
);
2633 #endif /* RX_ENABLE_LOCKS */
2634 opr_queue_Remove(&call
->entry
);
2635 if (rx_stats_active
)
2636 rx_atomic_dec(&rx_stats
.nFreeCallStructs
);
2637 MUTEX_EXIT(&rx_freeCallQueue_lock
);
2638 MUTEX_ENTER(&call
->lock
);
2639 CLEAR_CALL_QUEUE_LOCK(call
);
2640 #ifdef RX_ENABLE_LOCKS
2641 /* Now, if TQ wasn't cleared earlier, do it now. */
2642 rxi_WaitforTQBusy(call
);
2643 if (call
->flags
& RX_CALL_TQ_CLEARME
) {
2644 rxi_ClearTransmitQueue(call
, 1);
2645 /*queue_Init(&call->tq);*/
2647 #endif /* RX_ENABLE_LOCKS */
2648 /* Bind the call to its connection structure */
2650 rxi_ResetCall(call
, 1);
2653 call
= rxi_Alloc(sizeof(struct rx_call
));
2654 #ifdef RXDEBUG_PACKET
2655 call
->allNextp
= rx_allCallsp
;
2656 rx_allCallsp
= call
;
2658 rx_atomic_inc_and_read(&rx_stats
.nCallStructs
);
2659 #else /* RXDEBUG_PACKET */
2660 rx_atomic_inc(&rx_stats
.nCallStructs
);
2661 #endif /* RXDEBUG_PACKET */
2663 MUTEX_EXIT(&rx_freeCallQueue_lock
);
2664 MUTEX_INIT(&call
->lock
, "call lock", MUTEX_DEFAULT
, NULL
);
2665 MUTEX_ENTER(&call
->lock
);
2666 CV_INIT(&call
->cv_twind
, "call twind", CV_DEFAULT
, 0);
2667 CV_INIT(&call
->cv_rq
, "call rq", CV_DEFAULT
, 0);
2668 CV_INIT(&call
->cv_tq
, "call tq", CV_DEFAULT
, 0);
2670 /* Initialize once-only items */
2671 opr_queue_Init(&call
->tq
);
2672 opr_queue_Init(&call
->rq
);
2673 opr_queue_Init(&call
->app
.iovq
);
2674 #ifdef RXDEBUG_PACKET
2675 call
->rqc
= call
->tqc
= call
->iovqc
= 0;
2676 #endif /* RXDEBUG_PACKET */
2677 /* Bind the call to its connection structure (prereq for reset) */
2679 rxi_ResetCall(call
, 1);
2681 call
->channel
= channel
;
2682 call
->callNumber
= &conn
->callNumber
[channel
];
2683 call
->rwind
= conn
->rwind
[channel
];
2684 call
->twind
= conn
->twind
[channel
];
2685 /* Note that the next expected call number is retained (in
2686 * conn->callNumber[i]), even if we reallocate the call structure
2688 conn
->call
[channel
] = call
;
2689 /* if the channel's never been used (== 0), we should start at 1, otherwise
2690 * the call number is valid from the last time this channel was used */
2691 if (*call
->callNumber
== 0)
2692 *call
->callNumber
= 1;
2697 /* A call has been inactive long enough that so we can throw away
2698 * state, including the call structure, which is placed on the call
2701 * call->lock amd rx_refcnt_mutex are held upon entry.
2702 * haveCTLock is set when called from rxi_ReapConnections.
2704 * return 1 if the call is freed, 0 if not.
2707 rxi_FreeCall(struct rx_call
*call
, int haveCTLock
)
2709 int channel
= call
->channel
;
2710 struct rx_connection
*conn
= call
->conn
;
2711 u_char state
= call
->state
;
2714 * We are setting the state to RX_STATE_RESET to
2715 * ensure that no one else will attempt to use this
2716 * call once we drop the refcnt lock. We must drop
2717 * the refcnt lock before calling rxi_ResetCall
2718 * because it cannot be held across acquiring the
2719 * freepktQ lock. NewCall does the same.
2721 call
->state
= RX_STATE_RESET
;
2722 MUTEX_EXIT(&rx_refcnt_mutex
);
2723 rxi_ResetCall(call
, 0);
2725 if (MUTEX_TRYENTER(&conn
->conn_call_lock
))
2727 if (state
== RX_STATE_DALLY
|| state
== RX_STATE_HOLD
)
2728 (*call
->callNumber
)++;
2730 if (call
->conn
->call
[channel
] == call
)
2731 call
->conn
->call
[channel
] = 0;
2732 MUTEX_EXIT(&conn
->conn_call_lock
);
2735 * We couldn't obtain the conn_call_lock so we can't
2736 * disconnect the call from the connection. Set the
2737 * call state to dally so that the call can be reused.
2739 MUTEX_ENTER(&rx_refcnt_mutex
);
2740 call
->state
= RX_STATE_DALLY
;
2744 MUTEX_ENTER(&rx_freeCallQueue_lock
);
2745 SET_CALL_QUEUE_LOCK(call
, &rx_freeCallQueue_lock
);
2746 #ifdef RX_ENABLE_LOCKS
2747 /* A call may be free even though its transmit queue is still in use.
2748 * Since we search the call list from head to tail, put busy calls at
2749 * the head of the list, and idle calls at the tail.
2751 if (call
->flags
& RX_CALL_TQ_BUSY
)
2752 opr_queue_Prepend(&rx_freeCallQueue
, &call
->entry
);
2754 opr_queue_Append(&rx_freeCallQueue
, &call
->entry
);
2755 #else /* RX_ENABLE_LOCKS */
2756 opr_queue_Append(&rx_freeCallQueue
, &call
->entry
);
2757 #endif /* RX_ENABLE_LOCKS */
2758 if (rx_stats_active
)
2759 rx_atomic_inc(&rx_stats
.nFreeCallStructs
);
2760 MUTEX_EXIT(&rx_freeCallQueue_lock
);
2762 /* Destroy the connection if it was previously slated for
2763 * destruction, i.e. the Rx client code previously called
2764 * rx_DestroyConnection (client connections), or
2765 * rxi_ReapConnections called the same routine (server
2766 * connections). Only do this, however, if there are no
2767 * outstanding calls. Note that for fine grain locking, there appears
2768 * to be a deadlock in that rxi_FreeCall has a call locked and
2769 * DestroyConnectionNoLock locks each call in the conn. But note a
2770 * few lines up where we have removed this call from the conn.
2771 * If someone else destroys a connection, they either have no
2772 * call lock held or are going through this section of code.
2774 MUTEX_ENTER(&conn
->conn_data_lock
);
2775 if (conn
->flags
& RX_CONN_DESTROY_ME
&& !(conn
->flags
& RX_CONN_MAKECALL_WAITING
)) {
2776 MUTEX_ENTER(&rx_refcnt_mutex
);
2778 MUTEX_EXIT(&rx_refcnt_mutex
);
2779 MUTEX_EXIT(&conn
->conn_data_lock
);
2780 #ifdef RX_ENABLE_LOCKS
2782 rxi_DestroyConnectionNoLock(conn
);
2784 rxi_DestroyConnection(conn
);
2785 #else /* RX_ENABLE_LOCKS */
2786 rxi_DestroyConnection(conn
);
2787 #endif /* RX_ENABLE_LOCKS */
2789 MUTEX_EXIT(&conn
->conn_data_lock
);
2791 MUTEX_ENTER(&rx_refcnt_mutex
);
2795 rx_atomic_t rxi_Allocsize
= RX_ATOMIC_INIT(0);
2796 rx_atomic_t rxi_Alloccnt
= RX_ATOMIC_INIT(0);
2799 rxi_Alloc(size_t size
)
2803 if (rx_stats_active
) {
2804 rx_atomic_add(&rxi_Allocsize
, (int) size
);
2805 rx_atomic_inc(&rxi_Alloccnt
);
2809 #if defined(KERNEL) && !defined(UKERNEL) && defined(AFS_FBSD80_ENV)
2810 afs_osi_Alloc_NoSleep(size
);
2815 osi_Panic("rxi_Alloc error");
2821 rxi_Free(void *addr
, size_t size
)
2823 if (rx_stats_active
) {
2824 rx_atomic_sub(&rxi_Allocsize
, (int) size
);
2825 rx_atomic_dec(&rxi_Alloccnt
);
2827 osi_Free(addr
, size
);
2831 rxi_SetPeerMtu(struct rx_peer
*peer
, afs_uint32 host
, afs_uint32 port
, int mtu
)
2833 struct rx_peer
**peer_ptr
= NULL
, **peer_end
= NULL
;
2834 struct rx_peer
*next
= NULL
;
2838 MUTEX_ENTER(&rx_peerHashTable_lock
);
2840 peer_ptr
= &rx_peerHashTable
[0];
2841 peer_end
= &rx_peerHashTable
[rx_hashTableSize
];
2844 for ( ; peer_ptr
< peer_end
; peer_ptr
++) {
2847 for ( ; peer
; peer
= next
) {
2849 if (host
== peer
->host
)
2854 hashIndex
= PEER_HASH(host
, port
);
2855 for (peer
= rx_peerHashTable
[hashIndex
]; peer
; peer
= peer
->next
) {
2856 if ((peer
->host
== host
) && (peer
->port
== port
))
2861 MUTEX_ENTER(&rx_peerHashTable_lock
);
2866 MUTEX_EXIT(&rx_peerHashTable_lock
);
2868 MUTEX_ENTER(&peer
->peer_lock
);
2869 /* We don't handle dropping below min, so don't */
2870 mtu
= MAX(mtu
, RX_MIN_PACKET_SIZE
);
2871 peer
->ifMTU
=MIN(mtu
, peer
->ifMTU
);
2872 peer
->natMTU
= rxi_AdjustIfMTU(peer
->ifMTU
);
2873 /* if we tweaked this down, need to tune our peer MTU too */
2874 peer
->MTU
= MIN(peer
->MTU
, peer
->natMTU
);
2875 /* if we discovered a sub-1500 mtu, degrade */
2876 if (peer
->ifMTU
< OLD_MAX_PACKET_SIZE
)
2877 peer
->maxDgramPackets
= 1;
2878 /* We no longer have valid peer packet information */
2879 if (peer
->maxPacketSize
+ RX_HEADER_SIZE
> peer
->ifMTU
)
2880 peer
->maxPacketSize
= 0;
2881 MUTEX_EXIT(&peer
->peer_lock
);
2883 MUTEX_ENTER(&rx_peerHashTable_lock
);
2885 if (host
&& !port
) {
2887 /* pick up where we left off */
2891 MUTEX_EXIT(&rx_peerHashTable_lock
);
2894 #ifdef AFS_RXERRQ_ENV
2896 rxi_SetPeerDead(struct sock_extended_err
*err
, afs_uint32 host
, afs_uint16 port
)
2898 int hashIndex
= PEER_HASH(host
, port
);
2899 struct rx_peer
*peer
;
2901 MUTEX_ENTER(&rx_peerHashTable_lock
);
2903 for (peer
= rx_peerHashTable
[hashIndex
]; peer
; peer
= peer
->next
) {
2904 if (peer
->host
== host
&& peer
->port
== port
) {
2910 MUTEX_EXIT(&rx_peerHashTable_lock
);
2913 rx_atomic_inc(&peer
->neterrs
);
2914 MUTEX_ENTER(&peer
->peer_lock
);
2915 peer
->last_err_origin
= RX_NETWORK_ERROR_ORIGIN_ICMP
;
2916 peer
->last_err_type
= err
->ee_type
;
2917 peer
->last_err_code
= err
->ee_code
;
2918 MUTEX_EXIT(&peer
->peer_lock
);
2920 MUTEX_ENTER(&rx_peerHashTable_lock
);
2922 MUTEX_EXIT(&rx_peerHashTable_lock
);
2927 rxi_ProcessNetError(struct sock_extended_err
*err
, afs_uint32 addr
, afs_uint16 port
)
2929 # ifdef AFS_ADAPT_PMTU
2930 if (err
->ee_errno
== EMSGSIZE
&& err
->ee_info
>= 68) {
2931 rxi_SetPeerMtu(NULL
, addr
, port
, err
->ee_info
- RX_IPUDP_SIZE
);
2935 if (err
->ee_origin
== SO_EE_ORIGIN_ICMP
&& err
->ee_type
== ICMP_DEST_UNREACH
) {
2936 switch (err
->ee_code
) {
2937 case ICMP_NET_UNREACH
:
2938 case ICMP_HOST_UNREACH
:
2939 case ICMP_PORT_UNREACH
:
2942 rxi_SetPeerDead(err
, addr
, port
);
2949 rxi_TranslateICMP(int type
, int code
)
2952 case ICMP_DEST_UNREACH
:
2954 case ICMP_NET_UNREACH
:
2955 return "Destination Net Unreachable";
2956 case ICMP_HOST_UNREACH
:
2957 return "Destination Host Unreachable";
2958 case ICMP_PROT_UNREACH
:
2959 return "Destination Protocol Unreachable";
2960 case ICMP_PORT_UNREACH
:
2961 return "Destination Port Unreachable";
2963 return "Destination Net Prohibited";
2965 return "Destination Host Prohibited";
2971 #endif /* AFS_RXERRQ_ENV */
2974 * Get the last network error for a connection
2976 * A "network error" here means an error retrieved from ICMP, or some other
2977 * mechanism outside of Rx that informs us of errors in network reachability.
2979 * If a peer associated with the given Rx connection has received a network
2980 * error recently, this function allows the caller to know what error
2981 * specifically occurred. This can be useful to know, since e.g. ICMP errors
2982 * can cause calls to that peer to be quickly aborted. So, this function can
2983 * help see why a call was aborted due to network errors.
2985 * If we have received traffic from a peer since the last network error, we
2986 * treat that peer as if we had not received an network error for it.
2988 * @param[in] conn The Rx connection to examine
2989 * @param[out] err_origin The origin of the last network error (e.g. ICMP);
2990 * one of the RX_NETWORK_ERROR_ORIGIN_* constants
2991 * @param[out] err_type The type of the last error
2992 * @param[out] err_code The code of the last error
2993 * @param[out] msg Human-readable error message, if applicable; NULL otherwise
2995 * @return If we have an error
2996 * @retval -1 No error to get; 'out' params are undefined
2997 * @retval 0 We have an error; 'out' params contain the last error
3000 rx_GetNetworkError(struct rx_connection
*conn
, int *err_origin
, int *err_type
,
3001 int *err_code
, const char **msg
)
3003 #ifdef AFS_RXERRQ_ENV
3004 struct rx_peer
*peer
= conn
->peer
;
3005 if (rx_atomic_read(&peer
->neterrs
)) {
3006 MUTEX_ENTER(&peer
->peer_lock
);
3007 *err_origin
= peer
->last_err_origin
;
3008 *err_type
= peer
->last_err_type
;
3009 *err_code
= peer
->last_err_code
;
3010 MUTEX_EXIT(&peer
->peer_lock
);
3013 if (*err_origin
== RX_NETWORK_ERROR_ORIGIN_ICMP
) {
3014 *msg
= rxi_TranslateICMP(*err_type
, *err_code
);
3023 /* Find the peer process represented by the supplied (host,port)
3024 * combination. If there is no appropriate active peer structure, a
3025 * new one will be allocated and initialized
3028 rxi_FindPeer(afs_uint32 host
, u_short port
, int create
)
3032 hashIndex
= PEER_HASH(host
, port
);
3033 MUTEX_ENTER(&rx_peerHashTable_lock
);
3034 for (pp
= rx_peerHashTable
[hashIndex
]; pp
; pp
= pp
->next
) {
3035 if ((pp
->host
== host
) && (pp
->port
== port
))
3040 pp
= rxi_AllocPeer(); /* This bzero's *pp */
3041 pp
->host
= host
; /* set here or in InitPeerParams is zero */
3043 #ifdef AFS_RXERRQ_ENV
3044 rx_atomic_set(&pp
->neterrs
, 0);
3046 MUTEX_INIT(&pp
->peer_lock
, "peer_lock", MUTEX_DEFAULT
, 0);
3047 opr_queue_Init(&pp
->rpcStats
);
3048 pp
->next
= rx_peerHashTable
[hashIndex
];
3049 rx_peerHashTable
[hashIndex
] = pp
;
3050 rxi_InitPeerParams(pp
);
3051 if (rx_stats_active
)
3052 rx_atomic_inc(&rx_stats
.nPeerStructs
);
3058 MUTEX_EXIT(&rx_peerHashTable_lock
);
3063 /* Find the connection at (host, port) started at epoch, and with the
3064 * given connection id. Creates the server connection if necessary.
3065 * The type specifies whether a client connection or a server
3066 * connection is desired. In both cases, (host, port) specify the
3067 * peer's (host, pair) pair. Client connections are not made
3068 * automatically by this routine. The parameter socket gives the
3069 * socket descriptor on which the packet was received. This is used,
3070 * in the case of server connections, to check that *new* connections
3071 * come via a valid (port, serviceId). Finally, the securityIndex
3072 * parameter must match the existing index for the connection. If a
3073 * server connection is created, it will be created using the supplied
3074 * index, if the index is valid for this service */
3075 static struct rx_connection
*
3076 rxi_FindConnection(osi_socket socket
, afs_uint32 host
,
3077 u_short port
, u_short serviceId
, afs_uint32 cid
,
3078 afs_uint32 epoch
, int type
, u_int securityIndex
,
3079 int *unknownService
)
3081 int hashindex
, flag
, i
;
3082 struct rx_connection
*conn
;
3083 *unknownService
= 0;
3084 hashindex
= CONN_HASH(host
, port
, cid
, epoch
, type
);
3085 MUTEX_ENTER(&rx_connHashTable_lock
);
3086 rxLastConn
? (conn
= rxLastConn
, flag
= 0) : (conn
=
3087 rx_connHashTable
[hashindex
],
3090 if ((conn
->type
== type
) && ((cid
& RX_CIDMASK
) == conn
->cid
)
3091 && (epoch
== conn
->epoch
)) {
3092 struct rx_peer
*pp
= conn
->peer
;
3093 if (securityIndex
!= conn
->securityIndex
) {
3094 /* this isn't supposed to happen, but someone could forge a packet
3095 * like this, and there seems to be some CM bug that makes this
3096 * happen from time to time -- in which case, the fileserver
3098 MUTEX_EXIT(&rx_connHashTable_lock
);
3099 return (struct rx_connection
*)0;
3101 if (pp
->host
== host
&& pp
->port
== port
)
3103 if (type
== RX_CLIENT_CONNECTION
&& pp
->port
== port
)
3105 /* So what happens when it's a callback connection? */
3106 if ( /*type == RX_CLIENT_CONNECTION && */
3107 (conn
->epoch
& 0x80000000))
3111 /* the connection rxLastConn that was used the last time is not the
3112 ** one we are looking for now. Hence, start searching in the hash */
3114 conn
= rx_connHashTable
[hashindex
];
3119 struct rx_service
*service
;
3120 if (type
== RX_CLIENT_CONNECTION
) {
3121 MUTEX_EXIT(&rx_connHashTable_lock
);
3122 return (struct rx_connection
*)0;
3124 service
= rxi_FindService(socket
, serviceId
);
3125 if (!service
|| (securityIndex
>= service
->nSecurityObjects
)
3126 || (service
->securityObjects
[securityIndex
] == 0)) {
3127 MUTEX_EXIT(&rx_connHashTable_lock
);
3128 *unknownService
= 1;
3129 return (struct rx_connection
*)0;
3131 conn
= rxi_AllocConnection(); /* This bzero's the connection */
3132 MUTEX_INIT(&conn
->conn_call_lock
, "conn call lock", MUTEX_DEFAULT
, 0);
3133 MUTEX_INIT(&conn
->conn_data_lock
, "conn data lock", MUTEX_DEFAULT
, 0);
3134 CV_INIT(&conn
->conn_call_cv
, "conn call cv", CV_DEFAULT
, 0);
3135 conn
->next
= rx_connHashTable
[hashindex
];
3136 rx_connHashTable
[hashindex
] = conn
;
3137 conn
->peer
= rxi_FindPeer(host
, port
, 1);
3138 conn
->type
= RX_SERVER_CONNECTION
;
3139 conn
->lastSendTime
= clock_Sec(); /* don't GC immediately */
3140 conn
->epoch
= epoch
;
3141 conn
->cid
= cid
& RX_CIDMASK
;
3142 conn
->ackRate
= RX_FAST_ACK_RATE
;
3143 conn
->service
= service
;
3144 conn
->serviceId
= serviceId
;
3145 conn
->securityIndex
= securityIndex
;
3146 conn
->securityObject
= service
->securityObjects
[securityIndex
];
3147 conn
->nSpecific
= 0;
3148 conn
->specific
= NULL
;
3149 rx_SetConnDeadTime(conn
, service
->connDeadTime
);
3150 rx_SetConnIdleDeadTime(conn
, service
->idleDeadTime
);
3151 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
3152 conn
->twind
[i
] = rx_initSendWindow
;
3153 conn
->rwind
[i
] = rx_initReceiveWindow
;
3155 /* Notify security object of the new connection */
3156 RXS_NewConnection(conn
->securityObject
, conn
);
3157 /* XXXX Connection timeout? */
3158 if (service
->newConnProc
)
3159 (*service
->newConnProc
) (conn
);
3160 if (rx_stats_active
)
3161 rx_atomic_inc(&rx_stats
.nServerConns
);
3164 MUTEX_ENTER(&rx_refcnt_mutex
);
3166 MUTEX_EXIT(&rx_refcnt_mutex
);
3168 rxLastConn
= conn
; /* store this connection as the last conn used */
3169 MUTEX_EXIT(&rx_connHashTable_lock
);
3174 * Abort the call if the server is over the busy threshold. This
3175 * can be used without requiring a call structure be initialised,
3176 * or connected to a particular channel
3179 rxi_AbortIfServerBusy(osi_socket socket
, struct rx_connection
*conn
,
3180 struct rx_packet
*np
)
3182 if ((rx_BusyThreshold
> 0) &&
3183 (rx_atomic_read(&rx_nWaiting
) > rx_BusyThreshold
)) {
3184 rxi_SendRawAbort(socket
, conn
->peer
->host
, conn
->peer
->port
,
3185 rx_BusyError
, np
, 0);
3186 if (rx_stats_active
)
3187 rx_atomic_inc(&rx_stats
.nBusies
);
3194 static_inline
struct rx_call
*
3195 rxi_ReceiveClientCall(struct rx_packet
*np
, struct rx_connection
*conn
)
3198 struct rx_call
*call
;
3200 channel
= np
->header
.cid
& RX_CHANNELMASK
;
3201 MUTEX_ENTER(&conn
->conn_call_lock
);
3202 call
= conn
->call
[channel
];
3203 if (np
->header
.type
== RX_PACKET_TYPE_BUSY
) {
3204 conn
->lastBusy
[channel
] = clock_Sec();
3206 if (!call
|| conn
->callNumber
[channel
] != np
->header
.callNumber
) {
3207 MUTEX_EXIT(&conn
->conn_call_lock
);
3208 if (rx_stats_active
)
3209 rx_atomic_inc(&rx_stats
.spuriousPacketsRead
);
3213 MUTEX_ENTER(&call
->lock
);
3214 MUTEX_EXIT(&conn
->conn_call_lock
);
3216 if ((call
->state
== RX_STATE_DALLY
)
3217 && np
->header
.type
== RX_PACKET_TYPE_ACK
) {
3218 if (rx_stats_active
)
3219 rx_atomic_inc(&rx_stats
.ignorePacketDally
);
3220 MUTEX_EXIT(&call
->lock
);
3227 static_inline
struct rx_call
*
3228 rxi_ReceiveServerCall(osi_socket socket
, struct rx_packet
*np
,
3229 struct rx_connection
*conn
)
3232 struct rx_call
*call
;
3234 channel
= np
->header
.cid
& RX_CHANNELMASK
;
3235 MUTEX_ENTER(&conn
->conn_call_lock
);
3236 call
= conn
->call
[channel
];
3239 if (rxi_AbortIfServerBusy(socket
, conn
, np
)) {
3240 MUTEX_EXIT(&conn
->conn_call_lock
);
3244 call
= rxi_NewCall(conn
, channel
); /* returns locked call */
3245 *call
->callNumber
= np
->header
.callNumber
;
3246 MUTEX_EXIT(&conn
->conn_call_lock
);
3248 call
->state
= RX_STATE_PRECALL
;
3249 clock_GetTime(&call
->queueTime
);
3250 call
->app
.bytesSent
= 0;
3251 call
->app
.bytesRcvd
= 0;
3252 rxi_KeepAliveOn(call
);
3257 if (np
->header
.callNumber
== conn
->callNumber
[channel
]) {
3258 MUTEX_ENTER(&call
->lock
);
3259 MUTEX_EXIT(&conn
->conn_call_lock
);
3263 if (np
->header
.callNumber
< conn
->callNumber
[channel
]) {
3264 MUTEX_EXIT(&conn
->conn_call_lock
);
3265 if (rx_stats_active
)
3266 rx_atomic_inc(&rx_stats
.spuriousPacketsRead
);
3270 MUTEX_ENTER(&call
->lock
);
3271 MUTEX_EXIT(&conn
->conn_call_lock
);
3273 /* Wait until the transmit queue is idle before deciding
3274 * whether to reset the current call. Chances are that the
3275 * call will be in ether DALLY or HOLD state once the TQ_BUSY
3278 #ifdef RX_ENABLE_LOCKS
3279 if (call
->state
== RX_STATE_ACTIVE
&& !call
->error
) {
3280 rxi_WaitforTQBusy(call
);
3281 /* If we entered error state while waiting,
3282 * must call rxi_CallError to permit rxi_ResetCall
3283 * to processed when the tqWaiter count hits zero.
3286 rxi_CallError(call
, call
->error
);
3287 MUTEX_EXIT(&call
->lock
);
3291 #endif /* RX_ENABLE_LOCKS */
3292 /* If the new call cannot be taken right now send a busy and set
3293 * the error condition in this call, so that it terminates as
3294 * quickly as possible */
3295 if (call
->state
== RX_STATE_ACTIVE
) {
3296 rxi_CallError(call
, RX_CALL_DEAD
);
3297 rxi_SendSpecial(call
, conn
, NULL
, RX_PACKET_TYPE_BUSY
,
3299 MUTEX_EXIT(&call
->lock
);
3303 if (rxi_AbortIfServerBusy(socket
, conn
, np
)) {
3304 MUTEX_EXIT(&call
->lock
);
3308 rxi_ResetCall(call
, 0);
3309 /* The conn_call_lock is not held but no one else should be
3310 * using this call channel while we are processing this incoming
3311 * packet. This assignment should be safe.
3313 *call
->callNumber
= np
->header
.callNumber
;
3314 call
->state
= RX_STATE_PRECALL
;
3315 clock_GetTime(&call
->queueTime
);
3316 call
->app
.bytesSent
= 0;
3317 call
->app
.bytesRcvd
= 0;
3318 rxi_KeepAliveOn(call
);
3324 /* There are two packet tracing routines available for testing and monitoring
3325 * Rx. One is called just after every packet is received and the other is
3326 * called just before every packet is sent. Received packets, have had their
3327 * headers decoded, and packets to be sent have not yet had their headers
3328 * encoded. Both take two parameters: a pointer to the packet and a sockaddr
3329 * containing the network address. Both can be modified. The return value, if
3330 * non-zero, indicates that the packet should be dropped. */
3332 int (*rx_justReceived
) (struct rx_packet
*, struct sockaddr_in
*) = 0;
3333 int (*rx_almostSent
) (struct rx_packet
*, struct sockaddr_in
*) = 0;
3335 /* A packet has been received off the interface. Np is the packet, socket is
3336 * the socket number it was received from (useful in determining which service
3337 * this packet corresponds to), and (host, port) reflect the host,port of the
3338 * sender. This call returns the packet to the caller if it is finished with
3339 * it, rather than de-allocating it, just as a small performance hack */
3342 rxi_ReceivePacket(struct rx_packet
*np
, osi_socket socket
,
3343 afs_uint32 host
, u_short port
, int *tnop
,
3344 struct rx_call
**newcallp
)
3346 struct rx_call
*call
;
3347 struct rx_connection
*conn
;
3349 int unknownService
= 0;
3353 struct rx_packet
*tnp
;
3356 /* We don't print out the packet until now because (1) the time may not be
3357 * accurate enough until now in the lwp implementation (rx_Listener only gets
3358 * the time after the packet is read) and (2) from a protocol point of view,
3359 * this is the first time the packet has been seen */
3360 packetType
= (np
->header
.type
> 0 && np
->header
.type
< RX_N_PACKET_TYPES
)
3361 ? rx_packetTypes
[np
->header
.type
- 1] : "*UNKNOWN*";
3362 dpf(("R %d %s: %x.%d.%d.%d.%d.%d.%d flags %d, packet %"AFS_PTR_FMT
"\n",
3363 np
->header
.serial
, packetType
, ntohl(host
), ntohs(port
), np
->header
.serviceId
,
3364 np
->header
.epoch
, np
->header
.cid
, np
->header
.callNumber
,
3365 np
->header
.seq
, np
->header
.flags
, np
));
3368 /* Account for connectionless packets */
3369 if (rx_stats_active
&&
3370 ((np
->header
.type
== RX_PACKET_TYPE_VERSION
) ||
3371 (np
->header
.type
== RX_PACKET_TYPE_DEBUG
))) {
3372 struct rx_peer
*peer
;
3374 /* Try to look up the peer structure, but don't create one */
3375 peer
= rxi_FindPeer(host
, port
, 0);
3377 /* Since this may not be associated with a connection, it may have
3378 * no refCount, meaning we could race with ReapConnections
3381 if (peer
&& (peer
->refCount
> 0)) {
3382 #ifdef AFS_RXERRQ_ENV
3383 if (rx_atomic_read(&peer
->neterrs
)) {
3384 rx_atomic_set(&peer
->neterrs
, 0);
3387 MUTEX_ENTER(&peer
->peer_lock
);
3388 peer
->bytesReceived
+= np
->length
;
3389 MUTEX_EXIT(&peer
->peer_lock
);
3393 if (np
->header
.type
== RX_PACKET_TYPE_VERSION
) {
3394 return rxi_ReceiveVersionPacket(np
, socket
, host
, port
, 1);
3397 if (np
->header
.type
== RX_PACKET_TYPE_DEBUG
) {
3398 return rxi_ReceiveDebugPacket(np
, socket
, host
, port
, 1);
3401 /* If an input tracer function is defined, call it with the packet and
3402 * network address. Note this function may modify its arguments. */
3403 if (rx_justReceived
) {
3404 struct sockaddr_in addr
;
3406 addr
.sin_family
= AF_INET
;
3407 addr
.sin_port
= port
;
3408 addr
.sin_addr
.s_addr
= host
;
3409 memset(&addr
.sin_zero
, 0, sizeof(addr
.sin_zero
));
3410 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
3411 addr
.sin_len
= sizeof(addr
);
3412 #endif /* AFS_OSF_ENV */
3413 drop
= (*rx_justReceived
) (np
, &addr
);
3414 /* drop packet if return value is non-zero */
3417 port
= addr
.sin_port
; /* in case fcn changed addr */
3418 host
= addr
.sin_addr
.s_addr
;
3422 /* If packet was not sent by the client, then *we* must be the client */
3423 type
= ((np
->header
.flags
& RX_CLIENT_INITIATED
) != RX_CLIENT_INITIATED
)
3424 ? RX_CLIENT_CONNECTION
: RX_SERVER_CONNECTION
;
3426 /* Find the connection (or fabricate one, if we're the server & if
3427 * necessary) associated with this packet */
3429 rxi_FindConnection(socket
, host
, port
, np
->header
.serviceId
,
3430 np
->header
.cid
, np
->header
.epoch
, type
,
3431 np
->header
.securityIndex
, &unknownService
);
3433 /* To avoid having 2 connections just abort at each other,
3434 don't abort an abort. */
3436 if (unknownService
&& (np
->header
.type
!= RX_PACKET_TYPE_ABORT
))
3437 rxi_SendRawAbort(socket
, host
, port
, RX_INVALID_OPERATION
,
3442 #ifdef AFS_RXERRQ_ENV
3443 if (rx_atomic_read(&conn
->peer
->neterrs
)) {
3444 rx_atomic_set(&conn
->peer
->neterrs
, 0);
3448 /* If we're doing statistics, then account for the incoming packet */
3449 if (rx_stats_active
) {
3450 MUTEX_ENTER(&conn
->peer
->peer_lock
);
3451 conn
->peer
->bytesReceived
+= np
->length
;
3452 MUTEX_EXIT(&conn
->peer
->peer_lock
);
3455 /* If the connection is in an error state, send an abort packet and ignore
3456 * the incoming packet */
3458 /* Don't respond to an abort packet--we don't want loops! */
3459 MUTEX_ENTER(&conn
->conn_data_lock
);
3460 if (np
->header
.type
!= RX_PACKET_TYPE_ABORT
)
3461 np
= rxi_SendConnectionAbort(conn
, np
, 1, 0);
3462 putConnection(conn
);
3463 MUTEX_EXIT(&conn
->conn_data_lock
);
3467 /* Check for connection-only requests (i.e. not call specific). */
3468 if (np
->header
.callNumber
== 0) {
3469 switch (np
->header
.type
) {
3470 case RX_PACKET_TYPE_ABORT
: {
3471 /* What if the supplied error is zero? */
3472 afs_int32 errcode
= ntohl(rx_GetInt32(np
, 0));
3473 dpf(("rxi_ReceivePacket ABORT rx_GetInt32 = %d\n", errcode
));
3474 rxi_ConnectionError(conn
, errcode
);
3475 putConnection(conn
);
3478 case RX_PACKET_TYPE_CHALLENGE
:
3479 tnp
= rxi_ReceiveChallengePacket(conn
, np
, 1);
3480 putConnection(conn
);
3482 case RX_PACKET_TYPE_RESPONSE
:
3483 tnp
= rxi_ReceiveResponsePacket(conn
, np
, 1);
3484 putConnection(conn
);
3486 case RX_PACKET_TYPE_PARAMS
:
3487 case RX_PACKET_TYPE_PARAMS
+ 1:
3488 case RX_PACKET_TYPE_PARAMS
+ 2:
3489 /* ignore these packet types for now */
3490 putConnection(conn
);
3494 /* Should not reach here, unless the peer is broken: send an
3496 rxi_ConnectionError(conn
, RX_PROTOCOL_ERROR
);
3497 MUTEX_ENTER(&conn
->conn_data_lock
);
3498 tnp
= rxi_SendConnectionAbort(conn
, np
, 1, 0);
3499 putConnection(conn
);
3500 MUTEX_EXIT(&conn
->conn_data_lock
);
3505 if (type
== RX_SERVER_CONNECTION
)
3506 call
= rxi_ReceiveServerCall(socket
, np
, conn
);
3508 call
= rxi_ReceiveClientCall(np
, conn
);
3511 putConnection(conn
);
3515 MUTEX_ASSERT(&call
->lock
);
3516 /* Set remote user defined status from packet */
3517 call
->remoteStatus
= np
->header
.userStatus
;
3519 /* Now do packet type-specific processing */
3520 switch (np
->header
.type
) {
3521 case RX_PACKET_TYPE_DATA
:
3522 /* If we're a client, and receiving a response, then all the packets
3523 * we transmitted packets are implicitly acknowledged. */
3524 if (type
== RX_CLIENT_CONNECTION
&& !opr_queue_IsEmpty(&call
->tq
))
3525 rxi_AckAllInTransmitQueue(call
);
3527 np
= rxi_ReceiveDataPacket(call
, np
, 1, socket
, host
, port
, tnop
,
3530 case RX_PACKET_TYPE_ACK
:
3531 /* Respond immediately to ack packets requesting acknowledgement
3533 if (np
->header
.flags
& RX_REQUEST_ACK
) {
3535 (void)rxi_SendCallAbort(call
, 0, 1, 0);
3537 (void)rxi_SendAck(call
, 0, np
->header
.serial
,
3538 RX_ACK_PING_RESPONSE
, 1);
3540 np
= rxi_ReceiveAckPacket(call
, np
, 1);
3542 case RX_PACKET_TYPE_ABORT
: {
3543 /* An abort packet: reset the call, passing the error up to the user. */
3544 /* What if error is zero? */
3545 /* What if the error is -1? the application will treat it as a timeout. */
3546 afs_int32 errdata
= ntohl(*(afs_int32
*) rx_DataOf(np
));
3547 dpf(("rxi_ReceivePacket ABORT rx_DataOf = %d\n", errdata
));
3548 rxi_CallError(call
, errdata
);
3549 MUTEX_EXIT(&call
->lock
);
3550 putConnection(conn
);
3551 return np
; /* xmitting; drop packet */
3553 case RX_PACKET_TYPE_BUSY
:
3554 /* Mostly ignore BUSY packets. We will update lastReceiveTime below,
3555 * so we don't think the endpoint is completely dead, but otherwise
3556 * just act as if we never saw anything. If all we get are BUSY packets
3557 * back, then we will eventually error out with RX_CALL_TIMEOUT if the
3558 * connection is configured with idle/hard timeouts. */
3561 case RX_PACKET_TYPE_ACKALL
:
3562 /* All packets acknowledged, so we can drop all packets previously
3563 * readied for sending */
3564 rxi_AckAllInTransmitQueue(call
);
3567 /* Should not reach here, unless the peer is broken: send an abort
3569 rxi_CallError(call
, RX_PROTOCOL_ERROR
);
3570 np
= rxi_SendCallAbort(call
, np
, 1, 0);
3573 /* Note when this last legitimate packet was received, for keep-alive
3574 * processing. Note, we delay getting the time until now in the hope that
3575 * the packet will be delivered to the user before any get time is required
3576 * (if not, then the time won't actually be re-evaluated here). */
3577 call
->lastReceiveTime
= clock_Sec();
3578 MUTEX_EXIT(&call
->lock
);
3579 putConnection(conn
);
3583 /* return true if this is an "interesting" connection from the point of view
3584 of someone trying to debug the system */
3586 rxi_IsConnInteresting(struct rx_connection
*aconn
)
3589 struct rx_call
*tcall
;
3591 if (aconn
->flags
& (RX_CONN_MAKECALL_WAITING
| RX_CONN_DESTROY_ME
))
3594 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
3595 tcall
= aconn
->call
[i
];
3597 if ((tcall
->state
== RX_STATE_PRECALL
)
3598 || (tcall
->state
== RX_STATE_ACTIVE
))
3600 if ((tcall
->app
.mode
== RX_MODE_SENDING
)
3601 || (tcall
->app
.mode
== RX_MODE_RECEIVING
))
3609 /* if this is one of the last few packets AND it wouldn't be used by the
3610 receiving call to immediately satisfy a read request, then drop it on
3611 the floor, since accepting it might prevent a lock-holding thread from
3612 making progress in its reading. If a call has been cleared while in
3613 the precall state then ignore all subsequent packets until the call
3614 is assigned to a thread. */
3617 TooLow(struct rx_packet
*ap
, struct rx_call
*acall
)
3621 MUTEX_ENTER(&rx_quota_mutex
);
3622 if (((ap
->header
.seq
!= 1) && (acall
->flags
& RX_CALL_CLEARED
)
3623 && (acall
->state
== RX_STATE_PRECALL
))
3624 || ((rx_nFreePackets
< rxi_dataQuota
+ 2)
3625 && !((ap
->header
.seq
< acall
->rnext
+ rx_initSendWindow
)
3626 && (acall
->flags
& RX_CALL_READER_WAIT
)))) {
3629 MUTEX_EXIT(&rx_quota_mutex
);
3635 * Clear the attach wait flag on a connection and proceed.
3637 * Any processing waiting for a connection to be attached should be
3638 * unblocked. We clear the flag and do any other needed tasks.
3641 * the conn to unmark waiting for attach
3643 * @pre conn's conn_data_lock must be locked before calling this function
3647 rxi_ConnClearAttachWait(struct rx_connection
*conn
)
3649 /* Indicate that rxi_CheckReachEvent is no longer running by
3650 * clearing the flag. Must be atomic under conn_data_lock to
3651 * avoid a new call slipping by: rxi_CheckConnReach holds
3652 * conn_data_lock while checking RX_CONN_ATTACHWAIT.
3654 conn
->flags
&= ~RX_CONN_ATTACHWAIT
;
3655 if (conn
->flags
& RX_CONN_NAT_PING
) {
3656 conn
->flags
&= ~RX_CONN_NAT_PING
;
3657 rxi_ScheduleNatKeepAliveEvent(conn
);
3662 rxi_CheckReachEvent(struct rxevent
*event
, void *arg1
, void *arg2
, int dummy
)
3664 struct rx_connection
*conn
= arg1
;
3665 struct rx_call
*acall
= arg2
;
3666 struct rx_call
*call
= acall
;
3667 struct clock when
, now
;
3670 MUTEX_ENTER(&conn
->conn_data_lock
);
3673 rxevent_Put(&conn
->checkReachEvent
);
3675 waiting
= conn
->flags
& RX_CONN_ATTACHWAIT
;
3677 putConnection(conn
);
3679 MUTEX_EXIT(&conn
->conn_data_lock
);
3683 MUTEX_ENTER(&conn
->conn_call_lock
);
3684 MUTEX_ENTER(&conn
->conn_data_lock
);
3685 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
3686 struct rx_call
*tc
= conn
->call
[i
];
3687 if (tc
&& tc
->state
== RX_STATE_PRECALL
) {
3693 rxi_ConnClearAttachWait(conn
);
3694 MUTEX_EXIT(&conn
->conn_data_lock
);
3695 MUTEX_EXIT(&conn
->conn_call_lock
);
3700 MUTEX_ENTER(&call
->lock
);
3701 rxi_SendAck(call
, NULL
, 0, RX_ACK_PING
, 0);
3703 MUTEX_EXIT(&call
->lock
);
3705 clock_GetTime(&now
);
3707 when
.sec
+= RX_CHECKREACH_TIMEOUT
;
3708 MUTEX_ENTER(&conn
->conn_data_lock
);
3709 if (!conn
->checkReachEvent
) {
3710 MUTEX_ENTER(&rx_refcnt_mutex
);
3712 MUTEX_EXIT(&rx_refcnt_mutex
);
3713 conn
->checkReachEvent
= rxevent_Post(&when
, &now
,
3714 rxi_CheckReachEvent
, conn
,
3717 MUTEX_EXIT(&conn
->conn_data_lock
);
3723 rxi_CheckConnReach(struct rx_connection
*conn
, struct rx_call
*call
)
3725 struct rx_service
*service
= conn
->service
;
3726 struct rx_peer
*peer
= conn
->peer
;
3727 afs_uint32 now
, lastReach
;
3729 if (service
->checkReach
== 0)
3733 MUTEX_ENTER(&peer
->peer_lock
);
3734 lastReach
= peer
->lastReachTime
;
3735 MUTEX_EXIT(&peer
->peer_lock
);
3736 if (now
- lastReach
< RX_CHECKREACH_TTL
)
3739 MUTEX_ENTER(&conn
->conn_data_lock
);
3740 if (conn
->flags
& RX_CONN_ATTACHWAIT
) {
3741 MUTEX_EXIT(&conn
->conn_data_lock
);
3744 conn
->flags
|= RX_CONN_ATTACHWAIT
;
3745 MUTEX_EXIT(&conn
->conn_data_lock
);
3746 if (!conn
->checkReachEvent
)
3747 rxi_CheckReachEvent(NULL
, conn
, call
, 0);
3752 /* try to attach call, if authentication is complete */
3754 TryAttach(struct rx_call
*acall
, osi_socket socket
,
3755 int *tnop
, struct rx_call
**newcallp
,
3758 struct rx_connection
*conn
= acall
->conn
;
3760 if (conn
->type
== RX_SERVER_CONNECTION
3761 && acall
->state
== RX_STATE_PRECALL
) {
3762 /* Don't attach until we have any req'd. authentication. */
3763 if (RXS_CheckAuthentication(conn
->securityObject
, conn
) == 0) {
3764 if (reachOverride
|| rxi_CheckConnReach(conn
, acall
) == 0)
3765 rxi_AttachServerProc(acall
, socket
, tnop
, newcallp
);
3766 /* Note: this does not necessarily succeed; there
3767 * may not any proc available
3770 rxi_ChallengeOn(acall
->conn
);
3775 /* A data packet has been received off the interface. This packet is
3776 * appropriate to the call (the call is in the right state, etc.). This
3777 * routine can return a packet to the caller, for re-use */
3779 static struct rx_packet
*
3780 rxi_ReceiveDataPacket(struct rx_call
*call
,
3781 struct rx_packet
*np
, int istack
,
3782 osi_socket socket
, afs_uint32 host
, u_short port
,
3783 int *tnop
, struct rx_call
**newcallp
)
3785 int ackNeeded
= 0; /* 0 means no, otherwise ack_reason */
3790 afs_uint32 serial
=0, flags
=0;
3792 struct rx_packet
*tnp
;
3793 if (rx_stats_active
)
3794 rx_atomic_inc(&rx_stats
.dataPacketsRead
);
3797 /* If there are no packet buffers, drop this new packet, unless we can find
3798 * packet buffers from inactive calls */
3800 && (rxi_OverQuota(RX_PACKET_CLASS_RECEIVE
) || TooLow(np
, call
))) {
3801 MUTEX_ENTER(&rx_freePktQ_lock
);
3802 rxi_NeedMorePackets
= TRUE
;
3803 MUTEX_EXIT(&rx_freePktQ_lock
);
3804 if (rx_stats_active
)
3805 rx_atomic_inc(&rx_stats
.noPacketBuffersOnRead
);
3806 rxi_calltrace(RX_TRACE_DROP
, call
);
3807 dpf(("packet %"AFS_PTR_FMT
" dropped on receipt - quota problems\n", np
));
3808 /* We used to clear the receive queue here, in an attempt to free
3809 * packets. However this is unsafe if the queue has received a
3810 * soft ACK for the final packet */
3811 rxi_PostDelayedAckEvent(call
, &rx_softAckDelay
);
3817 * New in AFS 3.5, if the RX_JUMBO_PACKET flag is set then this
3818 * packet is one of several packets transmitted as a single
3819 * datagram. Do not send any soft or hard acks until all packets
3820 * in a jumbogram have been processed. Send negative acks right away.
3822 for (isFirst
= 1, tnp
= NULL
; isFirst
|| tnp
; isFirst
= 0) {
3823 /* tnp is non-null when there are more packets in the
3824 * current jumbo gram */
3831 seq
= np
->header
.seq
;
3832 serial
= np
->header
.serial
;
3833 flags
= np
->header
.flags
;
3835 /* If the call is in an error state, send an abort message */
3837 return rxi_SendCallAbort(call
, np
, istack
, 0);
3839 /* The RX_JUMBO_PACKET is set in all but the last packet in each
3840 * AFS 3.5 jumbogram. */
3841 if (flags
& RX_JUMBO_PACKET
) {
3842 tnp
= rxi_SplitJumboPacket(np
, host
, port
, isFirst
);
3847 if (np
->header
.spare
!= 0) {
3848 MUTEX_ENTER(&call
->conn
->conn_data_lock
);
3849 call
->conn
->flags
|= RX_CONN_USING_PACKET_CKSUM
;
3850 MUTEX_EXIT(&call
->conn
->conn_data_lock
);
3853 /* The usual case is that this is the expected next packet */
3854 if (seq
== call
->rnext
) {
3856 /* Check to make sure it is not a duplicate of one already queued */
3857 if (!opr_queue_IsEmpty(&call
->rq
)
3858 && opr_queue_First(&call
->rq
, struct rx_packet
, entry
)->header
.seq
== seq
) {
3859 if (rx_stats_active
)
3860 rx_atomic_inc(&rx_stats
.dupPacketsRead
);
3861 dpf(("packet %"AFS_PTR_FMT
" dropped on receipt - duplicate\n", np
));
3862 rxi_CancelDelayedAckEvent(call
);
3863 np
= rxi_SendAck(call
, np
, serial
, RX_ACK_DUPLICATE
, istack
);
3869 /* It's the next packet. Stick it on the receive queue
3870 * for this call. Set newPackets to make sure we wake
3871 * the reader once all packets have been processed */
3872 #ifdef RX_TRACK_PACKETS
3873 np
->flags
|= RX_PKTFLAG_RQ
;
3875 opr_queue_Prepend(&call
->rq
, &np
->entry
);
3876 #ifdef RXDEBUG_PACKET
3878 #endif /* RXDEBUG_PACKET */
3880 np
= NULL
; /* We can't use this anymore */
3883 /* If an ack is requested then set a flag to make sure we
3884 * send an acknowledgement for this packet */
3885 if (flags
& RX_REQUEST_ACK
) {
3886 ackNeeded
= RX_ACK_REQUESTED
;
3889 /* Keep track of whether we have received the last packet */
3890 if (flags
& RX_LAST_PACKET
) {
3891 call
->flags
|= RX_CALL_HAVE_LAST
;
3895 /* Check whether we have all of the packets for this call */
3896 if (call
->flags
& RX_CALL_HAVE_LAST
) {
3897 afs_uint32 tseq
; /* temporary sequence number */
3898 struct opr_queue
*cursor
;
3900 for (tseq
= seq
, opr_queue_Scan(&call
->rq
, cursor
)) {
3901 struct rx_packet
*tp
;
3903 tp
= opr_queue_Entry(cursor
, struct rx_packet
, entry
);
3904 if (tseq
!= tp
->header
.seq
)
3906 if (tp
->header
.flags
& RX_LAST_PACKET
) {
3907 call
->flags
|= RX_CALL_RECEIVE_DONE
;
3914 /* Provide asynchronous notification for those who want it
3915 * (e.g. multi rx) */
3916 if (call
->arrivalProc
) {
3917 (*call
->arrivalProc
) (call
, call
->arrivalProcHandle
,
3918 call
->arrivalProcArg
);
3919 call
->arrivalProc
= (void (*)())0;
3922 /* Update last packet received */
3925 /* If there is no server process serving this call, grab
3926 * one, if available. We only need to do this once. If a
3927 * server thread is available, this thread becomes a server
3928 * thread and the server thread becomes a listener thread. */
3930 TryAttach(call
, socket
, tnop
, newcallp
, 0);
3933 /* This is not the expected next packet. */
3935 /* Determine whether this is a new or old packet, and if it's
3936 * a new one, whether it fits into the current receive window.
3937 * Also figure out whether the packet was delivered in sequence.
3938 * We use the prev variable to determine whether the new packet
3939 * is the successor of its immediate predecessor in the
3940 * receive queue, and the missing flag to determine whether
3941 * any of this packets predecessors are missing. */
3943 afs_uint32 prev
; /* "Previous packet" sequence number */
3944 struct opr_queue
*cursor
;
3945 int missing
; /* Are any predecessors missing? */
3947 /* If the new packet's sequence number has been sent to the
3948 * application already, then this is a duplicate */
3949 if (seq
< call
->rnext
) {
3950 if (rx_stats_active
)
3951 rx_atomic_inc(&rx_stats
.dupPacketsRead
);
3952 rxi_CancelDelayedAckEvent(call
);
3953 np
= rxi_SendAck(call
, np
, serial
, RX_ACK_DUPLICATE
, istack
);
3959 /* If the sequence number is greater than what can be
3960 * accomodated by the current window, then send a negative
3961 * acknowledge and drop the packet */
3962 if ((call
->rnext
+ call
->rwind
) <= seq
) {
3963 rxi_CancelDelayedAckEvent(call
);
3964 np
= rxi_SendAck(call
, np
, serial
, RX_ACK_EXCEEDS_WINDOW
,
3971 /* Look for the packet in the queue of old received packets */
3972 prev
= call
->rnext
- 1;
3974 for (opr_queue_Scan(&call
->rq
, cursor
)) {
3975 struct rx_packet
*tp
3976 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
3978 /*Check for duplicate packet */
3979 if (seq
== tp
->header
.seq
) {
3980 if (rx_stats_active
)
3981 rx_atomic_inc(&rx_stats
.dupPacketsRead
);
3982 rxi_CancelDelayedAckEvent(call
);
3983 np
= rxi_SendAck(call
, np
, serial
, RX_ACK_DUPLICATE
,
3989 /* If we find a higher sequence packet, break out and
3990 * insert the new packet here. */
3991 if (seq
< tp
->header
.seq
)
3993 /* Check for missing packet */
3994 if (tp
->header
.seq
!= prev
+ 1) {
3998 prev
= tp
->header
.seq
;
4001 /* Keep track of whether we have received the last packet. */
4002 if (flags
& RX_LAST_PACKET
) {
4003 call
->flags
|= RX_CALL_HAVE_LAST
;
4006 /* It's within the window: add it to the the receive queue.
4007 * tp is left by the previous loop either pointing at the
4008 * packet before which to insert the new packet, or at the
4009 * queue head if the queue is empty or the packet should be
4011 #ifdef RX_TRACK_PACKETS
4012 np
->flags
|= RX_PKTFLAG_RQ
;
4014 #ifdef RXDEBUG_PACKET
4016 #endif /* RXDEBUG_PACKET */
4017 opr_queue_InsertBefore(cursor
, &np
->entry
);
4021 /* Check whether we have all of the packets for this call */
4022 if ((call
->flags
& RX_CALL_HAVE_LAST
)
4023 && !(call
->flags
& RX_CALL_RECEIVE_DONE
)) {
4024 afs_uint32 tseq
; /* temporary sequence number */
4027 for (opr_queue_Scan(&call
->rq
, cursor
)) {
4028 struct rx_packet
*tp
4029 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
4030 if (tseq
!= tp
->header
.seq
)
4032 if (tp
->header
.flags
& RX_LAST_PACKET
) {
4033 call
->flags
|= RX_CALL_RECEIVE_DONE
;
4040 /* We need to send an ack of the packet is out of sequence,
4041 * or if an ack was requested by the peer. */
4042 if (seq
!= prev
+ 1 || missing
) {
4043 ackNeeded
= RX_ACK_OUT_OF_SEQUENCE
;
4044 } else if (flags
& RX_REQUEST_ACK
) {
4045 ackNeeded
= RX_ACK_REQUESTED
;
4048 /* Acknowledge the last packet for each call */
4049 if (flags
& RX_LAST_PACKET
) {
4060 * If the receiver is waiting for an iovec, fill the iovec
4061 * using the data from the receive queue */
4062 if (call
->flags
& RX_CALL_IOVEC_WAIT
) {
4063 didHardAck
= rxi_FillReadVec(call
, serial
);
4064 /* the call may have been aborted */
4073 /* Wakeup the reader if any */
4074 if ((call
->flags
& RX_CALL_READER_WAIT
)
4075 && (!(call
->flags
& RX_CALL_IOVEC_WAIT
) || !(call
->iovNBytes
)
4076 || (call
->iovNext
>= call
->iovMax
)
4077 || (call
->flags
& RX_CALL_RECEIVE_DONE
))) {
4078 call
->flags
&= ~RX_CALL_READER_WAIT
;
4079 #ifdef RX_ENABLE_LOCKS
4080 CV_BROADCAST(&call
->cv_rq
);
4082 osi_rxWakeup(&call
->rq
);
4088 * Send an ack when requested by the peer, or once every
4089 * rxi_SoftAckRate packets until the last packet has been
4090 * received. Always send a soft ack for the last packet in
4091 * the server's reply. */
4093 rxi_CancelDelayedAckEvent(call
);
4094 np
= rxi_SendAck(call
, np
, serial
, ackNeeded
, istack
);
4095 } else if (call
->nSoftAcks
> (u_short
) rxi_SoftAckRate
) {
4096 rxi_CancelDelayedAckEvent(call
);
4097 np
= rxi_SendAck(call
, np
, serial
, RX_ACK_IDLE
, istack
);
4098 } else if (call
->nSoftAcks
) {
4099 if (haveLast
&& !(flags
& RX_CLIENT_INITIATED
))
4100 rxi_PostDelayedAckEvent(call
, &rx_lastAckDelay
);
4102 rxi_PostDelayedAckEvent(call
, &rx_softAckDelay
);
4103 } else if (call
->flags
& RX_CALL_RECEIVE_DONE
) {
4104 rxi_CancelDelayedAckEvent(call
);
4111 rxi_UpdatePeerReach(struct rx_connection
*conn
, struct rx_call
*acall
)
4113 struct rx_peer
*peer
= conn
->peer
;
4115 MUTEX_ENTER(&peer
->peer_lock
);
4116 peer
->lastReachTime
= clock_Sec();
4117 MUTEX_EXIT(&peer
->peer_lock
);
4119 MUTEX_ENTER(&conn
->conn_data_lock
);
4120 if (conn
->flags
& RX_CONN_ATTACHWAIT
) {
4123 rxi_ConnClearAttachWait(conn
);
4124 MUTEX_EXIT(&conn
->conn_data_lock
);
4126 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
4127 struct rx_call
*call
= conn
->call
[i
];
4130 MUTEX_ENTER(&call
->lock
);
4131 /* tnop can be null if newcallp is null */
4132 TryAttach(call
, (osi_socket
) - 1, NULL
, NULL
, 1);
4134 MUTEX_EXIT(&call
->lock
);
4138 MUTEX_EXIT(&conn
->conn_data_lock
);
4141 #if defined(RXDEBUG) && defined(AFS_NT40_ENV)
4143 rx_ack_reason(int reason
)
4146 case RX_ACK_REQUESTED
:
4148 case RX_ACK_DUPLICATE
:
4150 case RX_ACK_OUT_OF_SEQUENCE
:
4152 case RX_ACK_EXCEEDS_WINDOW
:
4154 case RX_ACK_NOSPACE
:
4158 case RX_ACK_PING_RESPONSE
:
4171 /* The real smarts of the whole thing. */
4172 static struct rx_packet
*
4173 rxi_ReceiveAckPacket(struct rx_call
*call
, struct rx_packet
*np
,
4176 struct rx_ackPacket
*ap
;
4178 struct rx_packet
*tp
;
4179 struct rx_connection
*conn
= call
->conn
;
4180 struct rx_peer
*peer
= conn
->peer
;
4181 struct opr_queue
*cursor
;
4182 struct clock now
; /* Current time, for RTT calculations */
4190 int newAckCount
= 0;
4191 int maxDgramPackets
= 0; /* Set if peer supports AFS 3.5 jumbo datagrams */
4192 int pktsize
= 0; /* Set if we need to update the peer mtu */
4193 int conn_data_locked
= 0;
4195 if (rx_stats_active
)
4196 rx_atomic_inc(&rx_stats
.ackPacketsRead
);
4197 ap
= (struct rx_ackPacket
*)rx_DataOf(np
);
4198 nbytes
= rx_Contiguous(np
) - (int)((ap
->acks
) - (u_char
*) ap
);
4200 return np
; /* truncated ack packet */
4202 /* depends on ack packet struct */
4203 nAcks
= MIN((unsigned)nbytes
, (unsigned)ap
->nAcks
);
4204 first
= ntohl(ap
->firstPacket
);
4205 prev
= ntohl(ap
->previousPacket
);
4206 serial
= ntohl(ap
->serial
);
4209 * Ignore ack packets received out of order while protecting
4210 * against peers that set the previousPacket field to a packet
4211 * serial number instead of a sequence number.
4213 if (first
< call
->tfirst
||
4214 (first
== call
->tfirst
&& prev
< call
->tprev
&& prev
< call
->tfirst
4221 if (np
->header
.flags
& RX_SLOW_START_OK
) {
4222 call
->flags
|= RX_CALL_SLOW_START_OK
;
4225 if (ap
->reason
== RX_ACK_PING_RESPONSE
)
4226 rxi_UpdatePeerReach(conn
, call
);
4228 if (conn
->lastPacketSizeSeq
) {
4229 MUTEX_ENTER(&conn
->conn_data_lock
);
4230 conn_data_locked
= 1;
4231 if ((first
> conn
->lastPacketSizeSeq
) && (conn
->lastPacketSize
)) {
4232 pktsize
= conn
->lastPacketSize
;
4233 conn
->lastPacketSize
= conn
->lastPacketSizeSeq
= 0;
4236 if ((ap
->reason
== RX_ACK_PING_RESPONSE
) && (conn
->lastPingSizeSer
)) {
4237 if (!conn_data_locked
) {
4238 MUTEX_ENTER(&conn
->conn_data_lock
);
4239 conn_data_locked
= 1;
4241 if ((conn
->lastPingSizeSer
== serial
) && (conn
->lastPingSize
)) {
4242 /* process mtu ping ack */
4243 pktsize
= conn
->lastPingSize
;
4244 conn
->lastPingSizeSer
= conn
->lastPingSize
= 0;
4248 if (conn_data_locked
) {
4249 MUTEX_EXIT(&conn
->conn_data_lock
);
4250 conn_data_locked
= 0;
4254 if (rxdebug_active
) {
4258 len
= _snprintf(msg
, sizeof(msg
),
4259 "tid[%d] RACK: reason %s serial %u previous %u seq %u first %u acks %u space %u ",
4260 GetCurrentThreadId(), rx_ack_reason(ap
->reason
),
4261 ntohl(ap
->serial
), ntohl(ap
->previousPacket
),
4262 (unsigned int)np
->header
.seq
, ntohl(ap
->firstPacket
),
4263 ap
->nAcks
, ntohs(ap
->bufferSpace
) );
4267 for (offset
= 0; offset
< nAcks
&& len
< sizeof(msg
); offset
++)
4268 msg
[len
++] = (ap
->acks
[offset
] == RX_ACK_TYPE_NACK
? '-' : '*');
4272 OutputDebugString(msg
);
4274 #else /* AFS_NT40_ENV */
4277 "RACK: reason %x previous %u seq %u serial %u first %u",
4278 ap
->reason
, ntohl(ap
->previousPacket
),
4279 (unsigned int)np
->header
.seq
, (unsigned int)serial
,
4280 ntohl(ap
->firstPacket
));
4283 for (offset
= 0; offset
< nAcks
; offset
++)
4284 putc(ap
->acks
[offset
] == RX_ACK_TYPE_NACK
? '-' : '*',
4289 #endif /* AFS_NT40_ENV */
4292 MUTEX_ENTER(&peer
->peer_lock
);
4295 * Start somewhere. Can't assume we can send what we can receive,
4296 * but we are clearly receiving.
4298 if (!peer
->maxPacketSize
)
4299 peer
->maxPacketSize
= RX_MIN_PACKET_SIZE
- RX_HEADER_SIZE
;
4301 if (pktsize
> peer
->maxPacketSize
) {
4302 peer
->maxPacketSize
= pktsize
;
4303 if ((pktsize
+ RX_HEADER_SIZE
> peer
->ifMTU
)) {
4304 peer
->ifMTU
= pktsize
+ RX_HEADER_SIZE
;
4305 peer
->natMTU
= rxi_AdjustIfMTU(peer
->ifMTU
);
4306 rxi_ScheduleGrowMTUEvent(call
, 1);
4311 clock_GetTime(&now
);
4313 /* The transmit queue splits into 4 sections.
4315 * The first section is packets which have now been acknowledged
4316 * by a window size change in the ack. These have reached the
4317 * application layer, and may be discarded. These are packets
4318 * with sequence numbers < ap->firstPacket.
4320 * The second section is packets which have sequence numbers in
4321 * the range ap->firstPacket to ap->firstPacket + ap->nAcks. The
4322 * contents of the packet's ack array determines whether these
4323 * packets are acknowledged or not.
4325 * The third section is packets which fall above the range
4326 * addressed in the ack packet. These have not yet been received
4329 * The four section is packets which have not yet been transmitted.
4330 * These packets will have a header.serial of 0.
4333 /* First section - implicitly acknowledged packets that can be
4337 tp
= opr_queue_First(&call
->tq
, struct rx_packet
, entry
);
4338 while(!opr_queue_IsEnd(&call
->tq
, &tp
->entry
) && tp
->header
.seq
< first
) {
4339 struct rx_packet
*next
;
4341 next
= opr_queue_Next(&tp
->entry
, struct rx_packet
, entry
);
4342 call
->tfirst
= tp
->header
.seq
+ 1;
4344 if (!(tp
->flags
& RX_PKTFLAG_ACKED
)) {
4346 rxi_ComputeRoundTripTime(tp
, ap
, call
, peer
, &now
);
4349 #ifdef RX_ENABLE_LOCKS
4350 /* XXX Hack. Because we have to release the global call lock when sending
4351 * packets (osi_NetSend) we drop all acks while we're traversing the tq
4352 * in rxi_Start sending packets out because packets may move to the
4353 * freePacketQueue as result of being here! So we drop these packets until
4354 * we're safely out of the traversing. Really ugly!
4355 * To make it even uglier, if we're using fine grain locking, we can
4356 * set the ack bits in the packets and have rxi_Start remove the packets
4357 * when it's done transmitting.
4359 if (call
->flags
& RX_CALL_TQ_BUSY
) {
4360 tp
->flags
|= RX_PKTFLAG_ACKED
;
4361 call
->flags
|= RX_CALL_TQ_SOME_ACKED
;
4363 #endif /* RX_ENABLE_LOCKS */
4365 opr_queue_Remove(&tp
->entry
);
4366 #ifdef RX_TRACK_PACKETS
4367 tp
->flags
&= ~RX_PKTFLAG_TQ
;
4369 #ifdef RXDEBUG_PACKET
4371 #endif /* RXDEBUG_PACKET */
4372 rxi_FreePacket(tp
); /* rxi_FreePacket mustn't wake up anyone, preemptively. */
4377 /* N.B. we don't turn off any timers here. They'll go away by themselves, anyway */
4379 /* Second section of the queue - packets for which we are receiving
4382 * Go through the explicit acks/nacks and record the results in
4383 * the waiting packets. These are packets that can't be released
4384 * yet, even with a positive acknowledge. This positive
4385 * acknowledge only means the packet has been received by the
4386 * peer, not that it will be retained long enough to be sent to
4387 * the peer's upper level. In addition, reset the transmit timers
4388 * of any missing packets (those packets that must be missing
4389 * because this packet was out of sequence) */
4391 call
->nSoftAcked
= 0;
4393 while (!opr_queue_IsEnd(&call
->tq
, &tp
->entry
)
4394 && tp
->header
.seq
< first
+ nAcks
) {
4395 /* Set the acknowledge flag per packet based on the
4396 * information in the ack packet. An acknowlegded packet can
4397 * be downgraded when the server has discarded a packet it
4398 * soacked previously, or when an ack packet is received
4399 * out of sequence. */
4400 if (ap
->acks
[tp
->header
.seq
- first
] == RX_ACK_TYPE_ACK
) {
4401 if (!(tp
->flags
& RX_PKTFLAG_ACKED
)) {
4403 tp
->flags
|= RX_PKTFLAG_ACKED
;
4404 rxi_ComputeRoundTripTime(tp
, ap
, call
, peer
, &now
);
4411 } else /* RX_ACK_TYPE_NACK */ {
4412 tp
->flags
&= ~RX_PKTFLAG_ACKED
;
4416 tp
= opr_queue_Next(&tp
->entry
, struct rx_packet
, entry
);
4419 /* We don't need to take any action with the 3rd or 4th section in the
4420 * queue - they're not addressed by the contents of this ACK packet.
4423 /* if the ack packet has a receivelen field hanging off it,
4424 * update our state */
4425 if (np
->length
>= rx_AckDataSize(ap
->nAcks
) + 2 * sizeof(afs_int32
)) {
4428 /* If the ack packet has a "recommended" size that is less than
4429 * what I am using now, reduce my size to match */
4430 rx_packetread(np
, rx_AckDataSize(ap
->nAcks
) + (int)sizeof(afs_int32
),
4431 (int)sizeof(afs_int32
), &tSize
);
4432 tSize
= (afs_uint32
) ntohl(tSize
);
4433 if (tSize
> RX_MAX_PACKET_SIZE
)
4434 tSize
= RX_MAX_PACKET_SIZE
;
4435 if (tSize
< RX_MIN_PACKET_SIZE
)
4436 tSize
= RX_MIN_PACKET_SIZE
;
4437 peer
->natMTU
= rxi_AdjustIfMTU(MIN(tSize
, peer
->ifMTU
));
4439 /* Get the maximum packet size to send to this peer */
4440 rx_packetread(np
, rx_AckDataSize(ap
->nAcks
), (int)sizeof(afs_int32
),
4442 tSize
= (afs_uint32
) ntohl(tSize
);
4443 if (tSize
> RX_MAX_PACKET_SIZE
)
4444 tSize
= RX_MAX_PACKET_SIZE
;
4445 if (tSize
< RX_MIN_PACKET_SIZE
)
4446 tSize
= RX_MIN_PACKET_SIZE
;
4447 tSize
= (afs_uint32
) MIN(tSize
, rx_MyMaxSendSize
);
4448 tSize
= rxi_AdjustMaxMTU(peer
->natMTU
, tSize
);
4450 /* sanity check - peer might have restarted with different params.
4451 * If peer says "send less", dammit, send less... Peer should never
4452 * be unable to accept packets of the size that prior AFS versions would
4453 * send without asking. */
4454 if (peer
->maxMTU
!= tSize
) {
4455 if (peer
->maxMTU
> tSize
) /* possible cong., maxMTU decreased */
4457 peer
->maxMTU
= tSize
;
4458 peer
->MTU
= MIN(tSize
, peer
->MTU
);
4459 call
->MTU
= MIN(call
->MTU
, tSize
);
4462 if (np
->length
== rx_AckDataSize(ap
->nAcks
) + 3 * sizeof(afs_int32
)) {
4465 rx_AckDataSize(ap
->nAcks
) + 2 * (int)sizeof(afs_int32
),
4466 (int)sizeof(afs_int32
), &tSize
);
4467 tSize
= (afs_uint32
) ntohl(tSize
); /* peer's receive window, if it's */
4470 if (tSize
>= rx_maxSendWindow
)
4471 tSize
= rx_maxSendWindow
;
4472 if (tSize
< call
->twind
) { /* smaller than our send */
4473 call
->twind
= tSize
; /* window, we must send less... */
4474 call
->ssthresh
= MIN(call
->twind
, call
->ssthresh
);
4475 call
->conn
->twind
[call
->channel
] = call
->twind
;
4478 /* Only send jumbograms to 3.4a fileservers. 3.3a RX gets the
4479 * network MTU confused with the loopback MTU. Calculate the
4480 * maximum MTU here for use in the slow start code below.
4482 /* Did peer restart with older RX version? */
4483 if (peer
->maxDgramPackets
> 1) {
4484 peer
->maxDgramPackets
= 1;
4486 } else if (np
->length
>=
4487 rx_AckDataSize(ap
->nAcks
) + 4 * sizeof(afs_int32
)) {
4490 rx_AckDataSize(ap
->nAcks
) + 2 * (int)sizeof(afs_int32
),
4491 sizeof(afs_int32
), &tSize
);
4492 tSize
= (afs_uint32
) ntohl(tSize
);
4495 if (tSize
>= rx_maxSendWindow
)
4496 tSize
= rx_maxSendWindow
;
4498 * As of AFS 3.5 we set the send window to match the receive window.
4500 if (tSize
< call
->twind
) {
4501 call
->twind
= tSize
;
4502 call
->conn
->twind
[call
->channel
] = call
->twind
;
4503 call
->ssthresh
= MIN(call
->twind
, call
->ssthresh
);
4504 } else if (tSize
> call
->twind
) {
4505 call
->twind
= tSize
;
4506 call
->conn
->twind
[call
->channel
] = call
->twind
;
4510 * As of AFS 3.5, a jumbogram is more than one fixed size
4511 * packet transmitted in a single UDP datagram. If the remote
4512 * MTU is smaller than our local MTU then never send a datagram
4513 * larger than the natural MTU.
4516 rx_AckDataSize(ap
->nAcks
) + 3 * (int)sizeof(afs_int32
),
4517 (int)sizeof(afs_int32
), &tSize
);
4518 maxDgramPackets
= (afs_uint32
) ntohl(tSize
);
4519 maxDgramPackets
= MIN(maxDgramPackets
, rxi_nDgramPackets
);
4521 MIN(maxDgramPackets
, (int)(peer
->ifDgramPackets
));
4522 if (maxDgramPackets
> 1) {
4523 peer
->maxDgramPackets
= maxDgramPackets
;
4524 call
->MTU
= RX_JUMBOBUFFERSIZE
+ RX_HEADER_SIZE
;
4526 peer
->maxDgramPackets
= 1;
4527 call
->MTU
= peer
->natMTU
;
4529 } else if (peer
->maxDgramPackets
> 1) {
4530 /* Restarted with lower version of RX */
4531 peer
->maxDgramPackets
= 1;
4533 } else if (peer
->maxDgramPackets
> 1
4534 || peer
->maxMTU
!= OLD_MAX_PACKET_SIZE
) {
4535 /* Restarted with lower version of RX */
4536 peer
->maxMTU
= OLD_MAX_PACKET_SIZE
;
4537 peer
->natMTU
= OLD_MAX_PACKET_SIZE
;
4538 peer
->MTU
= OLD_MAX_PACKET_SIZE
;
4539 peer
->maxDgramPackets
= 1;
4540 peer
->nDgramPackets
= 1;
4542 call
->MTU
= OLD_MAX_PACKET_SIZE
;
4545 /* If the window has been extended by this acknowledge packet,
4546 * then wakeup a sender waiting in alloc for window space, or try
4547 * sending packets now, if he's been sitting on packets due to
4548 * lack of window space */
4549 if (call
->tnext
< (call
->tfirst
+ call
->twind
)) {
4550 #ifdef RX_ENABLE_LOCKS
4551 CV_SIGNAL(&call
->cv_twind
);
4553 if (call
->flags
& RX_CALL_WAIT_WINDOW_ALLOC
) {
4554 call
->flags
&= ~RX_CALL_WAIT_WINDOW_ALLOC
;
4555 osi_rxWakeup(&call
->twind
);
4558 if (call
->flags
& RX_CALL_WAIT_WINDOW_SEND
) {
4559 call
->flags
&= ~RX_CALL_WAIT_WINDOW_SEND
;
4565 * Calculate how many datagrams were successfully received after
4566 * the first missing packet and adjust the negative ack counter
4571 nNacked
= (nNacked
+ call
->nDgramPackets
- 1) / call
->nDgramPackets
;
4572 if (call
->nNacks
< nNacked
) {
4573 call
->nNacks
= nNacked
;
4576 call
->nAcks
+= newAckCount
;
4580 /* If the packet contained new acknowledgements, rather than just
4581 * being a duplicate of one we have previously seen, then we can restart
4584 if (newAckCount
> 0)
4585 rxi_rto_packet_acked(call
, istack
);
4587 if (call
->flags
& RX_CALL_FAST_RECOVER
) {
4588 if (newAckCount
== 0) {
4589 call
->cwind
= MIN((int)(call
->cwind
+ 1), rx_maxSendWindow
);
4591 call
->flags
&= ~RX_CALL_FAST_RECOVER
;
4592 call
->cwind
= call
->nextCwind
;
4593 call
->nextCwind
= 0;
4596 call
->nCwindAcks
= 0;
4597 } else if (nNacked
&& call
->nNacks
>= (u_short
) rx_nackThreshold
) {
4598 /* Three negative acks in a row trigger congestion recovery */
4599 call
->flags
|= RX_CALL_FAST_RECOVER
;
4600 call
->ssthresh
= MAX(4, MIN((int)call
->cwind
, (int)call
->twind
)) >> 1;
4602 MIN((int)(call
->ssthresh
+ rx_nackThreshold
), rx_maxSendWindow
);
4603 call
->nDgramPackets
= MAX(2, (int)call
->nDgramPackets
) >> 1;
4604 call
->nextCwind
= call
->ssthresh
;
4607 peer
->MTU
= call
->MTU
;
4608 peer
->cwind
= call
->nextCwind
;
4609 peer
->nDgramPackets
= call
->nDgramPackets
;
4611 call
->congestSeq
= peer
->congestSeq
;
4613 /* Reset the resend times on the packets that were nacked
4614 * so we will retransmit as soon as the window permits
4618 for (opr_queue_ScanBackwards(&call
->tq
, cursor
)) {
4619 struct rx_packet
*tp
=
4620 opr_queue_Entry(cursor
, struct rx_packet
, entry
);
4622 if (!(tp
->flags
& RX_PKTFLAG_ACKED
)) {
4623 tp
->flags
&= ~RX_PKTFLAG_SENT
;
4625 } else if (tp
->flags
& RX_PKTFLAG_ACKED
) {
4630 /* If cwind is smaller than ssthresh, then increase
4631 * the window one packet for each ack we receive (exponential
4633 * If cwind is greater than or equal to ssthresh then increase
4634 * the congestion window by one packet for each cwind acks we
4635 * receive (linear growth). */
4636 if (call
->cwind
< call
->ssthresh
) {
4638 MIN((int)call
->ssthresh
, (int)(call
->cwind
+ newAckCount
));
4639 call
->nCwindAcks
= 0;
4641 call
->nCwindAcks
+= newAckCount
;
4642 if (call
->nCwindAcks
>= call
->cwind
) {
4643 call
->nCwindAcks
= 0;
4644 call
->cwind
= MIN((int)(call
->cwind
+ 1), rx_maxSendWindow
);
4648 * If we have received several acknowledgements in a row then
4649 * it is time to increase the size of our datagrams
4651 if ((int)call
->nAcks
> rx_nDgramThreshold
) {
4652 if (peer
->maxDgramPackets
> 1) {
4653 if (call
->nDgramPackets
< peer
->maxDgramPackets
) {
4654 call
->nDgramPackets
++;
4656 call
->MTU
= RX_HEADER_SIZE
+ RX_JUMBOBUFFERSIZE
;
4657 } else if (call
->MTU
< peer
->maxMTU
) {
4658 /* don't upgrade if we can't handle it */
4659 if ((call
->nDgramPackets
== 1) && (call
->MTU
>= peer
->ifMTU
))
4660 call
->MTU
= peer
->ifMTU
;
4662 call
->MTU
+= peer
->natMTU
;
4663 call
->MTU
= MIN(call
->MTU
, peer
->maxMTU
);
4670 MUTEX_EXIT(&peer
->peer_lock
); /* rxi_Start will lock peer. */
4672 /* Servers need to hold the call until all response packets have
4673 * been acknowledged. Soft acks are good enough since clients
4674 * are not allowed to clear their receive queues. */
4675 if (call
->state
== RX_STATE_HOLD
4676 && call
->tfirst
+ call
->nSoftAcked
>= call
->tnext
) {
4677 call
->state
= RX_STATE_DALLY
;
4678 rxi_ClearTransmitQueue(call
, 0);
4679 rxi_CancelKeepAliveEvent(call
);
4680 } else if (!opr_queue_IsEmpty(&call
->tq
)) {
4681 rxi_Start(call
, istack
);
4687 * Schedule a connection abort to be sent after some delay.
4689 * @param[in] conn The connection to send the abort on.
4690 * @param[in] msec The number of milliseconds to wait before sending.
4692 * @pre conn_data_lock must be held
4695 rxi_SendConnectionAbortLater(struct rx_connection
*conn
, int msec
)
4697 struct clock when
, now
;
4701 if (!conn
->delayedAbortEvent
) {
4702 clock_GetTime(&now
);
4704 clock_Addmsec(&when
, msec
);
4705 conn
->delayedAbortEvent
=
4706 rxevent_Post(&when
, &now
, rxi_SendDelayedConnAbort
, conn
, NULL
, 0);
4710 /* Received a response to a challenge packet */
4711 static struct rx_packet
*
4712 rxi_ReceiveResponsePacket(struct rx_connection
*conn
,
4713 struct rx_packet
*np
, int istack
)
4717 /* Ignore the packet if we're the client */
4718 if (conn
->type
== RX_CLIENT_CONNECTION
)
4721 /* If already authenticated, ignore the packet (it's probably a retry) */
4722 if (RXS_CheckAuthentication(conn
->securityObject
, conn
) == 0)
4725 if (!conn
->securityChallengeSent
) {
4726 /* We've never sent out a challenge for this connection, so this
4727 * response cannot possibly be correct; ignore it. This can happen
4728 * if we sent a challenge to the client, then we were restarted, and
4729 * then the client sent us a response. If we ignore the response, the
4730 * client will eventually resend a data packet, causing us to send a
4731 * new challenge and the client to send a new response. */
4735 /* Otherwise, have the security object evaluate the response packet */
4736 error
= RXS_CheckResponse(conn
->securityObject
, conn
, np
);
4738 /* If the response is invalid, reset the connection, sending
4739 * an abort to the peer. Send the abort with a 1 second delay,
4740 * to avoid a peer hammering us by constantly recreating a
4741 * connection with bad credentials. */
4742 rxi_ConnectionError(conn
, error
);
4743 MUTEX_ENTER(&conn
->conn_data_lock
);
4744 rxi_SendConnectionAbortLater(conn
, 1000);
4745 MUTEX_EXIT(&conn
->conn_data_lock
);
4748 /* If the response is valid, any calls waiting to attach
4749 * servers can now do so */
4752 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
4753 struct rx_call
*call
= conn
->call
[i
];
4755 MUTEX_ENTER(&call
->lock
);
4756 if (call
->state
== RX_STATE_PRECALL
)
4757 rxi_AttachServerProc(call
, (osi_socket
) - 1, NULL
, NULL
);
4758 /* tnop can be null if newcallp is null */
4759 MUTEX_EXIT(&call
->lock
);
4763 /* Update the peer reachability information, just in case
4764 * some calls went into attach-wait while we were waiting
4765 * for authentication..
4767 rxi_UpdatePeerReach(conn
, NULL
);
4772 /* A client has received an authentication challenge: the security
4773 * object is asked to cough up a respectable response packet to send
4774 * back to the server. The server is responsible for retrying the
4775 * challenge if it fails to get a response. */
4777 static struct rx_packet
*
4778 rxi_ReceiveChallengePacket(struct rx_connection
*conn
,
4779 struct rx_packet
*np
, int istack
)
4783 /* Ignore the challenge if we're the server */
4784 if (conn
->type
== RX_SERVER_CONNECTION
)
4787 /* Ignore the challenge if the connection is otherwise idle; someone's
4788 * trying to use us as an oracle. */
4789 if (!rxi_HasActiveCalls(conn
))
4792 /* Send the security object the challenge packet. It is expected to fill
4793 * in the response. */
4794 error
= RXS_GetResponse(conn
->securityObject
, conn
, np
);
4796 /* If the security object is unable to return a valid response, reset the
4797 * connection and send an abort to the peer. Otherwise send the response
4798 * packet to the peer connection. */
4800 rxi_ConnectionError(conn
, error
);
4801 MUTEX_ENTER(&conn
->conn_data_lock
);
4802 np
= rxi_SendConnectionAbort(conn
, np
, istack
, 0);
4803 MUTEX_EXIT(&conn
->conn_data_lock
);
4805 np
= rxi_SendSpecial((struct rx_call
*)0, conn
, np
,
4806 RX_PACKET_TYPE_RESPONSE
, NULL
, -1, istack
);
4812 /* Find an available server process to service the current request in
4813 * the given call structure. If one isn't available, queue up this
4814 * call so it eventually gets one */
4816 rxi_AttachServerProc(struct rx_call
*call
,
4817 osi_socket socket
, int *tnop
,
4818 struct rx_call
**newcallp
)
4820 struct rx_serverQueueEntry
*sq
;
4821 struct rx_service
*service
= call
->conn
->service
;
4824 /* May already be attached */
4825 if (call
->state
== RX_STATE_ACTIVE
)
4828 MUTEX_ENTER(&rx_serverPool_lock
);
4830 haveQuota
= QuotaOK(service
);
4831 if ((!haveQuota
) || opr_queue_IsEmpty(&rx_idleServerQueue
)) {
4832 /* If there are no processes available to service this call,
4833 * put the call on the incoming call queue (unless it's
4834 * already on the queue).
4836 #ifdef RX_ENABLE_LOCKS
4838 ReturnToServerPool(service
);
4839 #endif /* RX_ENABLE_LOCKS */
4841 if (!(call
->flags
& RX_CALL_WAIT_PROC
)) {
4842 call
->flags
|= RX_CALL_WAIT_PROC
;
4843 rx_atomic_inc(&rx_nWaiting
);
4844 rx_atomic_inc(&rx_nWaited
);
4845 rxi_calltrace(RX_CALL_ARRIVAL
, call
);
4846 SET_CALL_QUEUE_LOCK(call
, &rx_serverPool_lock
);
4847 opr_queue_Append(&rx_incomingCallQueue
, &call
->entry
);
4850 sq
= opr_queue_Last(&rx_idleServerQueue
,
4851 struct rx_serverQueueEntry
, entry
);
4853 /* If hot threads are enabled, and both newcallp and sq->socketp
4854 * are non-null, then this thread will process the call, and the
4855 * idle server thread will start listening on this threads socket.
4857 opr_queue_Remove(&sq
->entry
);
4859 if (rx_enable_hot_thread
&& newcallp
&& sq
->socketp
) {
4862 *sq
->socketp
= socket
;
4863 clock_GetTime(&call
->startTime
);
4864 CALL_HOLD(call
, RX_CALL_REFCOUNT_BEGIN
);
4868 if (call
->flags
& RX_CALL_WAIT_PROC
) {
4869 /* Conservative: I don't think this should happen */
4870 call
->flags
&= ~RX_CALL_WAIT_PROC
;
4871 rx_atomic_dec(&rx_nWaiting
);
4872 if (opr_queue_IsOnQueue(&call
->entry
)) {
4873 opr_queue_Remove(&call
->entry
);
4876 call
->state
= RX_STATE_ACTIVE
;
4877 call
->app
.mode
= RX_MODE_RECEIVING
;
4878 #ifdef RX_KERNEL_TRACE
4880 int glockOwner
= ISAFS_GLOCK();
4883 afs_Trace3(afs_iclSetp
, CM_TRACE_WASHERE
, ICL_TYPE_STRING
,
4884 __FILE__
, ICL_TYPE_INT32
, __LINE__
, ICL_TYPE_POINTER
,
4890 if (call
->flags
& RX_CALL_CLEARED
) {
4891 /* send an ack now to start the packet flow up again */
4892 call
->flags
&= ~RX_CALL_CLEARED
;
4893 rxi_SendAck(call
, 0, 0, RX_ACK_DELAY
, 0);
4895 #ifdef RX_ENABLE_LOCKS
4898 service
->nRequestsRunning
++;
4899 MUTEX_ENTER(&rx_quota_mutex
);
4900 if (service
->nRequestsRunning
<= service
->minProcs
)
4903 MUTEX_EXIT(&rx_quota_mutex
);
4907 MUTEX_EXIT(&rx_serverPool_lock
);
4910 /* Delay the sending of an acknowledge event for a short while, while
4911 * a new call is being prepared (in the case of a client) or a reply
4912 * is being prepared (in the case of a server). Rather than sending
4913 * an ack packet, an ACKALL packet is sent. */
4915 rxi_AckAll(struct rx_call
*call
)
4917 rxi_SendSpecial(call
, call
->conn
, NULL
, RX_PACKET_TYPE_ACKALL
,
4919 call
->flags
|= RX_CALL_ACKALL_SENT
;
4923 rxi_SendDelayedAck(struct rxevent
*event
, void *arg1
, void *unused1
,
4926 struct rx_call
*call
= arg1
;
4927 #ifdef RX_ENABLE_LOCKS
4929 MUTEX_ENTER(&call
->lock
);
4930 if (event
== call
->delayedAckEvent
)
4931 rxevent_Put(&call
->delayedAckEvent
);
4932 CALL_RELE(call
, RX_CALL_REFCOUNT_DELAY
);
4934 (void)rxi_SendAck(call
, 0, 0, RX_ACK_DELAY
, 0);
4936 MUTEX_EXIT(&call
->lock
);
4937 #else /* RX_ENABLE_LOCKS */
4939 rxevent_Put(&call
->delayedAckEvent
);
4940 (void)rxi_SendAck(call
, 0, 0, RX_ACK_DELAY
, 0);
4941 #endif /* RX_ENABLE_LOCKS */
4944 #ifdef RX_ENABLE_LOCKS
4945 /* Set ack in all packets in transmit queue. rxi_Start will deal with
4946 * clearing them out.
4949 rxi_SetAcksInTransmitQueue(struct rx_call
*call
)
4951 struct opr_queue
*cursor
;
4954 for (opr_queue_Scan(&call
->tq
, cursor
)) {
4956 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
4958 p
->flags
|= RX_PKTFLAG_ACKED
;
4963 call
->flags
|= RX_CALL_TQ_CLEARME
;
4964 call
->flags
|= RX_CALL_TQ_SOME_ACKED
;
4967 rxi_rto_cancel(call
);
4969 call
->tfirst
= call
->tnext
;
4970 call
->nSoftAcked
= 0;
4972 if (call
->flags
& RX_CALL_FAST_RECOVER
) {
4973 call
->flags
&= ~RX_CALL_FAST_RECOVER
;
4974 call
->cwind
= call
->nextCwind
;
4975 call
->nextCwind
= 0;
4978 CV_SIGNAL(&call
->cv_twind
);
4980 #endif /* RX_ENABLE_LOCKS */
4983 * Acknowledge the whole transmit queue.
4985 * If we're running without locks, or the transmit queue isn't busy, then
4986 * we can just clear the queue now. Otherwise, we have to mark all of the
4987 * packets as acknowledged, and let rxi_Start clear it later on
4990 rxi_AckAllInTransmitQueue(struct rx_call
*call
)
4992 #ifdef RX_ENABLE_LOCKS
4993 if (call
->flags
& RX_CALL_TQ_BUSY
) {
4994 rxi_SetAcksInTransmitQueue(call
);
4998 rxi_ClearTransmitQueue(call
, 0);
5000 /* Clear out the transmit queue for the current call (all packets have
5001 * been received by peer) */
5003 rxi_ClearTransmitQueue(struct rx_call
*call
, int force
)
5005 #ifdef RX_ENABLE_LOCKS
5006 struct opr_queue
*cursor
;
5007 if (!force
&& (call
->flags
& RX_CALL_TQ_BUSY
)) {
5009 for (opr_queue_Scan(&call
->tq
, cursor
)) {
5011 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
5013 p
->flags
|= RX_PKTFLAG_ACKED
;
5017 call
->flags
|= RX_CALL_TQ_CLEARME
;
5018 call
->flags
|= RX_CALL_TQ_SOME_ACKED
;
5021 #endif /* RX_ENABLE_LOCKS */
5022 #ifdef RXDEBUG_PACKET
5024 #endif /* RXDEBUG_PACKET */
5025 rxi_FreePackets(0, &call
->tq
);
5026 rxi_WakeUpTransmitQueue(call
);
5027 #ifdef RX_ENABLE_LOCKS
5028 call
->flags
&= ~RX_CALL_TQ_CLEARME
;
5032 rxi_rto_cancel(call
);
5033 call
->tfirst
= call
->tnext
; /* implicitly acknowledge all data already sent */
5034 call
->nSoftAcked
= 0;
5036 if (call
->flags
& RX_CALL_FAST_RECOVER
) {
5037 call
->flags
&= ~RX_CALL_FAST_RECOVER
;
5038 call
->cwind
= call
->nextCwind
;
5040 #ifdef RX_ENABLE_LOCKS
5041 CV_SIGNAL(&call
->cv_twind
);
5043 osi_rxWakeup(&call
->twind
);
5048 rxi_ClearReceiveQueue(struct rx_call
*call
)
5050 if (!opr_queue_IsEmpty(&call
->rq
)) {
5053 count
= rxi_FreePackets(0, &call
->rq
);
5054 rx_packetReclaims
+= count
;
5055 #ifdef RXDEBUG_PACKET
5057 if ( call
->rqc
!= 0 )
5058 dpf(("rxi_ClearReceiveQueue call %"AFS_PTR_FMT
" rqc %u != 0\n", call
, call
->rqc
));
5060 call
->flags
&= ~(RX_CALL_RECEIVE_DONE
| RX_CALL_HAVE_LAST
);
5062 if (call
->state
== RX_STATE_PRECALL
) {
5063 call
->flags
|= RX_CALL_CLEARED
;
5067 /* Send an abort packet for the specified call */
5068 static struct rx_packet
*
5069 rxi_SendCallAbort(struct rx_call
*call
, struct rx_packet
*packet
,
5070 int istack
, int force
)
5073 struct clock when
, now
;
5078 /* Clients should never delay abort messages */
5079 if (rx_IsClientConn(call
->conn
))
5082 if (call
->abortCode
!= call
->error
) {
5083 call
->abortCode
= call
->error
;
5084 call
->abortCount
= 0;
5087 if (force
|| rxi_callAbortThreshhold
== 0
5088 || call
->abortCount
< rxi_callAbortThreshhold
) {
5089 rxi_CancelDelayedAbortEvent(call
);
5090 error
= htonl(call
->error
);
5093 rxi_SendSpecial(call
, call
->conn
, packet
, RX_PACKET_TYPE_ABORT
,
5094 (char *)&error
, sizeof(error
), istack
);
5095 } else if (!call
->delayedAbortEvent
) {
5096 clock_GetTime(&now
);
5098 clock_Addmsec(&when
, rxi_callAbortDelay
);
5099 CALL_HOLD(call
, RX_CALL_REFCOUNT_ABORT
);
5100 call
->delayedAbortEvent
=
5101 rxevent_Post(&when
, &now
, rxi_SendDelayedCallAbort
, call
, 0, 0);
5107 rxi_CancelDelayedAbortEvent(struct rx_call
*call
)
5109 if (call
->delayedAbortEvent
) {
5110 rxevent_Cancel(&call
->delayedAbortEvent
);
5111 CALL_RELE(call
, RX_CALL_REFCOUNT_ABORT
);
5115 /* Send an abort packet for the specified connection. Packet is an
5116 * optional pointer to a packet that can be used to send the abort.
5117 * Once the number of abort messages reaches the threshhold, an
5118 * event is scheduled to send the abort. Setting the force flag
5119 * overrides sending delayed abort messages.
5121 * NOTE: Called with conn_data_lock held. conn_data_lock is dropped
5122 * to send the abort packet.
5125 rxi_SendConnectionAbort(struct rx_connection
*conn
,
5126 struct rx_packet
*packet
, int istack
, int force
)
5133 /* Clients should never delay abort messages */
5134 if (rx_IsClientConn(conn
))
5137 if (force
|| rxi_connAbortThreshhold
== 0
5138 || conn
->abortCount
< rxi_connAbortThreshhold
) {
5140 rxevent_Cancel(&conn
->delayedAbortEvent
);
5141 error
= htonl(conn
->error
);
5143 MUTEX_EXIT(&conn
->conn_data_lock
);
5145 rxi_SendSpecial((struct rx_call
*)0, conn
, packet
,
5146 RX_PACKET_TYPE_ABORT
, (char *)&error
,
5147 sizeof(error
), istack
);
5148 MUTEX_ENTER(&conn
->conn_data_lock
);
5150 rxi_SendConnectionAbortLater(conn
, rxi_connAbortDelay
);
5155 /* Associate an error all of the calls owned by a connection. Called
5156 * with error non-zero. This is only for really fatal things, like
5157 * bad authentication responses. The connection itself is set in
5158 * error at this point, so that future packets received will be
5161 rxi_ConnectionError(struct rx_connection
*conn
,
5167 dpf(("rxi_ConnectionError conn %"AFS_PTR_FMT
" error %d\n", conn
, error
));
5169 MUTEX_ENTER(&conn
->conn_data_lock
);
5170 rxevent_Cancel(&conn
->challengeEvent
);
5171 rxevent_Cancel(&conn
->natKeepAliveEvent
);
5172 if (conn
->checkReachEvent
) {
5173 rxevent_Cancel(&conn
->checkReachEvent
);
5174 conn
->flags
&= ~(RX_CONN_ATTACHWAIT
|RX_CONN_NAT_PING
);
5175 putConnection(conn
);
5177 MUTEX_EXIT(&conn
->conn_data_lock
);
5178 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
5179 struct rx_call
*call
= conn
->call
[i
];
5181 MUTEX_ENTER(&call
->lock
);
5182 rxi_CallError(call
, error
);
5183 MUTEX_EXIT(&call
->lock
);
5186 conn
->error
= error
;
5187 if (rx_stats_active
)
5188 rx_atomic_inc(&rx_stats
.fatalErrors
);
5193 * Interrupt an in-progress call with the specified error and wakeup waiters.
5195 * @param[in] call The call to interrupt
5196 * @param[in] error The error code to send to the peer
5199 rx_InterruptCall(struct rx_call
*call
, afs_int32 error
)
5201 MUTEX_ENTER(&call
->lock
);
5202 rxi_CallError(call
, error
);
5203 rxi_SendCallAbort(call
, NULL
, 0, 1);
5204 MUTEX_EXIT(&call
->lock
);
5208 rxi_CallError(struct rx_call
*call
, afs_int32 error
)
5210 MUTEX_ASSERT(&call
->lock
);
5211 dpf(("rxi_CallError call %"AFS_PTR_FMT
" error %d call->error %d\n", call
, error
, call
->error
));
5213 error
= call
->error
;
5215 #ifdef RX_ENABLE_LOCKS
5216 if (!((call
->flags
& RX_CALL_TQ_BUSY
) || (call
->tqWaiters
> 0))) {
5217 rxi_ResetCall(call
, 0);
5220 rxi_ResetCall(call
, 0);
5222 call
->error
= error
;
5225 /* Reset various fields in a call structure, and wakeup waiting
5226 * processes. Some fields aren't changed: state & mode are not
5227 * touched (these must be set by the caller), and bufptr, nLeft, and
5228 * nFree are not reset, since these fields are manipulated by
5229 * unprotected macros, and may only be reset by non-interrupting code.
5233 rxi_ResetCall(struct rx_call
*call
, int newcall
)
5236 struct rx_peer
*peer
;
5237 struct rx_packet
*packet
;
5239 MUTEX_ASSERT(&call
->lock
);
5240 dpf(("rxi_ResetCall(call %"AFS_PTR_FMT
", newcall %d)\n", call
, newcall
));
5242 /* Notify anyone who is waiting for asynchronous packet arrival */
5243 if (call
->arrivalProc
) {
5244 (*call
->arrivalProc
) (call
, call
->arrivalProcHandle
,
5245 call
->arrivalProcArg
);
5246 call
->arrivalProc
= (void (*)())0;
5250 rxi_CancelGrowMTUEvent(call
);
5252 if (call
->delayedAbortEvent
) {
5253 rxi_CancelDelayedAbortEvent(call
);
5254 packet
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
);
5256 rxi_SendCallAbort(call
, packet
, 0, 1);
5257 rxi_FreePacket(packet
);
5262 * Update the peer with the congestion information in this call
5263 * so other calls on this connection can pick up where this call
5264 * left off. If the congestion sequence numbers don't match then
5265 * another call experienced a retransmission.
5267 peer
= call
->conn
->peer
;
5268 MUTEX_ENTER(&peer
->peer_lock
);
5270 if (call
->congestSeq
== peer
->congestSeq
) {
5271 peer
->cwind
= MAX(peer
->cwind
, call
->cwind
);
5272 peer
->MTU
= MAX(peer
->MTU
, call
->MTU
);
5273 peer
->nDgramPackets
=
5274 MAX(peer
->nDgramPackets
, call
->nDgramPackets
);
5277 call
->abortCode
= 0;
5278 call
->abortCount
= 0;
5280 if (peer
->maxDgramPackets
> 1) {
5281 call
->MTU
= RX_HEADER_SIZE
+ RX_JUMBOBUFFERSIZE
;
5283 call
->MTU
= peer
->MTU
;
5285 call
->cwind
= MIN((int)peer
->cwind
, (int)peer
->nDgramPackets
);
5286 call
->ssthresh
= rx_maxSendWindow
;
5287 call
->nDgramPackets
= peer
->nDgramPackets
;
5288 call
->congestSeq
= peer
->congestSeq
;
5289 call
->rtt
= peer
->rtt
;
5290 call
->rtt_dev
= peer
->rtt_dev
;
5291 clock_Zero(&call
->rto
);
5292 clock_Addmsec(&call
->rto
,
5293 MAX(((call
->rtt
>> 3) + call
->rtt_dev
), rx_minPeerTimeout
) + 200);
5294 MUTEX_EXIT(&peer
->peer_lock
);
5296 flags
= call
->flags
;
5297 rxi_WaitforTQBusy(call
);
5299 rxi_ClearTransmitQueue(call
, 1);
5300 if (call
->tqWaiters
|| (flags
& RX_CALL_TQ_WAIT
)) {
5301 dpf(("rcall %"AFS_PTR_FMT
" has %d waiters and flags %d\n", call
, call
->tqWaiters
, call
->flags
));
5305 rxi_ClearReceiveQueue(call
);
5306 /* why init the queue if you just emptied it? queue_Init(&call->rq); */
5310 call
->twind
= call
->conn
->twind
[call
->channel
];
5311 call
->rwind
= call
->conn
->rwind
[call
->channel
];
5312 call
->nSoftAcked
= 0;
5313 call
->nextCwind
= 0;
5316 call
->nCwindAcks
= 0;
5317 call
->nSoftAcks
= 0;
5318 call
->nHardAcks
= 0;
5320 call
->tfirst
= call
->rnext
= call
->tnext
= 1;
5323 call
->lastAcked
= 0;
5324 call
->localStatus
= call
->remoteStatus
= 0;
5326 if (flags
& RX_CALL_READER_WAIT
) {
5327 #ifdef RX_ENABLE_LOCKS
5328 CV_BROADCAST(&call
->cv_rq
);
5330 osi_rxWakeup(&call
->rq
);
5333 if (flags
& RX_CALL_WAIT_PACKETS
) {
5334 MUTEX_ENTER(&rx_freePktQ_lock
);
5335 rxi_PacketsUnWait(); /* XXX */
5336 MUTEX_EXIT(&rx_freePktQ_lock
);
5338 #ifdef RX_ENABLE_LOCKS
5339 CV_SIGNAL(&call
->cv_twind
);
5341 if (flags
& RX_CALL_WAIT_WINDOW_ALLOC
)
5342 osi_rxWakeup(&call
->twind
);
5345 if (flags
& RX_CALL_WAIT_PROC
) {
5346 rx_atomic_dec(&rx_nWaiting
);
5348 #ifdef RX_ENABLE_LOCKS
5349 /* The following ensures that we don't mess with any queue while some
5350 * other thread might also be doing so. The call_queue_lock field is
5351 * is only modified under the call lock. If the call is in the process
5352 * of being removed from a queue, the call is not locked until the
5353 * the queue lock is dropped and only then is the call_queue_lock field
5354 * zero'd out. So it's safe to lock the queue if call_queue_lock is set.
5355 * Note that any other routine which removes a call from a queue has to
5356 * obtain the queue lock before examing the queue and removing the call.
5358 if (call
->call_queue_lock
) {
5359 MUTEX_ENTER(call
->call_queue_lock
);
5360 if (opr_queue_IsOnQueue(&call
->entry
)) {
5361 opr_queue_Remove(&call
->entry
);
5363 MUTEX_EXIT(call
->call_queue_lock
);
5364 CLEAR_CALL_QUEUE_LOCK(call
);
5366 #else /* RX_ENABLE_LOCKS */
5367 if (opr_queue_IsOnQueue(&call
->entry
)) {
5368 opr_queue_Remove(&call
->entry
);
5370 #endif /* RX_ENABLE_LOCKS */
5372 rxi_CancelKeepAliveEvent(call
);
5373 rxi_CancelDelayedAckEvent(call
);
5376 /* Send an acknowledge for the indicated packet (seq,serial) of the
5377 * indicated call, for the indicated reason (reason). This
5378 * acknowledge will specifically acknowledge receiving the packet, and
5379 * will also specify which other packets for this call have been
5380 * received. This routine returns the packet that was used to the
5381 * caller. The caller is responsible for freeing it or re-using it.
5382 * This acknowledgement also returns the highest sequence number
5383 * actually read out by the higher level to the sender; the sender
5384 * promises to keep around packets that have not been read by the
5385 * higher level yet (unless, of course, the sender decides to abort
5386 * the call altogether). Any of p, seq, serial, pflags, or reason may
5387 * be set to zero without ill effect. That is, if they are zero, they
5388 * will not convey any information.
5389 * NOW there is a trailer field, after the ack where it will safely be
5390 * ignored by mundanes, which indicates the maximum size packet this
5391 * host can swallow. */
5393 struct rx_packet *optionalPacket; use to send ack (or null)
5394 int seq; Sequence number of the packet we are acking
5395 int serial; Serial number of the packet
5396 int pflags; Flags field from packet header
5397 int reason; Reason an acknowledge was prompted
5400 #define RX_ZEROS 1024
5401 static char rx_zeros
[RX_ZEROS
];
5404 rxi_SendAck(struct rx_call
*call
,
5405 struct rx_packet
*optionalPacket
, int serial
, int reason
,
5408 struct rx_ackPacket
*ap
;
5409 struct rx_packet
*p
;
5410 struct opr_queue
*cursor
;
5413 afs_uint32 padbytes
= 0;
5414 #ifdef RX_ENABLE_TSFPQ
5415 struct rx_ts_info_t
* rx_ts_info
;
5419 * Open the receive window once a thread starts reading packets
5421 if (call
->rnext
> 1) {
5422 call
->conn
->rwind
[call
->channel
] = call
->rwind
= rx_maxReceiveWindow
;
5425 /* Don't attempt to grow MTU if this is a critical ping */
5426 if (reason
== RX_ACK_MTU
) {
5427 /* keep track of per-call attempts, if we're over max, do in small
5428 * otherwise in larger? set a size to increment by, decrease
5431 if (call
->conn
->peer
->maxPacketSize
&&
5432 (call
->conn
->peer
->maxPacketSize
< OLD_MAX_PACKET_SIZE
5434 padbytes
= call
->conn
->peer
->maxPacketSize
+16;
5436 padbytes
= call
->conn
->peer
->maxMTU
+ 128;
5438 /* do always try a minimum size ping */
5439 padbytes
= MAX(padbytes
, RX_MIN_PACKET_SIZE
+RX_IPUDP_SIZE
+4);
5441 /* subtract the ack payload */
5442 padbytes
-= (rx_AckDataSize(call
->rwind
) + 4 * sizeof(afs_int32
));
5443 reason
= RX_ACK_PING
;
5446 call
->nHardAcks
= 0;
5447 call
->nSoftAcks
= 0;
5448 if (call
->rnext
> call
->lastAcked
)
5449 call
->lastAcked
= call
->rnext
;
5453 rx_computelen(p
, p
->length
); /* reset length, you never know */
5454 } /* where that's been... */
5455 #ifdef RX_ENABLE_TSFPQ
5457 RX_TS_INFO_GET(rx_ts_info
);
5458 if ((p
= rx_ts_info
->local_special_packet
)) {
5459 rx_computelen(p
, p
->length
);
5460 } else if ((p
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
))) {
5461 rx_ts_info
->local_special_packet
= p
;
5462 } else { /* We won't send the ack, but don't panic. */
5463 return optionalPacket
;
5467 else if (!(p
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
))) {
5468 /* We won't send the ack, but don't panic. */
5469 return optionalPacket
;
5474 rx_AckDataSize(call
->rwind
) + 4 * sizeof(afs_int32
) -
5477 if (rxi_AllocDataBuf(p
, templ
, RX_PACKET_CLASS_SPECIAL
) > 0) {
5478 #ifndef RX_ENABLE_TSFPQ
5479 if (!optionalPacket
)
5482 return optionalPacket
;
5484 templ
= rx_AckDataSize(call
->rwind
) + 2 * sizeof(afs_int32
);
5485 if (rx_Contiguous(p
) < templ
) {
5486 #ifndef RX_ENABLE_TSFPQ
5487 if (!optionalPacket
)
5490 return optionalPacket
;
5495 /* MTUXXX failing to send an ack is very serious. We should */
5496 /* try as hard as possible to send even a partial ack; it's */
5497 /* better than nothing. */
5498 ap
= (struct rx_ackPacket
*)rx_DataOf(p
);
5499 ap
->bufferSpace
= htonl(0); /* Something should go here, sometime */
5500 ap
->reason
= reason
;
5502 /* The skew computation used to be bogus, I think it's better now. */
5503 /* We should start paying attention to skew. XXX */
5504 ap
->serial
= htonl(serial
);
5505 ap
->maxSkew
= 0; /* used to be peer->inPacketSkew */
5508 * First packet not yet forwarded to reader. When ACKALL has been
5509 * sent the peer has been told that all received packets will be
5510 * delivered to the reader. The value 'rnext' is used internally
5511 * to refer to the next packet in the receive queue that must be
5512 * delivered to the reader. From the perspective of the peer it
5513 * already has so report the last sequence number plus one if there
5514 * are packets in the receive queue awaiting processing.
5516 if ((call
->flags
& RX_CALL_ACKALL_SENT
) &&
5517 !opr_queue_IsEmpty(&call
->rq
)) {
5518 ap
->firstPacket
= htonl(opr_queue_Last(&call
->rq
, struct rx_packet
, entry
)->header
.seq
+ 1);
5520 ap
->firstPacket
= htonl(call
->rnext
);
5522 ap
->previousPacket
= htonl(call
->rprev
); /* Previous packet received */
5524 /* No fear of running out of ack packet here because there can only
5525 * be at most one window full of unacknowledged packets. The window
5526 * size must be constrained to be less than the maximum ack size,
5527 * of course. Also, an ack should always fit into a single packet
5528 * -- it should not ever be fragmented. */
5530 for (opr_queue_Scan(&call
->rq
, cursor
)) {
5531 struct rx_packet
*rqp
5532 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
5534 if (!rqp
|| !call
->rq
.next
5535 || (rqp
->header
.seq
> (call
->rnext
+ call
->rwind
))) {
5536 #ifndef RX_ENABLE_TSFPQ
5537 if (!optionalPacket
)
5540 rxi_CallError(call
, RX_CALL_DEAD
);
5541 return optionalPacket
;
5544 while (rqp
->header
.seq
> call
->rnext
+ offset
)
5545 ap
->acks
[offset
++] = RX_ACK_TYPE_NACK
;
5546 ap
->acks
[offset
++] = RX_ACK_TYPE_ACK
;
5548 if ((offset
> (u_char
) rx_maxReceiveWindow
) || (offset
> call
->rwind
)) {
5549 #ifndef RX_ENABLE_TSFPQ
5550 if (!optionalPacket
)
5553 rxi_CallError(call
, RX_CALL_DEAD
);
5554 return optionalPacket
;
5560 p
->length
= rx_AckDataSize(offset
) + 4 * sizeof(afs_int32
);
5562 /* Must zero the 3 octets that rx_AckDataSize skips at the end of the
5565 rx_packetwrite(p
, rx_AckDataSize(offset
) - 3, 3, rx_zeros
);
5567 /* these are new for AFS 3.3 */
5568 templ
= rxi_AdjustMaxMTU(call
->conn
->peer
->ifMTU
, rx_maxReceiveSize
);
5569 templ
= htonl(templ
);
5570 rx_packetwrite(p
, rx_AckDataSize(offset
), sizeof(afs_int32
), &templ
);
5571 templ
= htonl(call
->conn
->peer
->ifMTU
);
5572 rx_packetwrite(p
, rx_AckDataSize(offset
) + sizeof(afs_int32
),
5573 sizeof(afs_int32
), &templ
);
5575 /* new for AFS 3.4 */
5576 templ
= htonl(call
->rwind
);
5577 rx_packetwrite(p
, rx_AckDataSize(offset
) + 2 * sizeof(afs_int32
),
5578 sizeof(afs_int32
), &templ
);
5580 /* new for AFS 3.5 */
5581 templ
= htonl(call
->conn
->peer
->ifDgramPackets
);
5582 rx_packetwrite(p
, rx_AckDataSize(offset
) + 3 * sizeof(afs_int32
),
5583 sizeof(afs_int32
), &templ
);
5585 p
->length
= rx_AckDataSize(offset
) + 4 * sizeof(afs_int32
);
5587 p
->header
.serviceId
= call
->conn
->serviceId
;
5588 p
->header
.cid
= (call
->conn
->cid
| call
->channel
);
5589 p
->header
.callNumber
= *call
->callNumber
;
5591 p
->header
.securityIndex
= call
->conn
->securityIndex
;
5592 p
->header
.epoch
= call
->conn
->epoch
;
5593 p
->header
.type
= RX_PACKET_TYPE_ACK
;
5594 p
->header
.flags
= RX_SLOW_START_OK
;
5595 if (reason
== RX_ACK_PING
)
5596 p
->header
.flags
|= RX_REQUEST_ACK
;
5598 while (padbytes
> 0) {
5599 if (padbytes
> RX_ZEROS
) {
5600 rx_packetwrite(p
, p
->length
, RX_ZEROS
, rx_zeros
);
5601 p
->length
+= RX_ZEROS
;
5602 padbytes
-= RX_ZEROS
;
5604 rx_packetwrite(p
, p
->length
, padbytes
, rx_zeros
);
5605 p
->length
+= padbytes
;
5610 if (call
->conn
->type
== RX_CLIENT_CONNECTION
)
5611 p
->header
.flags
|= RX_CLIENT_INITIATED
;
5615 if (rxdebug_active
) {
5619 len
= _snprintf(msg
, sizeof(msg
),
5620 "tid[%d] SACK: reason %s serial %u previous %u seq %u first %u acks %u space %u ",
5621 GetCurrentThreadId(), rx_ack_reason(ap
->reason
),
5622 ntohl(ap
->serial
), ntohl(ap
->previousPacket
),
5623 (unsigned int)p
->header
.seq
, ntohl(ap
->firstPacket
),
5624 ap
->nAcks
, ntohs(ap
->bufferSpace
) );
5628 for (offset
= 0; offset
< ap
->nAcks
&& len
< sizeof(msg
); offset
++)
5629 msg
[len
++] = (ap
->acks
[offset
] == RX_ACK_TYPE_NACK
? '-' : '*');
5633 OutputDebugString(msg
);
5635 #else /* AFS_NT40_ENV */
5637 fprintf(rx_Log
, "SACK: reason %x previous %u seq %u first %u ",
5638 ap
->reason
, ntohl(ap
->previousPacket
),
5639 (unsigned int)p
->header
.seq
, ntohl(ap
->firstPacket
));
5641 for (offset
= 0; offset
< ap
->nAcks
; offset
++)
5642 putc(ap
->acks
[offset
] == RX_ACK_TYPE_NACK
? '-' : '*',
5647 #endif /* AFS_NT40_ENV */
5650 int i
, nbytes
= p
->length
;
5652 for (i
= 1; i
< p
->niovecs
; i
++) { /* vec 0 is ALWAYS header */
5653 if (nbytes
<= p
->wirevec
[i
].iov_len
) {
5656 savelen
= p
->wirevec
[i
].iov_len
;
5658 p
->wirevec
[i
].iov_len
= nbytes
;
5660 rxi_Send(call
, p
, istack
);
5661 p
->wirevec
[i
].iov_len
= savelen
;
5665 nbytes
-= p
->wirevec
[i
].iov_len
;
5668 if (rx_stats_active
)
5669 rx_atomic_inc(&rx_stats
.ackPacketsSent
);
5670 #ifndef RX_ENABLE_TSFPQ
5671 if (!optionalPacket
)
5674 return optionalPacket
; /* Return packet for re-use by caller */
5678 struct rx_packet
**list
;
5683 /* Send all of the packets in the list in single datagram */
5685 rxi_SendList(struct rx_call
*call
, struct xmitlist
*xmit
,
5686 int istack
, int moreFlag
)
5692 struct rx_connection
*conn
= call
->conn
;
5693 struct rx_peer
*peer
= conn
->peer
;
5695 MUTEX_ENTER(&peer
->peer_lock
);
5696 peer
->nSent
+= xmit
->len
;
5697 if (xmit
->resending
)
5698 peer
->reSends
+= xmit
->len
;
5699 MUTEX_EXIT(&peer
->peer_lock
);
5701 if (rx_stats_active
) {
5702 if (xmit
->resending
)
5703 rx_atomic_add(&rx_stats
.dataPacketsReSent
, xmit
->len
);
5705 rx_atomic_add(&rx_stats
.dataPacketsSent
, xmit
->len
);
5708 clock_GetTime(&now
);
5710 if (xmit
->list
[xmit
->len
- 1]->header
.flags
& RX_LAST_PACKET
) {
5714 /* Set the packet flags and schedule the resend events */
5715 /* Only request an ack for the last packet in the list */
5716 for (i
= 0; i
< xmit
->len
; i
++) {
5717 struct rx_packet
*packet
= xmit
->list
[i
];
5719 /* Record the time sent */
5720 packet
->timeSent
= now
;
5721 packet
->flags
|= RX_PKTFLAG_SENT
;
5723 /* Ask for an ack on retransmitted packets, on every other packet
5724 * if the peer doesn't support slow start. Ask for an ack on every
5725 * packet until the congestion window reaches the ack rate. */
5726 if (packet
->header
.serial
) {
5729 packet
->firstSent
= now
;
5730 if (!lastPacket
&& (call
->cwind
<= (u_short
) (conn
->ackRate
+ 1)
5731 || (!(call
->flags
& RX_CALL_SLOW_START_OK
)
5732 && (packet
->header
.seq
& 1)))) {
5737 /* Tag this packet as not being the last in this group,
5738 * for the receiver's benefit */
5739 if (i
< xmit
->len
- 1 || moreFlag
) {
5740 packet
->header
.flags
|= RX_MORE_PACKETS
;
5745 xmit
->list
[xmit
->len
- 1]->header
.flags
|= RX_REQUEST_ACK
;
5748 /* Since we're about to send a data packet to the peer, it's
5749 * safe to nuke any scheduled end-of-packets ack */
5750 rxi_CancelDelayedAckEvent(call
);
5752 MUTEX_EXIT(&call
->lock
);
5753 CALL_HOLD(call
, RX_CALL_REFCOUNT_SEND
);
5754 if (xmit
->len
> 1) {
5755 rxi_SendPacketList(call
, conn
, xmit
->list
, xmit
->len
, istack
);
5757 rxi_SendPacket(call
, conn
, xmit
->list
[0], istack
);
5759 MUTEX_ENTER(&call
->lock
);
5760 CALL_RELE(call
, RX_CALL_REFCOUNT_SEND
);
5762 /* Tell the RTO calculation engine that we have sent a packet, and
5763 * if it was the last one */
5764 rxi_rto_packet_sent(call
, lastPacket
, istack
);
5766 /* Update last send time for this call (for keep-alive
5767 * processing), and for the connection (so that we can discover
5768 * idle connections) */
5769 conn
->lastSendTime
= call
->lastSendTime
= clock_Sec();
5772 /* When sending packets we need to follow these rules:
5773 * 1. Never send more than maxDgramPackets in a jumbogram.
5774 * 2. Never send a packet with more than two iovecs in a jumbogram.
5775 * 3. Never send a retransmitted packet in a jumbogram.
5776 * 4. Never send more than cwind/4 packets in a jumbogram
5777 * We always keep the last list we should have sent so we
5778 * can set the RX_MORE_PACKETS flags correctly.
5782 rxi_SendXmitList(struct rx_call
*call
, struct rx_packet
**list
, int len
,
5787 struct xmitlist working
;
5788 struct xmitlist last
;
5790 struct rx_peer
*peer
= call
->conn
->peer
;
5791 int morePackets
= 0;
5793 memset(&last
, 0, sizeof(struct xmitlist
));
5794 working
.list
= &list
[0];
5796 working
.resending
= 0;
5798 recovery
= call
->flags
& RX_CALL_FAST_RECOVER
;
5800 for (i
= 0; i
< len
; i
++) {
5801 /* Does the current packet force us to flush the current list? */
5803 && (list
[i
]->header
.serial
|| (list
[i
]->flags
& RX_PKTFLAG_ACKED
)
5804 || list
[i
]->length
> RX_JUMBOBUFFERSIZE
)) {
5806 /* This sends the 'last' list and then rolls the current working
5807 * set into the 'last' one, and resets the working set */
5810 rxi_SendList(call
, &last
, istack
, 1);
5811 /* If the call enters an error state stop sending, or if
5812 * we entered congestion recovery mode, stop sending */
5814 || (!recovery
&& (call
->flags
& RX_CALL_FAST_RECOVER
)))
5819 working
.resending
= 0;
5820 working
.list
= &list
[i
];
5822 /* Add the current packet to the list if it hasn't been acked.
5823 * Otherwise adjust the list pointer to skip the current packet. */
5824 if (!(list
[i
]->flags
& RX_PKTFLAG_ACKED
)) {
5827 if (list
[i
]->header
.serial
)
5828 working
.resending
= 1;
5830 /* Do we need to flush the list? */
5831 if (working
.len
>= (int)peer
->maxDgramPackets
5832 || working
.len
>= (int)call
->nDgramPackets
5833 || working
.len
>= (int)call
->cwind
5834 || list
[i
]->header
.serial
5835 || list
[i
]->length
!= RX_JUMBOBUFFERSIZE
) {
5837 rxi_SendList(call
, &last
, istack
, 1);
5838 /* If the call enters an error state stop sending, or if
5839 * we entered congestion recovery mode, stop sending */
5841 || (!recovery
&& (call
->flags
& RX_CALL_FAST_RECOVER
)))
5846 working
.resending
= 0;
5847 working
.list
= &list
[i
+ 1];
5850 if (working
.len
!= 0) {
5851 osi_Panic("rxi_SendList error");
5853 working
.list
= &list
[i
+ 1];
5857 /* Send the whole list when the call is in receive mode, when
5858 * the call is in eof mode, when we are in fast recovery mode,
5859 * and when we have the last packet */
5860 /* XXX - The accesses to app.mode aren't safe, as this may be called by
5861 * the listener or event threads
5863 if ((list
[len
- 1]->header
.flags
& RX_LAST_PACKET
)
5864 || (call
->flags
& RX_CALL_FLUSH
)
5865 || (call
->flags
& RX_CALL_FAST_RECOVER
)) {
5866 /* Check for the case where the current list contains
5867 * an acked packet. Since we always send retransmissions
5868 * in a separate packet, we only need to check the first
5869 * packet in the list */
5870 if (working
.len
> 0 && !(working
.list
[0]->flags
& RX_PKTFLAG_ACKED
)) {
5874 rxi_SendList(call
, &last
, istack
, morePackets
);
5875 /* If the call enters an error state stop sending, or if
5876 * we entered congestion recovery mode, stop sending */
5878 || (!recovery
&& (call
->flags
& RX_CALL_FAST_RECOVER
)))
5882 rxi_SendList(call
, &working
, istack
, 0);
5884 } else if (last
.len
> 0) {
5885 rxi_SendList(call
, &last
, istack
, 0);
5886 /* Packets which are in 'working' are not sent by this call */
5891 * Check if the peer for the given call is known to be dead
5893 * If the call's peer appears dead (it has encountered fatal network errors
5894 * since the call started) the call is killed with RX_CALL_DEAD if the call
5895 * is active. Otherwise, we do nothing.
5897 * @param[in] call The call to check
5900 * @retval 0 The call is fine, and we haven't done anything to the call
5901 * @retval nonzero The call's peer appears dead, and the call has been
5902 * terminated if it was active
5904 * @pre call->lock must be locked
5907 rxi_CheckPeerDead(struct rx_call
*call
)
5909 #ifdef AFS_RXERRQ_ENV
5912 if (call
->state
== RX_STATE_DALLY
) {
5916 peererrs
= rx_atomic_read(&call
->conn
->peer
->neterrs
);
5917 if (call
->neterr_gen
< peererrs
) {
5918 /* we have received network errors since this call started; kill
5920 if (call
->state
== RX_STATE_ACTIVE
) {
5921 rxi_CallError(call
, RX_CALL_DEAD
);
5925 if (call
->neterr_gen
> peererrs
) {
5926 /* someone has reset the number of peer errors; set the call error gen
5927 * so we can detect if more errors are encountered */
5928 call
->neterr_gen
= peererrs
;
5935 rxi_Resend(struct rxevent
*event
, void *arg0
, void *arg1
, int istack
)
5937 struct rx_call
*call
= arg0
;
5938 struct rx_peer
*peer
;
5939 struct opr_queue
*cursor
;
5940 struct clock maxTimeout
= { 60, 0 };
5942 MUTEX_ENTER(&call
->lock
);
5944 peer
= call
->conn
->peer
;
5946 /* Make sure that the event pointer is removed from the call
5947 * structure, since there is no longer a per-call retransmission
5949 if (event
== call
->resendEvent
) {
5950 CALL_RELE(call
, RX_CALL_REFCOUNT_RESEND
);
5951 rxevent_Put(&call
->resendEvent
);
5954 rxi_CheckPeerDead(call
);
5956 if (opr_queue_IsEmpty(&call
->tq
)) {
5957 /* Nothing to do. This means that we've been raced, and that an
5958 * ACK has come in between when we were triggered, and when we
5959 * actually got to run. */
5963 /* We're in loss recovery */
5964 call
->flags
|= RX_CALL_FAST_RECOVER
;
5966 /* Mark all of the pending packets in the queue as being lost */
5967 for (opr_queue_Scan(&call
->tq
, cursor
)) {
5968 struct rx_packet
*p
= opr_queue_Entry(cursor
, struct rx_packet
, entry
);
5969 if (!(p
->flags
& RX_PKTFLAG_ACKED
))
5970 p
->flags
&= ~RX_PKTFLAG_SENT
;
5973 /* We're resending, so we double the timeout of the call. This will be
5974 * dropped back down by the first successful ACK that we receive.
5976 * We apply a maximum value here of 60 seconds
5978 clock_Add(&call
->rto
, &call
->rto
);
5979 if (clock_Gt(&call
->rto
, &maxTimeout
))
5980 call
->rto
= maxTimeout
;
5982 /* Packet loss is most likely due to congestion, so drop our window size
5983 * and start again from the beginning */
5984 if (peer
->maxDgramPackets
>1) {
5985 call
->MTU
= RX_JUMBOBUFFERSIZE
+ RX_HEADER_SIZE
;
5986 call
->MTU
= MIN(peer
->natMTU
, peer
->maxMTU
);
5988 call
->ssthresh
= MAX(4, MIN((int)call
->cwind
, (int)call
->twind
)) >> 1;
5989 call
->nDgramPackets
= 1;
5991 call
->nextCwind
= 1;
5994 MUTEX_ENTER(&peer
->peer_lock
);
5995 peer
->MTU
= call
->MTU
;
5996 peer
->cwind
= call
->cwind
;
5997 peer
->nDgramPackets
= 1;
5999 call
->congestSeq
= peer
->congestSeq
;
6000 MUTEX_EXIT(&peer
->peer_lock
);
6002 rxi_Start(call
, istack
);
6005 MUTEX_EXIT(&call
->lock
);
6008 /* This routine is called when new packets are readied for
6009 * transmission and when retransmission may be necessary, or when the
6010 * transmission window or burst count are favourable. This should be
6011 * better optimized for new packets, the usual case, now that we've
6012 * got rid of queues of send packets. XXXXXXXXXXX */
6014 rxi_Start(struct rx_call
*call
, int istack
)
6016 struct opr_queue
*cursor
;
6017 #ifdef RX_ENABLE_LOCKS
6018 struct opr_queue
*store
;
6024 #ifdef RX_ENABLE_LOCKS
6025 if (rx_stats_active
)
6026 rx_atomic_inc(&rx_tq_debug
.rxi_start_in_error
);
6031 if (!opr_queue_IsEmpty(&call
->tq
)) { /* If we have anything to send */
6032 /* Send (or resend) any packets that need it, subject to
6033 * window restrictions and congestion burst control
6034 * restrictions. Ask for an ack on the last packet sent in
6035 * this burst. For now, we're relying upon the window being
6036 * considerably bigger than the largest number of packets that
6037 * are typically sent at once by one initial call to
6038 * rxi_Start. This is probably bogus (perhaps we should ask
6039 * for an ack when we're half way through the current
6040 * window?). Also, for non file transfer applications, this
6041 * may end up asking for an ack for every packet. Bogus. XXXX
6044 * But check whether we're here recursively, and let the other guy
6047 #ifdef RX_ENABLE_LOCKS
6048 if (!(call
->flags
& RX_CALL_TQ_BUSY
)) {
6049 call
->flags
|= RX_CALL_TQ_BUSY
;
6051 #endif /* RX_ENABLE_LOCKS */
6053 #ifdef RX_ENABLE_LOCKS
6054 call
->flags
&= ~RX_CALL_NEED_START
;
6055 #endif /* RX_ENABLE_LOCKS */
6057 maxXmitPackets
= MIN(call
->twind
, call
->cwind
);
6058 for (opr_queue_Scan(&call
->tq
, cursor
)) {
6060 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
6062 if (p
->flags
& RX_PKTFLAG_ACKED
) {
6063 /* Since we may block, don't trust this */
6064 if (rx_stats_active
)
6065 rx_atomic_inc(&rx_stats
.ignoreAckedPacket
);
6066 continue; /* Ignore this packet if it has been acknowledged */
6069 /* Turn off all flags except these ones, which are the same
6070 * on each transmission */
6071 p
->header
.flags
&= RX_PRESET_FLAGS
;
6073 if (p
->header
.seq
>=
6074 call
->tfirst
+ MIN((int)call
->twind
,
6075 (int)(call
->nSoftAcked
+
6077 call
->flags
|= RX_CALL_WAIT_WINDOW_SEND
; /* Wait for transmit window */
6078 /* Note: if we're waiting for more window space, we can
6079 * still send retransmits; hence we don't return here, but
6080 * break out to schedule a retransmit event */
6081 dpf(("call %d waiting for window (seq %d, twind %d, nSoftAcked %d, cwind %d)\n",
6082 *(call
->callNumber
), p
->header
.seq
, call
->twind
, call
->nSoftAcked
,
6087 /* Transmit the packet if it needs to be sent. */
6088 if (!(p
->flags
& RX_PKTFLAG_SENT
)) {
6089 if (nXmitPackets
== maxXmitPackets
) {
6090 rxi_SendXmitList(call
, call
->xmitList
,
6091 nXmitPackets
, istack
);
6094 dpf(("call %d xmit packet %"AFS_PTR_FMT
"\n",
6095 *(call
->callNumber
), p
));
6096 call
->xmitList
[nXmitPackets
++] = p
;
6098 } /* end of the queue_Scan */
6100 /* xmitList now hold pointers to all of the packets that are
6101 * ready to send. Now we loop to send the packets */
6102 if (nXmitPackets
> 0) {
6103 rxi_SendXmitList(call
, call
->xmitList
, nXmitPackets
,
6107 #ifdef RX_ENABLE_LOCKS
6109 /* We went into the error state while sending packets. Now is
6110 * the time to reset the call. This will also inform the using
6111 * process that the call is in an error state.
6113 if (rx_stats_active
)
6114 rx_atomic_inc(&rx_tq_debug
.rxi_start_aborted
);
6115 call
->flags
&= ~RX_CALL_TQ_BUSY
;
6116 rxi_WakeUpTransmitQueue(call
);
6117 rxi_CallError(call
, call
->error
);
6121 if (call
->flags
& RX_CALL_TQ_SOME_ACKED
) {
6123 call
->flags
&= ~RX_CALL_TQ_SOME_ACKED
;
6124 /* Some packets have received acks. If they all have, we can clear
6125 * the transmit queue.
6128 for (opr_queue_ScanSafe(&call
->tq
, cursor
, store
)) {
6130 = opr_queue_Entry(cursor
, struct rx_packet
, entry
);
6132 if (p
->header
.seq
< call
->tfirst
6133 && (p
->flags
& RX_PKTFLAG_ACKED
)) {
6134 opr_queue_Remove(&p
->entry
);
6135 #ifdef RX_TRACK_PACKETS
6136 p
->flags
&= ~RX_PKTFLAG_TQ
;
6138 #ifdef RXDEBUG_PACKET
6146 call
->flags
|= RX_CALL_TQ_CLEARME
;
6148 if (call
->flags
& RX_CALL_TQ_CLEARME
)
6149 rxi_ClearTransmitQueue(call
, 1);
6150 } while (call
->flags
& RX_CALL_NEED_START
);
6152 * TQ references no longer protected by this flag; they must remain
6153 * protected by the call lock.
6155 call
->flags
&= ~RX_CALL_TQ_BUSY
;
6156 rxi_WakeUpTransmitQueue(call
);
6158 call
->flags
|= RX_CALL_NEED_START
;
6160 #endif /* RX_ENABLE_LOCKS */
6162 rxi_rto_cancel(call
);
6166 /* Also adjusts the keep alive parameters for the call, to reflect
6167 * that we have just sent a packet (so keep alives aren't sent
6170 rxi_Send(struct rx_call
*call
, struct rx_packet
*p
,
6173 struct rx_connection
*conn
= call
->conn
;
6175 /* Stamp each packet with the user supplied status */
6176 p
->header
.userStatus
= call
->localStatus
;
6178 /* Allow the security object controlling this call's security to
6179 * make any last-minute changes to the packet */
6180 RXS_SendPacket(conn
->securityObject
, call
, p
);
6182 /* Since we're about to send SOME sort of packet to the peer, it's
6183 * safe to nuke any scheduled end-of-packets ack */
6184 rxi_CancelDelayedAckEvent(call
);
6186 /* Actually send the packet, filling in more connection-specific fields */
6187 MUTEX_EXIT(&call
->lock
);
6188 CALL_HOLD(call
, RX_CALL_REFCOUNT_SEND
);
6189 rxi_SendPacket(call
, conn
, p
, istack
);
6190 CALL_RELE(call
, RX_CALL_REFCOUNT_SEND
);
6191 MUTEX_ENTER(&call
->lock
);
6193 /* Update last send time for this call (for keep-alive
6194 * processing), and for the connection (so that we can discover
6195 * idle connections) */
6196 if ((p
->header
.type
!= RX_PACKET_TYPE_ACK
) ||
6197 (((struct rx_ackPacket
*)rx_DataOf(p
))->reason
== RX_ACK_PING
) ||
6198 (p
->length
<= (rx_AckDataSize(call
->rwind
) + 4 * sizeof(afs_int32
))))
6200 conn
->lastSendTime
= call
->lastSendTime
= clock_Sec();
6204 /* Check if a call needs to be destroyed. Called by keep-alive code to ensure
6205 * that things are fine. Also called periodically to guarantee that nothing
6206 * falls through the cracks (e.g. (error + dally) connections have keepalive
6207 * turned off. Returns 0 if conn is well, -1 otherwise. If otherwise, call
6209 * haveCTLock Set if calling from rxi_ReapConnections
6212 rxi_CheckCall(struct rx_call
*call
, int haveCTLock
)
6214 struct rx_connection
*conn
= call
->conn
;
6216 afs_uint32 deadTime
, idleDeadTime
= 0, hardDeadTime
= 0;
6217 afs_uint32 fudgeFactor
;
6220 int idle_timeout
= 0;
6221 afs_int32 clock_diff
= 0;
6223 if (rxi_CheckPeerDead(call
)) {
6229 /* Large swings in the clock can have a significant impact on
6230 * the performance of RX call processing. Forward clock shifts
6231 * will result in premature event triggering or timeouts.
6232 * Backward shifts can result in calls not completing until
6233 * the clock catches up with the original start clock value.
6235 * If a backward clock shift of more than five minutes is noticed,
6236 * just fail the call.
6238 if (now
< call
->lastSendTime
)
6239 clock_diff
= call
->lastSendTime
- now
;
6240 if (now
< call
->startWait
)
6241 clock_diff
= MAX(clock_diff
, call
->startWait
- now
);
6242 if (now
< call
->lastReceiveTime
)
6243 clock_diff
= MAX(clock_diff
, call
->lastReceiveTime
- now
);
6244 if (clock_diff
> 5 * 60)
6246 if (call
->state
== RX_STATE_ACTIVE
)
6247 rxi_CallError(call
, RX_CALL_TIMEOUT
);
6251 #ifdef RX_ENABLE_LOCKS
6252 if (call
->flags
& RX_CALL_TQ_BUSY
) {
6253 /* Call is active and will be reset by rxi_Start if it's
6254 * in an error state.
6259 /* RTT + 8*MDEV, rounded up to the next second. */
6260 fudgeFactor
= (((afs_uint32
) call
->rtt
>> 3) +
6261 ((afs_uint32
) call
->rtt_dev
<< 1) + 1023) >> 10;
6263 deadTime
= conn
->secondsUntilDead
+ fudgeFactor
;
6264 /* These are computed to the second (+- 1 second). But that's
6265 * good enough for these values, which should be a significant
6266 * number of seconds. */
6267 if (now
> (call
->lastReceiveTime
+ deadTime
)) {
6268 if (call
->state
== RX_STATE_ACTIVE
) {
6269 cerror
= RX_CALL_DEAD
;
6272 #ifdef RX_ENABLE_LOCKS
6273 /* Cancel pending events */
6274 rxi_CancelDelayedAckEvent(call
);
6275 rxi_rto_cancel(call
);
6276 rxi_CancelKeepAliveEvent(call
);
6277 rxi_CancelGrowMTUEvent(call
);
6278 MUTEX_ENTER(&rx_refcnt_mutex
);
6279 /* if rxi_FreeCall returns 1 it has freed the call */
6280 if (call
->refCount
== 0 &&
6281 rxi_FreeCall(call
, haveCTLock
))
6283 MUTEX_EXIT(&rx_refcnt_mutex
);
6286 MUTEX_EXIT(&rx_refcnt_mutex
);
6288 #else /* RX_ENABLE_LOCKS */
6289 rxi_FreeCall(call
, 0);
6291 #endif /* RX_ENABLE_LOCKS */
6293 /* Non-active calls are destroyed if they are not responding
6294 * to pings; active calls are simply flagged in error, so the
6295 * attached process can die reasonably gracefully. */
6298 if (conn
->idleDeadTime
) {
6299 idleDeadTime
= conn
->idleDeadTime
+ fudgeFactor
;
6303 /* see if we have a non-activity timeout */
6304 if (call
->startWait
&& ((call
->startWait
+ idleDeadTime
) < now
)) {
6305 if (call
->state
== RX_STATE_ACTIVE
) {
6306 cerror
= RX_CALL_TIMEOUT
;
6312 if (conn
->hardDeadTime
) {
6313 hardDeadTime
= conn
->hardDeadTime
+ fudgeFactor
;
6316 /* see if we have a hard timeout */
6318 && (now
> (hardDeadTime
+ call
->startTime
.sec
))) {
6319 if (call
->state
== RX_STATE_ACTIVE
)
6320 rxi_CallError(call
, RX_CALL_TIMEOUT
);
6325 if (conn
->msgsizeRetryErr
&& cerror
!= RX_CALL_TIMEOUT
&& !idle_timeout
&&
6326 call
->lastReceiveTime
) {
6327 int oldMTU
= conn
->peer
->ifMTU
;
6329 /* If we thought we could send more, perhaps things got worse.
6330 * Shrink by 128 bytes and try again. */
6331 if (conn
->peer
->maxPacketSize
< conn
->lastPacketSize
)
6332 /* maxPacketSize will be cleared in rxi_SetPeerMtu */
6333 newmtu
= MAX(conn
->peer
->maxPacketSize
+ RX_HEADER_SIZE
,
6334 conn
->lastPacketSize
- 128 + RX_HEADER_SIZE
);
6336 newmtu
= conn
->lastPacketSize
- 128 + RX_HEADER_SIZE
;
6338 /* minimum capped in SetPeerMtu */
6339 rxi_SetPeerMtu(conn
->peer
, 0, 0, newmtu
);
6342 conn
->lastPacketSize
= conn
->lastPacketSizeSeq
= 0;
6344 /* needed so ResetCall doesn't clobber us. */
6345 call
->MTU
= conn
->peer
->ifMTU
;
6347 /* if we never succeeded, let the error pass out as-is */
6348 if (conn
->peer
->maxPacketSize
&& oldMTU
!= conn
->peer
->ifMTU
)
6349 cerror
= conn
->msgsizeRetryErr
;
6352 rxi_CallError(call
, cerror
);
6357 rxi_NatKeepAliveEvent(struct rxevent
*event
, void *arg1
,
6358 void *dummy
, int dummy2
)
6360 struct rx_connection
*conn
= arg1
;
6361 struct rx_header theader
;
6362 char tbuffer
[1 + sizeof(struct rx_header
)];
6363 struct sockaddr_in taddr
;
6366 struct iovec tmpiov
[2];
6369 RX_CLIENT_CONNECTION
? rx_socket
: conn
->service
->socket
);
6372 tp
= &tbuffer
[sizeof(struct rx_header
)];
6373 taddr
.sin_family
= AF_INET
;
6374 taddr
.sin_port
= rx_PortOf(rx_PeerOf(conn
));
6375 taddr
.sin_addr
.s_addr
= rx_HostOf(rx_PeerOf(conn
));
6376 memset(&taddr
.sin_zero
, 0, sizeof(taddr
.sin_zero
));
6377 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
6378 taddr
.sin_len
= sizeof(struct sockaddr_in
);
6380 memset(&theader
, 0, sizeof(theader
));
6381 theader
.epoch
= htonl(999);
6383 theader
.callNumber
= 0;
6386 theader
.type
= RX_PACKET_TYPE_VERSION
;
6387 theader
.flags
= RX_LAST_PACKET
;
6388 theader
.serviceId
= 0;
6390 memcpy(tbuffer
, &theader
, sizeof(theader
));
6391 memcpy(tp
, &a
, sizeof(a
));
6392 tmpiov
[0].iov_base
= tbuffer
;
6393 tmpiov
[0].iov_len
= 1 + sizeof(struct rx_header
);
6395 osi_NetSend(socket
, &taddr
, tmpiov
, 1, 1 + sizeof(struct rx_header
), 1);
6397 MUTEX_ENTER(&conn
->conn_data_lock
);
6398 MUTEX_ENTER(&rx_refcnt_mutex
);
6399 /* Only reschedule ourselves if the connection would not be destroyed */
6400 if (conn
->refCount
<= 1) {
6401 rxevent_Put(&conn
->natKeepAliveEvent
);
6402 MUTEX_EXIT(&rx_refcnt_mutex
);
6403 MUTEX_EXIT(&conn
->conn_data_lock
);
6404 rx_DestroyConnection(conn
); /* drop the reference for this */
6406 conn
->refCount
--; /* drop the reference for this */
6407 MUTEX_EXIT(&rx_refcnt_mutex
);
6408 rxevent_Put(&conn
->natKeepAliveEvent
);
6409 rxi_ScheduleNatKeepAliveEvent(conn
);
6410 MUTEX_EXIT(&conn
->conn_data_lock
);
6415 rxi_ScheduleNatKeepAliveEvent(struct rx_connection
*conn
)
6417 if (!conn
->natKeepAliveEvent
&& conn
->secondsUntilNatPing
) {
6418 struct clock when
, now
;
6419 clock_GetTime(&now
);
6421 when
.sec
+= conn
->secondsUntilNatPing
;
6422 MUTEX_ENTER(&rx_refcnt_mutex
);
6423 conn
->refCount
++; /* hold a reference for this */
6424 MUTEX_EXIT(&rx_refcnt_mutex
);
6425 conn
->natKeepAliveEvent
=
6426 rxevent_Post(&when
, &now
, rxi_NatKeepAliveEvent
, conn
, NULL
, 0);
6431 rx_SetConnSecondsUntilNatPing(struct rx_connection
*conn
, afs_int32 seconds
)
6433 MUTEX_ENTER(&conn
->conn_data_lock
);
6434 conn
->secondsUntilNatPing
= seconds
;
6436 if (!(conn
->flags
& RX_CONN_ATTACHWAIT
))
6437 rxi_ScheduleNatKeepAliveEvent(conn
);
6439 conn
->flags
|= RX_CONN_NAT_PING
;
6441 MUTEX_EXIT(&conn
->conn_data_lock
);
6444 /* When a call is in progress, this routine is called occasionally to
6445 * make sure that some traffic has arrived (or been sent to) the peer.
6446 * If nothing has arrived in a reasonable amount of time, the call is
6447 * declared dead; if nothing has been sent for a while, we send a
6448 * keep-alive packet (if we're actually trying to keep the call alive)
6451 rxi_KeepAliveEvent(struct rxevent
*event
, void *arg1
, void *dummy
,
6454 struct rx_call
*call
= arg1
;
6455 struct rx_connection
*conn
;
6458 CALL_RELE(call
, RX_CALL_REFCOUNT_ALIVE
);
6459 MUTEX_ENTER(&call
->lock
);
6461 if (event
== call
->keepAliveEvent
)
6462 rxevent_Put(&call
->keepAliveEvent
);
6466 if (rxi_CheckCall(call
, 0)) {
6467 MUTEX_EXIT(&call
->lock
);
6471 /* Don't try to keep alive dallying calls */
6472 if (call
->state
== RX_STATE_DALLY
) {
6473 MUTEX_EXIT(&call
->lock
);
6478 if ((now
- call
->lastSendTime
) > conn
->secondsUntilPing
) {
6479 /* Don't try to send keepalives if there is unacknowledged data */
6480 /* the rexmit code should be good enough, this little hack
6481 * doesn't quite work XXX */
6482 (void)rxi_SendAck(call
, NULL
, 0, RX_ACK_PING
, 0);
6484 rxi_ScheduleKeepAliveEvent(call
);
6485 MUTEX_EXIT(&call
->lock
);
6488 /* Does what's on the nameplate. */
6490 rxi_GrowMTUEvent(struct rxevent
*event
, void *arg1
, void *dummy
, int dummy2
)
6492 struct rx_call
*call
= arg1
;
6493 struct rx_connection
*conn
;
6495 CALL_RELE(call
, RX_CALL_REFCOUNT_MTU
);
6496 MUTEX_ENTER(&call
->lock
);
6498 if (event
== call
->growMTUEvent
)
6499 rxevent_Put(&call
->growMTUEvent
);
6501 if (rxi_CheckCall(call
, 0)) {
6502 MUTEX_EXIT(&call
->lock
);
6506 /* Don't bother with dallying calls */
6507 if (call
->state
== RX_STATE_DALLY
) {
6508 MUTEX_EXIT(&call
->lock
);
6515 * keep being scheduled, just don't do anything if we're at peak,
6516 * or we're not set up to be properly handled (idle timeout required)
6518 if ((conn
->peer
->maxPacketSize
!= 0) &&
6519 (conn
->peer
->natMTU
< RX_MAX_PACKET_SIZE
) &&
6521 (void)rxi_SendAck(call
, NULL
, 0, RX_ACK_MTU
, 0);
6522 rxi_ScheduleGrowMTUEvent(call
, 0);
6523 MUTEX_EXIT(&call
->lock
);
6527 rxi_ScheduleKeepAliveEvent(struct rx_call
*call
)
6529 if (!call
->keepAliveEvent
) {
6530 struct clock when
, now
;
6531 clock_GetTime(&now
);
6533 when
.sec
+= call
->conn
->secondsUntilPing
;
6534 CALL_HOLD(call
, RX_CALL_REFCOUNT_ALIVE
);
6535 call
->keepAliveEvent
=
6536 rxevent_Post(&when
, &now
, rxi_KeepAliveEvent
, call
, NULL
, 0);
6541 rxi_CancelKeepAliveEvent(struct rx_call
*call
) {
6542 if (call
->keepAliveEvent
) {
6543 rxevent_Cancel(&call
->keepAliveEvent
);
6544 CALL_RELE(call
, RX_CALL_REFCOUNT_ALIVE
);
6549 rxi_ScheduleGrowMTUEvent(struct rx_call
*call
, int secs
)
6551 if (!call
->growMTUEvent
) {
6552 struct clock when
, now
;
6554 clock_GetTime(&now
);
6557 if (call
->conn
->secondsUntilPing
)
6558 secs
= (6*call
->conn
->secondsUntilPing
)-1;
6560 if (call
->conn
->secondsUntilDead
)
6561 secs
= MIN(secs
, (call
->conn
->secondsUntilDead
-1));
6565 CALL_HOLD(call
, RX_CALL_REFCOUNT_MTU
);
6566 call
->growMTUEvent
=
6567 rxevent_Post(&when
, &now
, rxi_GrowMTUEvent
, call
, NULL
, 0);
6572 rxi_CancelGrowMTUEvent(struct rx_call
*call
)
6574 if (call
->growMTUEvent
) {
6575 rxevent_Cancel(&call
->growMTUEvent
);
6576 CALL_RELE(call
, RX_CALL_REFCOUNT_MTU
);
6581 * Increment the counter for the next connection ID, handling overflow.
6584 update_nextCid(void)
6586 /* Overflow is technically undefined behavior; avoid it. */
6587 if (rx_nextCid
> MAX_AFS_INT32
- (1 << RX_CIDSHIFT
))
6588 rx_nextCid
= -1 * ((MAX_AFS_INT32
/ RX_CIDSHIFT
) * RX_CIDSHIFT
);
6590 rx_nextCid
+= 1 << RX_CIDSHIFT
;
6594 rxi_KeepAliveOn(struct rx_call
*call
)
6596 /* Pretend last packet received was received now--i.e. if another
6597 * packet isn't received within the keep alive time, then the call
6598 * will die; Initialize last send time to the current time--even
6599 * if a packet hasn't been sent yet. This will guarantee that a
6600 * keep-alive is sent within the ping time */
6601 call
->lastReceiveTime
= call
->lastSendTime
= clock_Sec();
6602 rxi_ScheduleKeepAliveEvent(call
);
6606 rxi_GrowMTUOn(struct rx_call
*call
)
6608 struct rx_connection
*conn
= call
->conn
;
6609 MUTEX_ENTER(&conn
->conn_data_lock
);
6610 conn
->lastPingSizeSer
= conn
->lastPingSize
= 0;
6611 MUTEX_EXIT(&conn
->conn_data_lock
);
6612 rxi_ScheduleGrowMTUEvent(call
, 1);
6615 /* This routine is called to send connection abort messages
6616 * that have been delayed to throttle looping clients. */
6618 rxi_SendDelayedConnAbort(struct rxevent
*event
, void *arg1
, void *unused
,
6621 struct rx_connection
*conn
= arg1
;
6624 struct rx_packet
*packet
;
6626 MUTEX_ENTER(&conn
->conn_data_lock
);
6627 rxevent_Put(&conn
->delayedAbortEvent
);
6628 error
= htonl(conn
->error
);
6630 MUTEX_EXIT(&conn
->conn_data_lock
);
6631 packet
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
);
6634 rxi_SendSpecial((struct rx_call
*)0, conn
, packet
,
6635 RX_PACKET_TYPE_ABORT
, (char *)&error
,
6637 rxi_FreePacket(packet
);
6641 /* This routine is called to send call abort messages
6642 * that have been delayed to throttle looping clients. */
6644 rxi_SendDelayedCallAbort(struct rxevent
*event
, void *arg1
, void *dummy
,
6647 struct rx_call
*call
= arg1
;
6650 struct rx_packet
*packet
;
6652 MUTEX_ENTER(&call
->lock
);
6653 rxevent_Put(&call
->delayedAbortEvent
);
6654 error
= htonl(call
->error
);
6656 packet
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
);
6659 rxi_SendSpecial(call
, call
->conn
, packet
, RX_PACKET_TYPE_ABORT
,
6660 (char *)&error
, sizeof(error
), 0);
6661 rxi_FreePacket(packet
);
6663 MUTEX_EXIT(&call
->lock
);
6664 CALL_RELE(call
, RX_CALL_REFCOUNT_ABORT
);
6667 /* This routine is called periodically (every RX_AUTH_REQUEST_TIMEOUT
6668 * seconds) to ask the client to authenticate itself. The routine
6669 * issues a challenge to the client, which is obtained from the
6670 * security object associated with the connection */
6672 rxi_ChallengeEvent(struct rxevent
*event
,
6673 void *arg0
, void *arg1
, int tries
)
6675 struct rx_connection
*conn
= arg0
;
6678 rxevent_Put(&conn
->challengeEvent
);
6680 /* If there are no active calls it is not worth re-issuing the
6681 * challenge. If the client issues another call on this connection
6682 * the challenge can be requested at that time.
6684 if (!rxi_HasActiveCalls(conn
))
6687 if (RXS_CheckAuthentication(conn
->securityObject
, conn
) != 0) {
6688 struct rx_packet
*packet
;
6689 struct clock when
, now
;
6692 /* We've failed to authenticate for too long.
6693 * Reset any calls waiting for authentication;
6694 * they are all in RX_STATE_PRECALL.
6698 MUTEX_ENTER(&conn
->conn_call_lock
);
6699 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
6700 struct rx_call
*call
= conn
->call
[i
];
6702 MUTEX_ENTER(&call
->lock
);
6703 if (call
->state
== RX_STATE_PRECALL
) {
6704 rxi_CallError(call
, RX_CALL_DEAD
);
6705 rxi_SendCallAbort(call
, NULL
, 0, 0);
6707 MUTEX_EXIT(&call
->lock
);
6710 MUTEX_EXIT(&conn
->conn_call_lock
);
6714 packet
= rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL
);
6716 /* If there's no packet available, do this later. */
6717 RXS_GetChallenge(conn
->securityObject
, conn
, packet
);
6718 rxi_SendSpecial((struct rx_call
*)0, conn
, packet
,
6719 RX_PACKET_TYPE_CHALLENGE
, NULL
, -1, 0);
6720 rxi_FreePacket(packet
);
6721 conn
->securityChallengeSent
= 1;
6723 clock_GetTime(&now
);
6725 when
.sec
+= RX_CHALLENGE_TIMEOUT
;
6726 conn
->challengeEvent
=
6727 rxevent_Post(&when
, &now
, rxi_ChallengeEvent
, conn
, 0,
6732 /* Call this routine to start requesting the client to authenticate
6733 * itself. This will continue until authentication is established,
6734 * the call times out, or an invalid response is returned. The
6735 * security object associated with the connection is asked to create
6736 * the challenge at this time. N.B. rxi_ChallengeOff is a macro,
6737 * defined earlier. */
6739 rxi_ChallengeOn(struct rx_connection
*conn
)
6741 if (!conn
->challengeEvent
) {
6742 RXS_CreateChallenge(conn
->securityObject
, conn
);
6743 rxi_ChallengeEvent(NULL
, conn
, 0, RX_CHALLENGE_MAXTRIES
);
6748 /* rxi_ComputeRoundTripTime is called with peer locked. */
6749 /* peer may be null */
6751 rxi_ComputeRoundTripTime(struct rx_packet
*p
,
6752 struct rx_ackPacket
*ack
,
6753 struct rx_call
*call
,
6754 struct rx_peer
*peer
,
6757 struct clock thisRtt
, *sentp
;
6761 /* If the ACK is delayed, then do nothing */
6762 if (ack
->reason
== RX_ACK_DELAY
)
6765 /* On the wire, jumbograms are a single UDP packet. We shouldn't count
6766 * their RTT multiple times, so only include the RTT of the last packet
6768 if (p
->flags
& RX_JUMBO_PACKET
)
6771 /* Use the serial number to determine which transmission the ACK is for,
6772 * and set the sent time to match this. If we have no serial number, then
6773 * only use the ACK for RTT calculations if the packet has not been
6777 serial
= ntohl(ack
->serial
);
6779 if (serial
== p
->header
.serial
) {
6780 sentp
= &p
->timeSent
;
6781 } else if (serial
== p
->firstSerial
) {
6782 sentp
= &p
->firstSent
;
6783 } else if (clock_Eq(&p
->timeSent
, &p
->firstSent
)) {
6784 sentp
= &p
->firstSent
;
6788 if (clock_Eq(&p
->timeSent
, &p
->firstSent
)) {
6789 sentp
= &p
->firstSent
;
6796 if (clock_Lt(&thisRtt
, sentp
))
6797 return; /* somebody set the clock back, don't count this time. */
6799 clock_Sub(&thisRtt
, sentp
);
6800 dpf(("rxi_ComputeRoundTripTime(call=%d packet=%"AFS_PTR_FMT
" rttp=%d.%06d sec)\n",
6801 p
->header
.callNumber
, p
, thisRtt
.sec
, thisRtt
.usec
));
6803 if (clock_IsZero(&thisRtt
)) {
6805 * The actual round trip time is shorter than the
6806 * clock_GetTime resolution. It is most likely 1ms or 100ns.
6807 * Since we can't tell which at the moment we will assume 1ms.
6809 thisRtt
.usec
= 1000;
6812 if (rx_stats_active
) {
6813 MUTEX_ENTER(&rx_stats_mutex
);
6814 if (clock_Lt(&thisRtt
, &rx_stats
.minRtt
))
6815 rx_stats
.minRtt
= thisRtt
;
6816 if (clock_Gt(&thisRtt
, &rx_stats
.maxRtt
)) {
6817 if (thisRtt
.sec
> 60) {
6818 MUTEX_EXIT(&rx_stats_mutex
);
6819 return; /* somebody set the clock ahead */
6821 rx_stats
.maxRtt
= thisRtt
;
6823 clock_Add(&rx_stats
.totalRtt
, &thisRtt
);
6824 rx_atomic_inc(&rx_stats
.nRttSamples
);
6825 MUTEX_EXIT(&rx_stats_mutex
);
6828 /* better rtt calculation courtesy of UMich crew (dave,larry,peter,?) */
6830 /* Apply VanJacobson round-trip estimations */
6835 * srtt (call->rtt) is in units of one-eighth-milliseconds.
6836 * srtt is stored as fixed point with 3 bits after the binary
6837 * point (i.e., scaled by 8). The following magic is
6838 * equivalent to the smoothing algorithm in rfc793 with an
6839 * alpha of .875 (srtt' = rtt/8 + srtt*7/8 in fixed point).
6840 * srtt'*8 = rtt + srtt*7
6841 * srtt'*8 = srtt*8 + rtt - srtt
6842 * srtt' = srtt + rtt/8 - srtt/8
6843 * srtt' = srtt + (rtt - srtt)/8
6846 delta
= _8THMSEC(&thisRtt
) - call
->rtt
;
6847 call
->rtt
+= (delta
>> 3);
6850 * We accumulate a smoothed rtt variance (actually, a smoothed
6851 * mean difference), then set the retransmit timer to smoothed
6852 * rtt + 4 times the smoothed variance (was 2x in van's original
6853 * paper, but 4x works better for me, and apparently for him as
6855 * rttvar is stored as
6856 * fixed point with 2 bits after the binary point (scaled by
6857 * 4). The following is equivalent to rfc793 smoothing with
6858 * an alpha of .75 (rttvar' = rttvar*3/4 + |delta| / 4).
6859 * rttvar'*4 = rttvar*3 + |delta|
6860 * rttvar'*4 = rttvar*4 + |delta| - rttvar
6861 * rttvar' = rttvar + |delta|/4 - rttvar/4
6862 * rttvar' = rttvar + (|delta| - rttvar)/4
6863 * This replaces rfc793's wired-in beta.
6864 * dev*4 = dev*4 + (|actual - expected| - dev)
6870 delta
-= (call
->rtt_dev
<< 1);
6871 call
->rtt_dev
+= (delta
>> 3);
6873 /* I don't have a stored RTT so I start with this value. Since I'm
6874 * probably just starting a call, and will be pushing more data down
6875 * this, I expect congestion to increase rapidly. So I fudge a
6876 * little, and I set deviance to half the rtt. In practice,
6877 * deviance tends to approach something a little less than
6878 * half the smoothed rtt. */
6879 call
->rtt
= _8THMSEC(&thisRtt
) + 8;
6880 call
->rtt_dev
= call
->rtt
>> 2; /* rtt/2: they're scaled differently */
6882 /* the smoothed RTT time is RTT + 4*MDEV
6884 * We allow a user specified minimum to be set for this, to allow clamping
6885 * at a minimum value in the same way as TCP. In addition, we have to allow
6886 * for the possibility that this packet is answered by a delayed ACK, so we
6887 * add on a fixed 200ms to account for that timer expiring.
6890 rtt_timeout
= MAX(((call
->rtt
>> 3) + call
->rtt_dev
),
6891 rx_minPeerTimeout
) + 200;
6892 clock_Zero(&call
->rto
);
6893 clock_Addmsec(&call
->rto
, rtt_timeout
);
6895 /* Update the peer, so any new calls start with our values */
6896 peer
->rtt_dev
= call
->rtt_dev
;
6897 peer
->rtt
= call
->rtt
;
6899 dpf(("rxi_ComputeRoundTripTime(call=%d packet=%"AFS_PTR_FMT
" rtt=%d ms, srtt=%d ms, rtt_dev=%d ms, timeout=%d.%06d sec)\n",
6900 p
->header
.callNumber
, p
, MSEC(&thisRtt
), call
->rtt
>> 3, call
->rtt_dev
>> 2, (call
->rto
.sec
), (call
->rto
.usec
)));
6904 /* Find all server connections that have not been active for a long time, and
6907 rxi_ReapConnections(struct rxevent
*unused
, void *unused1
, void *unused2
,
6910 struct clock now
, when
;
6911 struct rxevent
*event
;
6912 clock_GetTime(&now
);
6914 /* Find server connection structures that haven't been used for
6915 * greater than rx_idleConnectionTime */
6917 struct rx_connection
**conn_ptr
, **conn_end
;
6918 int i
, havecalls
= 0;
6919 MUTEX_ENTER(&rx_connHashTable_lock
);
6920 for (conn_ptr
= &rx_connHashTable
[0], conn_end
=
6921 &rx_connHashTable
[rx_hashTableSize
]; conn_ptr
< conn_end
;
6923 struct rx_connection
*conn
, *next
;
6924 struct rx_call
*call
;
6928 for (conn
= *conn_ptr
; conn
; conn
= next
) {
6929 /* XXX -- Shouldn't the connection be locked? */
6932 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
6933 call
= conn
->call
[i
];
6937 code
= MUTEX_TRYENTER(&call
->lock
);
6940 result
= rxi_CheckCall(call
, 1);
6941 MUTEX_EXIT(&call
->lock
);
6943 /* If CheckCall freed the call, it might
6944 * have destroyed the connection as well,
6945 * which screws up the linked lists.
6951 if (conn
->type
== RX_SERVER_CONNECTION
) {
6952 /* This only actually destroys the connection if
6953 * there are no outstanding calls */
6954 MUTEX_ENTER(&conn
->conn_data_lock
);
6955 MUTEX_ENTER(&rx_refcnt_mutex
);
6956 if (!havecalls
&& !conn
->refCount
6957 && ((conn
->lastSendTime
+ rx_idleConnectionTime
) <
6959 conn
->refCount
++; /* it will be decr in rx_DestroyConn */
6960 MUTEX_EXIT(&rx_refcnt_mutex
);
6961 MUTEX_EXIT(&conn
->conn_data_lock
);
6962 #ifdef RX_ENABLE_LOCKS
6963 rxi_DestroyConnectionNoLock(conn
);
6964 #else /* RX_ENABLE_LOCKS */
6965 rxi_DestroyConnection(conn
);
6966 #endif /* RX_ENABLE_LOCKS */
6968 #ifdef RX_ENABLE_LOCKS
6970 MUTEX_EXIT(&rx_refcnt_mutex
);
6971 MUTEX_EXIT(&conn
->conn_data_lock
);
6973 #endif /* RX_ENABLE_LOCKS */
6977 #ifdef RX_ENABLE_LOCKS
6978 while (rx_connCleanup_list
) {
6979 struct rx_connection
*conn
;
6980 conn
= rx_connCleanup_list
;
6981 rx_connCleanup_list
= rx_connCleanup_list
->next
;
6982 MUTEX_EXIT(&rx_connHashTable_lock
);
6983 rxi_CleanupConnection(conn
);
6984 MUTEX_ENTER(&rx_connHashTable_lock
);
6986 MUTEX_EXIT(&rx_connHashTable_lock
);
6987 #endif /* RX_ENABLE_LOCKS */
6990 /* Find any peer structures that haven't been used (haven't had an
6991 * associated connection) for greater than rx_idlePeerTime */
6993 struct rx_peer
**peer_ptr
, **peer_end
;
6997 * Why do we need to hold the rx_peerHashTable_lock across
6998 * the incrementing of peer_ptr since the rx_peerHashTable
6999 * array is not changing? We don't.
7001 * By dropping the lock periodically we can permit other
7002 * activities to be performed while a rxi_ReapConnections
7003 * call is in progress. The goal of reap connections
7004 * is to clean up quickly without causing large amounts
7005 * of contention. Therefore, it is important that global
7006 * mutexes not be held for extended periods of time.
7008 for (peer_ptr
= &rx_peerHashTable
[0], peer_end
=
7009 &rx_peerHashTable
[rx_hashTableSize
]; peer_ptr
< peer_end
;
7011 struct rx_peer
*peer
, *next
, *prev
;
7013 MUTEX_ENTER(&rx_peerHashTable_lock
);
7014 for (prev
= peer
= *peer_ptr
; peer
; peer
= next
) {
7016 code
= MUTEX_TRYENTER(&peer
->peer_lock
);
7017 if ((code
) && (peer
->refCount
== 0)
7018 && ((peer
->idleWhen
+ rx_idlePeerTime
) < now
.sec
)) {
7019 struct opr_queue
*cursor
, *store
;
7023 * now know that this peer object is one to be
7024 * removed from the hash table. Once it is removed
7025 * it can't be referenced by other threads.
7026 * Lets remove it first and decrement the struct
7027 * nPeerStructs count.
7029 if (peer
== *peer_ptr
) {
7035 if (rx_stats_active
)
7036 rx_atomic_dec(&rx_stats
.nPeerStructs
);
7039 * Now if we hold references on 'prev' and 'next'
7040 * we can safely drop the rx_peerHashTable_lock
7041 * while we destroy this 'peer' object.
7047 MUTEX_EXIT(&rx_peerHashTable_lock
);
7049 MUTEX_EXIT(&peer
->peer_lock
);
7050 MUTEX_DESTROY(&peer
->peer_lock
);
7052 for (opr_queue_ScanSafe(&peer
->rpcStats
, cursor
, store
)) {
7053 unsigned int num_funcs
;
7054 struct rx_interface_stat
*rpc_stat
7055 = opr_queue_Entry(cursor
, struct rx_interface_stat
,
7060 opr_queue_Remove(&rpc_stat
->entry
);
7061 opr_queue_Remove(&rpc_stat
->entryPeers
);
7063 num_funcs
= rpc_stat
->stats
[0].func_total
;
7065 sizeof(rx_interface_stat_t
) +
7066 rpc_stat
->stats
[0].func_total
*
7067 sizeof(rx_function_entry_v1_t
);
7069 rxi_Free(rpc_stat
, space
);
7071 MUTEX_ENTER(&rx_rpc_stats
);
7072 rxi_rpc_peer_stat_cnt
-= num_funcs
;
7073 MUTEX_EXIT(&rx_rpc_stats
);
7078 * Regain the rx_peerHashTable_lock and
7079 * decrement the reference count on 'prev'
7082 MUTEX_ENTER(&rx_peerHashTable_lock
);
7089 MUTEX_EXIT(&peer
->peer_lock
);
7094 MUTEX_EXIT(&rx_peerHashTable_lock
);
7098 /* THIS HACK IS A TEMPORARY HACK. The idea is that the race condition in
7099 * rxi_AllocSendPacket, if it hits, will be handled at the next conn
7100 * GC, just below. Really, we shouldn't have to keep moving packets from
7101 * one place to another, but instead ought to always know if we can
7102 * afford to hold onto a packet in its particular use. */
7103 MUTEX_ENTER(&rx_freePktQ_lock
);
7104 if (rx_waitingForPackets
) {
7105 rx_waitingForPackets
= 0;
7106 #ifdef RX_ENABLE_LOCKS
7107 CV_BROADCAST(&rx_waitingForPackets_cv
);
7109 osi_rxWakeup(&rx_waitingForPackets
);
7112 MUTEX_EXIT(&rx_freePktQ_lock
);
7115 when
.sec
+= RX_REAP_TIME
; /* Check every RX_REAP_TIME seconds */
7116 event
= rxevent_Post(&when
, &now
, rxi_ReapConnections
, 0, NULL
, 0);
7117 rxevent_Put(&event
);
7121 /* rxs_Release - This isn't strictly necessary but, since the macro name from
7122 * rx.h is sort of strange this is better. This is called with a security
7123 * object before it is discarded. Each connection using a security object has
7124 * its own refcount to the object so it won't actually be freed until the last
7125 * connection is destroyed.
7127 * This is the only rxs module call. A hold could also be written but no one
7131 rxs_Release(struct rx_securityClass
*aobj
)
7133 return RXS_Close(aobj
);
7141 #define TRACE_OPTION_RX_DEBUG 16
7149 code
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, AFSREG_CLT_SVC_PARAM_SUBKEY
,
7150 0, KEY_QUERY_VALUE
, &parmKey
);
7151 if (code
!= ERROR_SUCCESS
)
7154 dummyLen
= sizeof(TraceOption
);
7155 code
= RegQueryValueEx(parmKey
, "TraceOption", NULL
, NULL
,
7156 (BYTE
*) &TraceOption
, &dummyLen
);
7157 if (code
== ERROR_SUCCESS
) {
7158 rxdebug_active
= (TraceOption
& TRACE_OPTION_RX_DEBUG
) ? 1 : 0;
7160 RegCloseKey (parmKey
);
7161 #endif /* AFS_NT40_ENV */
7166 rx_DebugOnOff(int on
)
7170 rxdebug_active
= on
;
7176 rx_StatsOnOff(int on
)
7178 rx_stats_active
= on
;
7182 /* Don't call this debugging routine directly; use dpf */
7184 rxi_DebugPrint(char *format
, ...)
7193 va_start(ap
, format
);
7195 len
= _snprintf(tformat
, sizeof(tformat
), "tid[%d] %s", GetCurrentThreadId(), format
);
7198 len
= _vsnprintf(msg
, sizeof(msg
)-2, tformat
, ap
);
7200 OutputDebugString(msg
);
7206 va_start(ap
, format
);
7208 clock_GetTime(&now
);
7209 fprintf(rx_Log
, " %d.%06d:", (unsigned int)now
.sec
,
7210 (unsigned int)now
.usec
);
7211 vfprintf(rx_Log
, format
, ap
);
7219 * This function is used to process the rx_stats structure that is local
7220 * to a process as well as an rx_stats structure received from a remote
7221 * process (via rxdebug). Therefore, it needs to do minimal version
7225 rx_PrintTheseStats(FILE * file
, struct rx_statistics
*s
, int size
,
7226 afs_int32 freePackets
, char version
)
7230 if (size
!= sizeof(struct rx_statistics
)) {
7232 "Unexpected size of stats structure: was %d, expected %" AFS_SIZET_FMT
"\n",
7233 size
, sizeof(struct rx_statistics
));
7236 fprintf(file
, "rx stats: free packets %d, allocs %d, ", (int)freePackets
,
7239 if (version
>= RX_DEBUGI_VERSION_W_NEWPACKETTYPES
) {
7240 fprintf(file
, "alloc-failures(rcv %u/%u,send %u/%u,ack %u)\n",
7241 s
->receivePktAllocFailures
, s
->receiveCbufPktAllocFailures
,
7242 s
->sendPktAllocFailures
, s
->sendCbufPktAllocFailures
,
7243 s
->specialPktAllocFailures
);
7245 fprintf(file
, "alloc-failures(rcv %u,send %u,ack %u)\n",
7246 s
->receivePktAllocFailures
, s
->sendPktAllocFailures
,
7247 s
->specialPktAllocFailures
);
7251 " greedy %u, " "bogusReads %u (last from host %x), "
7252 "noPackets %u, " "noBuffers %u, " "selects %u, "
7253 "sendSelects %u\n", s
->socketGreedy
, s
->bogusPacketOnRead
,
7254 s
->bogusHost
, s
->noPacketOnRead
, s
->noPacketBuffersOnRead
,
7255 s
->selects
, s
->sendSelects
);
7257 fprintf(file
, " packets read: ");
7258 for (i
= 0; i
< RX_N_PACKET_TYPES
; i
++) {
7259 fprintf(file
, "%s %u ", rx_packetTypes
[i
], s
->packetsRead
[i
]);
7261 fprintf(file
, "\n");
7264 " other read counters: data %u, " "ack %u, " "dup %u "
7265 "spurious %u " "dally %u\n", s
->dataPacketsRead
,
7266 s
->ackPacketsRead
, s
->dupPacketsRead
, s
->spuriousPacketsRead
,
7267 s
->ignorePacketDally
);
7269 fprintf(file
, " packets sent: ");
7270 for (i
= 0; i
< RX_N_PACKET_TYPES
; i
++) {
7271 fprintf(file
, "%s %u ", rx_packetTypes
[i
], s
->packetsSent
[i
]);
7273 fprintf(file
, "\n");
7276 " other send counters: ack %u, " "data %u (not resends), "
7277 "resends %u, " "pushed %u, " "acked&ignored %u\n",
7278 s
->ackPacketsSent
, s
->dataPacketsSent
, s
->dataPacketsReSent
,
7279 s
->dataPacketsPushed
, s
->ignoreAckedPacket
);
7282 " \t(these should be small) sendFailed %u, " "fatalErrors %u\n",
7283 s
->netSendFailures
, (int)s
->fatalErrors
);
7285 if (s
->nRttSamples
) {
7286 fprintf(file
, " Average rtt is %0.3f, with %d samples\n",
7287 clock_Float(&s
->totalRtt
) / s
->nRttSamples
, s
->nRttSamples
);
7289 fprintf(file
, " Minimum rtt is %0.3f, maximum is %0.3f\n",
7290 clock_Float(&s
->minRtt
), clock_Float(&s
->maxRtt
));
7294 " %d server connections, " "%d client connections, "
7295 "%d peer structs, " "%d call structs, " "%d free call structs\n",
7296 s
->nServerConns
, s
->nClientConns
, s
->nPeerStructs
,
7297 s
->nCallStructs
, s
->nFreeCallStructs
);
7299 #if !defined(AFS_PTHREAD_ENV) && !defined(AFS_USE_GETTIMEOFDAY)
7300 fprintf(file
, " %d clock updates\n", clock_nUpdates
);
7304 /* for backward compatibility */
7306 rx_PrintStats(FILE * file
)
7308 MUTEX_ENTER(&rx_stats_mutex
);
7309 rx_PrintTheseStats(file
, (struct rx_statistics
*) &rx_stats
,
7310 sizeof(rx_stats
), rx_nFreePackets
,
7312 MUTEX_EXIT(&rx_stats_mutex
);
7316 rx_PrintPeerStats(FILE * file
, struct rx_peer
*peer
)
7318 fprintf(file
, "Peer %x.%d.\n",
7319 ntohl(peer
->host
), (int)ntohs(peer
->port
));
7322 " Rtt %d, " "total sent %d, " "resent %d\n",
7323 peer
->rtt
, peer
->nSent
, peer
->reSends
);
7325 fprintf(file
, " Packet size %d\n", peer
->ifMTU
);
7329 #if defined(AFS_PTHREAD_ENV) && defined(RXDEBUG)
7331 * This mutex protects the following static variables:
7335 #define LOCK_RX_DEBUG MUTEX_ENTER(&rx_debug_mutex)
7336 #define UNLOCK_RX_DEBUG MUTEX_EXIT(&rx_debug_mutex)
7338 #define LOCK_RX_DEBUG
7339 #define UNLOCK_RX_DEBUG
7340 #endif /* AFS_PTHREAD_ENV */
7342 #if defined(RXDEBUG) || defined(MAKEDEBUGCALL)
7344 MakeDebugCall(osi_socket socket
, afs_uint32 remoteAddr
, afs_uint16 remotePort
,
7345 u_char type
, void *inputData
, size_t inputLength
,
7346 void *outputData
, size_t outputLength
)
7348 static afs_int32 counter
= 100;
7349 time_t waitTime
, waitCount
;
7350 struct rx_header theader
;
7353 struct timeval tv_now
, tv_wake
, tv_delta
;
7354 struct sockaddr_in taddr
, faddr
;
7368 tp
= &tbuffer
[sizeof(struct rx_header
)];
7369 taddr
.sin_family
= AF_INET
;
7370 taddr
.sin_port
= remotePort
;
7371 taddr
.sin_addr
.s_addr
= remoteAddr
;
7372 memset(&taddr
.sin_zero
, 0, sizeof(taddr
.sin_zero
));
7373 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
7374 taddr
.sin_len
= sizeof(struct sockaddr_in
);
7377 memset(&theader
, 0, sizeof(theader
));
7378 theader
.epoch
= htonl(999);
7380 theader
.callNumber
= htonl(counter
);
7383 theader
.type
= type
;
7384 theader
.flags
= RX_CLIENT_INITIATED
| RX_LAST_PACKET
;
7385 theader
.serviceId
= 0;
7387 memcpy(tbuffer
, &theader
, sizeof(theader
));
7388 memcpy(tp
, inputData
, inputLength
);
7390 sendto(socket
, tbuffer
, inputLength
+ sizeof(struct rx_header
), 0,
7391 (struct sockaddr
*)&taddr
, sizeof(struct sockaddr_in
));
7393 /* see if there's a packet available */
7394 gettimeofday(&tv_wake
, NULL
);
7395 tv_wake
.tv_sec
+= waitTime
;
7398 FD_SET(socket
, &imask
);
7399 tv_delta
.tv_sec
= tv_wake
.tv_sec
;
7400 tv_delta
.tv_usec
= tv_wake
.tv_usec
;
7401 gettimeofday(&tv_now
, NULL
);
7403 if (tv_delta
.tv_usec
< tv_now
.tv_usec
) {
7405 tv_delta
.tv_usec
+= 1000000;
7408 tv_delta
.tv_usec
-= tv_now
.tv_usec
;
7410 if (tv_delta
.tv_sec
< tv_now
.tv_sec
) {
7414 tv_delta
.tv_sec
-= tv_now
.tv_sec
;
7417 code
= select(0, &imask
, 0, 0, &tv_delta
);
7418 #else /* AFS_NT40_ENV */
7419 code
= select(socket
+ 1, &imask
, 0, 0, &tv_delta
);
7420 #endif /* AFS_NT40_ENV */
7421 if (code
== 1 && FD_ISSET(socket
, &imask
)) {
7422 /* now receive a packet */
7423 faddrLen
= sizeof(struct sockaddr_in
);
7425 recvfrom(socket
, tbuffer
, sizeof(tbuffer
), 0,
7426 (struct sockaddr
*)&faddr
, &faddrLen
);
7429 memcpy(&theader
, tbuffer
, sizeof(struct rx_header
));
7430 if (counter
== ntohl(theader
.callNumber
))
7438 /* see if we've timed out */
7446 code
-= sizeof(struct rx_header
);
7447 if (code
> outputLength
)
7448 code
= outputLength
;
7449 memcpy(outputData
, tp
, code
);
7452 #endif /* RXDEBUG */
7455 rx_GetServerDebug(osi_socket socket
, afs_uint32 remoteAddr
,
7456 afs_uint16 remotePort
, struct rx_debugStats
* stat
,
7457 afs_uint32
* supportedValues
)
7459 #if defined(RXDEBUG) || defined(MAKEDEBUGCALL)
7461 struct rx_debugIn in
;
7463 *supportedValues
= 0;
7464 in
.type
= htonl(RX_DEBUGI_GETSTATS
);
7467 rc
= MakeDebugCall(socket
, remoteAddr
, remotePort
, RX_PACKET_TYPE_DEBUG
,
7468 &in
, sizeof(in
), stat
, sizeof(*stat
));
7471 * If the call was successful, fixup the version and indicate
7472 * what contents of the stat structure are valid.
7473 * Also do net to host conversion of fields here.
7477 if (stat
->version
>= RX_DEBUGI_VERSION_W_SECSTATS
) {
7478 *supportedValues
|= RX_SERVER_DEBUG_SEC_STATS
;
7480 if (stat
->version
>= RX_DEBUGI_VERSION_W_GETALLCONN
) {
7481 *supportedValues
|= RX_SERVER_DEBUG_ALL_CONN
;
7483 if (stat
->version
>= RX_DEBUGI_VERSION_W_RXSTATS
) {
7484 *supportedValues
|= RX_SERVER_DEBUG_RX_STATS
;
7486 if (stat
->version
>= RX_DEBUGI_VERSION_W_WAITERS
) {
7487 *supportedValues
|= RX_SERVER_DEBUG_WAITER_CNT
;
7489 if (stat
->version
>= RX_DEBUGI_VERSION_W_IDLETHREADS
) {
7490 *supportedValues
|= RX_SERVER_DEBUG_IDLE_THREADS
;
7492 if (stat
->version
>= RX_DEBUGI_VERSION_W_NEWPACKETTYPES
) {
7493 *supportedValues
|= RX_SERVER_DEBUG_NEW_PACKETS
;
7495 if (stat
->version
>= RX_DEBUGI_VERSION_W_GETPEER
) {
7496 *supportedValues
|= RX_SERVER_DEBUG_ALL_PEER
;
7498 if (stat
->version
>= RX_DEBUGI_VERSION_W_WAITED
) {
7499 *supportedValues
|= RX_SERVER_DEBUG_WAITED_CNT
;
7501 if (stat
->version
>= RX_DEBUGI_VERSION_W_PACKETS
) {
7502 *supportedValues
|= RX_SERVER_DEBUG_PACKETS_CNT
;
7504 stat
->nFreePackets
= ntohl(stat
->nFreePackets
);
7505 stat
->packetReclaims
= ntohl(stat
->packetReclaims
);
7506 stat
->callsExecuted
= ntohl(stat
->callsExecuted
);
7507 stat
->nWaiting
= ntohl(stat
->nWaiting
);
7508 stat
->idleThreads
= ntohl(stat
->idleThreads
);
7509 stat
->nWaited
= ntohl(stat
->nWaited
);
7510 stat
->nPackets
= ntohl(stat
->nPackets
);
7519 rx_GetServerStats(osi_socket socket
, afs_uint32 remoteAddr
,
7520 afs_uint16 remotePort
, struct rx_statistics
* stat
,
7521 afs_uint32
* supportedValues
)
7523 #if defined(RXDEBUG) || defined(MAKEDEBUGCALL)
7525 struct rx_debugIn in
;
7526 afs_int32
*lp
= (afs_int32
*) stat
;
7530 * supportedValues is currently unused, but added to allow future
7531 * versioning of this function.
7534 *supportedValues
= 0;
7535 in
.type
= htonl(RX_DEBUGI_RXSTATS
);
7537 memset(stat
, 0, sizeof(*stat
));
7539 rc
= MakeDebugCall(socket
, remoteAddr
, remotePort
, RX_PACKET_TYPE_DEBUG
,
7540 &in
, sizeof(in
), stat
, sizeof(*stat
));
7545 * Do net to host conversion here
7548 for (i
= 0; i
< sizeof(*stat
) / sizeof(afs_int32
); i
++, lp
++) {
7559 rx_GetServerVersion(osi_socket socket
, afs_uint32 remoteAddr
,
7560 afs_uint16 remotePort
, size_t version_length
,
7563 #if defined(RXDEBUG) || defined(MAKEDEBUGCALL)
7565 return MakeDebugCall(socket
, remoteAddr
, remotePort
,
7566 RX_PACKET_TYPE_VERSION
, a
, 1, version
,
7574 rx_GetServerConnections(osi_socket socket
, afs_uint32 remoteAddr
,
7575 afs_uint16 remotePort
, afs_int32
* nextConnection
,
7576 int allConnections
, afs_uint32 debugSupportedValues
,
7577 struct rx_debugConn
* conn
,
7578 afs_uint32
* supportedValues
)
7580 #if defined(RXDEBUG) || defined(MAKEDEBUGCALL)
7582 struct rx_debugIn in
;
7586 * supportedValues is currently unused, but added to allow future
7587 * versioning of this function.
7590 *supportedValues
= 0;
7591 if (allConnections
) {
7592 in
.type
= htonl(RX_DEBUGI_GETALLCONN
);
7594 in
.type
= htonl(RX_DEBUGI_GETCONN
);
7596 in
.index
= htonl(*nextConnection
);
7597 memset(conn
, 0, sizeof(*conn
));
7599 rc
= MakeDebugCall(socket
, remoteAddr
, remotePort
, RX_PACKET_TYPE_DEBUG
,
7600 &in
, sizeof(in
), conn
, sizeof(*conn
));
7603 *nextConnection
+= 1;
7606 * Convert old connection format to new structure.
7609 if (debugSupportedValues
& RX_SERVER_DEBUG_OLD_CONN
) {
7610 struct rx_debugConn_vL
*vL
= (struct rx_debugConn_vL
*)conn
;
7611 #define MOVEvL(a) (conn->a = vL->a)
7613 /* any old or unrecognized version... */
7614 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
7615 MOVEvL(callState
[i
]);
7616 MOVEvL(callMode
[i
]);
7617 MOVEvL(callFlags
[i
]);
7618 MOVEvL(callOther
[i
]);
7620 if (debugSupportedValues
& RX_SERVER_DEBUG_SEC_STATS
) {
7621 MOVEvL(secStats
.type
);
7622 MOVEvL(secStats
.level
);
7623 MOVEvL(secStats
.flags
);
7624 MOVEvL(secStats
.expires
);
7625 MOVEvL(secStats
.packetsReceived
);
7626 MOVEvL(secStats
.packetsSent
);
7627 MOVEvL(secStats
.bytesReceived
);
7628 MOVEvL(secStats
.bytesSent
);
7633 * Do net to host conversion here
7635 * I don't convert host or port since we are most likely
7636 * going to want these in NBO.
7638 conn
->cid
= ntohl(conn
->cid
);
7639 conn
->serial
= ntohl(conn
->serial
);
7640 for (i
= 0; i
< RX_MAXCALLS
; i
++) {
7641 conn
->callNumber
[i
] = ntohl(conn
->callNumber
[i
]);
7643 conn
->error
= ntohl(conn
->error
);
7644 conn
->secStats
.flags
= ntohl(conn
->secStats
.flags
);
7645 conn
->secStats
.expires
= ntohl(conn
->secStats
.expires
);
7646 conn
->secStats
.packetsReceived
=
7647 ntohl(conn
->secStats
.packetsReceived
);
7648 conn
->secStats
.packetsSent
= ntohl(conn
->secStats
.packetsSent
);
7649 conn
->secStats
.bytesReceived
= ntohl(conn
->secStats
.bytesReceived
);
7650 conn
->secStats
.bytesSent
= ntohl(conn
->secStats
.bytesSent
);
7651 conn
->epoch
= ntohl(conn
->epoch
);
7652 conn
->natMTU
= ntohl(conn
->natMTU
);
7661 rx_GetServerPeers(osi_socket socket
, afs_uint32 remoteAddr
,
7662 afs_uint16 remotePort
, afs_int32
* nextPeer
,
7663 afs_uint32 debugSupportedValues
, struct rx_debugPeer
* peer
,
7664 afs_uint32
* supportedValues
)
7666 #if defined(RXDEBUG) || defined(MAKEDEBUGCALL)
7668 struct rx_debugIn in
;
7671 * supportedValues is currently unused, but added to allow future
7672 * versioning of this function.
7675 *supportedValues
= 0;
7676 in
.type
= htonl(RX_DEBUGI_GETPEER
);
7677 in
.index
= htonl(*nextPeer
);
7678 memset(peer
, 0, sizeof(*peer
));
7680 rc
= MakeDebugCall(socket
, remoteAddr
, remotePort
, RX_PACKET_TYPE_DEBUG
,
7681 &in
, sizeof(in
), peer
, sizeof(*peer
));
7687 * Do net to host conversion here
7689 * I don't convert host or port since we are most likely
7690 * going to want these in NBO.
7692 peer
->ifMTU
= ntohs(peer
->ifMTU
);
7693 peer
->idleWhen
= ntohl(peer
->idleWhen
);
7694 peer
->refCount
= ntohs(peer
->refCount
);
7695 peer
->rtt
= ntohl(peer
->rtt
);
7696 peer
->rtt_dev
= ntohl(peer
->rtt_dev
);
7697 peer
->timeout
.sec
= 0;
7698 peer
->timeout
.usec
= 0;
7699 peer
->nSent
= ntohl(peer
->nSent
);
7700 peer
->reSends
= ntohl(peer
->reSends
);
7701 peer
->natMTU
= ntohs(peer
->natMTU
);
7702 peer
->maxMTU
= ntohs(peer
->maxMTU
);
7703 peer
->maxDgramPackets
= ntohs(peer
->maxDgramPackets
);
7704 peer
->ifDgramPackets
= ntohs(peer
->ifDgramPackets
);
7705 peer
->MTU
= ntohs(peer
->MTU
);
7706 peer
->cwind
= ntohs(peer
->cwind
);
7707 peer
->nDgramPackets
= ntohs(peer
->nDgramPackets
);
7708 peer
->congestSeq
= ntohs(peer
->congestSeq
);
7709 peer
->bytesSent
.high
= ntohl(peer
->bytesSent
.high
);
7710 peer
->bytesSent
.low
= ntohl(peer
->bytesSent
.low
);
7711 peer
->bytesReceived
.high
= ntohl(peer
->bytesReceived
.high
);
7712 peer
->bytesReceived
.low
= ntohl(peer
->bytesReceived
.low
);
7721 rx_GetLocalPeers(afs_uint32 peerHost
, afs_uint16 peerPort
,
7722 struct rx_debugPeer
* peerStats
)
7725 afs_int32 error
= 1; /* default to "did not succeed" */
7726 afs_uint32 hashValue
= PEER_HASH(peerHost
, peerPort
);
7728 MUTEX_ENTER(&rx_peerHashTable_lock
);
7729 for(tp
= rx_peerHashTable
[hashValue
];
7730 tp
!= NULL
; tp
= tp
->next
) {
7731 if (tp
->host
== peerHost
)
7737 MUTEX_EXIT(&rx_peerHashTable_lock
);
7741 MUTEX_ENTER(&tp
->peer_lock
);
7742 peerStats
->host
= tp
->host
;
7743 peerStats
->port
= tp
->port
;
7744 peerStats
->ifMTU
= tp
->ifMTU
;
7745 peerStats
->idleWhen
= tp
->idleWhen
;
7746 peerStats
->refCount
= tp
->refCount
;
7747 peerStats
->burstSize
= 0;
7748 peerStats
->burst
= 0;
7749 peerStats
->burstWait
.sec
= 0;
7750 peerStats
->burstWait
.usec
= 0;
7751 peerStats
->rtt
= tp
->rtt
;
7752 peerStats
->rtt_dev
= tp
->rtt_dev
;
7753 peerStats
->timeout
.sec
= 0;
7754 peerStats
->timeout
.usec
= 0;
7755 peerStats
->nSent
= tp
->nSent
;
7756 peerStats
->reSends
= tp
->reSends
;
7757 peerStats
->natMTU
= tp
->natMTU
;
7758 peerStats
->maxMTU
= tp
->maxMTU
;
7759 peerStats
->maxDgramPackets
= tp
->maxDgramPackets
;
7760 peerStats
->ifDgramPackets
= tp
->ifDgramPackets
;
7761 peerStats
->MTU
= tp
->MTU
;
7762 peerStats
->cwind
= tp
->cwind
;
7763 peerStats
->nDgramPackets
= tp
->nDgramPackets
;
7764 peerStats
->congestSeq
= tp
->congestSeq
;
7765 peerStats
->bytesSent
.high
= tp
->bytesSent
>> 32;
7766 peerStats
->bytesSent
.low
= tp
->bytesSent
& MAX_AFS_UINT32
;
7767 peerStats
->bytesReceived
.high
= tp
->bytesReceived
>> 32;
7768 peerStats
->bytesReceived
.low
7769 = tp
->bytesReceived
& MAX_AFS_UINT32
;
7770 MUTEX_EXIT(&tp
->peer_lock
);
7772 MUTEX_ENTER(&rx_peerHashTable_lock
);
7775 MUTEX_EXIT(&rx_peerHashTable_lock
);
7783 struct rx_serverQueueEntry
*np
;
7786 struct rx_call
*call
;
7787 struct rx_serverQueueEntry
*sq
;
7790 if (rx_atomic_test_and_set_bit(&rxinit_status
, 0))
7791 return; /* Already shutdown. */
7795 #ifndef AFS_PTHREAD_ENV
7796 FD_ZERO(&rx_selectMask
);
7797 #endif /* AFS_PTHREAD_ENV */
7798 rxi_dataQuota
= RX_MAX_QUOTA
;
7799 #ifndef AFS_PTHREAD_ENV
7801 #endif /* AFS_PTHREAD_ENV */
7804 #ifndef AFS_PTHREAD_ENV
7805 #ifndef AFS_USE_GETTIMEOFDAY
7807 #endif /* AFS_USE_GETTIMEOFDAY */
7808 #endif /* AFS_PTHREAD_ENV */
7810 while (!opr_queue_IsEmpty(&rx_freeCallQueue
)) {
7811 call
= opr_queue_First(&rx_freeCallQueue
, struct rx_call
, entry
);
7812 opr_queue_Remove(&call
->entry
);
7813 rxi_Free(call
, sizeof(struct rx_call
));
7816 while (!opr_queue_IsEmpty(&rx_idleServerQueue
)) {
7817 sq
= opr_queue_First(&rx_idleServerQueue
, struct rx_serverQueueEntry
,
7819 opr_queue_Remove(&sq
->entry
);
7824 struct rx_peer
**peer_ptr
, **peer_end
;
7825 for (peer_ptr
= &rx_peerHashTable
[0], peer_end
=
7826 &rx_peerHashTable
[rx_hashTableSize
]; peer_ptr
< peer_end
;
7828 struct rx_peer
*peer
, *next
;
7830 MUTEX_ENTER(&rx_peerHashTable_lock
);
7831 for (peer
= *peer_ptr
; peer
; peer
= next
) {
7832 struct opr_queue
*cursor
, *store
;
7835 MUTEX_ENTER(&rx_rpc_stats
);
7836 MUTEX_ENTER(&peer
->peer_lock
);
7837 for (opr_queue_ScanSafe(&peer
->rpcStats
, cursor
, store
)) {
7838 unsigned int num_funcs
;
7839 struct rx_interface_stat
*rpc_stat
7840 = opr_queue_Entry(cursor
, struct rx_interface_stat
,
7844 opr_queue_Remove(&rpc_stat
->entry
);
7845 opr_queue_Remove(&rpc_stat
->entryPeers
);
7846 num_funcs
= rpc_stat
->stats
[0].func_total
;
7848 sizeof(rx_interface_stat_t
) +
7849 rpc_stat
->stats
[0].func_total
*
7850 sizeof(rx_function_entry_v1_t
);
7852 rxi_Free(rpc_stat
, space
);
7854 /* rx_rpc_stats must be held */
7855 rxi_rpc_peer_stat_cnt
-= num_funcs
;
7857 MUTEX_EXIT(&peer
->peer_lock
);
7858 MUTEX_EXIT(&rx_rpc_stats
);
7862 if (rx_stats_active
)
7863 rx_atomic_dec(&rx_stats
.nPeerStructs
);
7865 MUTEX_EXIT(&rx_peerHashTable_lock
);
7868 for (i
= 0; i
< RX_MAX_SERVICES
; i
++) {
7870 rxi_Free(rx_services
[i
], sizeof(*rx_services
[i
]));
7872 for (i
= 0; i
< rx_hashTableSize
; i
++) {
7873 struct rx_connection
*tc
, *ntc
;
7874 MUTEX_ENTER(&rx_connHashTable_lock
);
7875 for (tc
= rx_connHashTable
[i
]; tc
; tc
= ntc
) {
7877 for (j
= 0; j
< RX_MAXCALLS
; j
++) {
7879 rxi_Free(tc
->call
[j
], sizeof(*tc
->call
[j
]));
7882 rxi_Free(tc
, sizeof(*tc
));
7884 MUTEX_EXIT(&rx_connHashTable_lock
);
7887 MUTEX_ENTER(&freeSQEList_lock
);
7889 while ((np
= rx_FreeSQEList
)) {
7890 rx_FreeSQEList
= *(struct rx_serverQueueEntry
**)np
;
7891 MUTEX_DESTROY(&np
->lock
);
7892 rxi_Free(np
, sizeof(*np
));
7895 MUTEX_EXIT(&freeSQEList_lock
);
7896 MUTEX_DESTROY(&freeSQEList_lock
);
7897 MUTEX_DESTROY(&rx_freeCallQueue_lock
);
7898 MUTEX_DESTROY(&rx_connHashTable_lock
);
7899 MUTEX_DESTROY(&rx_peerHashTable_lock
);
7900 MUTEX_DESTROY(&rx_serverPool_lock
);
7902 osi_Free(rx_connHashTable
,
7903 rx_hashTableSize
* sizeof(struct rx_connection
*));
7904 osi_Free(rx_peerHashTable
, rx_hashTableSize
* sizeof(struct rx_peer
*));
7906 UNPIN(rx_connHashTable
,
7907 rx_hashTableSize
* sizeof(struct rx_connection
*));
7908 UNPIN(rx_peerHashTable
, rx_hashTableSize
* sizeof(struct rx_peer
*));
7910 MUTEX_ENTER(&rx_quota_mutex
);
7911 rxi_dataQuota
= RX_MAX_QUOTA
;
7912 rxi_availProcs
= rxi_totalMin
= rxi_minDeficit
= 0;
7913 MUTEX_EXIT(&rx_quota_mutex
);
7919 * Routines to implement connection specific data.
7923 rx_KeyCreate(rx_destructor_t rtn
)
7926 MUTEX_ENTER(&rxi_keyCreate_lock
);
7927 key
= rxi_keyCreate_counter
++;
7928 rxi_keyCreate_destructor
= (rx_destructor_t
*)
7929 realloc((void *)rxi_keyCreate_destructor
,
7930 (key
+ 1) * sizeof(rx_destructor_t
));
7931 rxi_keyCreate_destructor
[key
] = rtn
;
7932 MUTEX_EXIT(&rxi_keyCreate_lock
);
7937 rx_SetSpecific(struct rx_connection
*conn
, int key
, void *ptr
)
7940 MUTEX_ENTER(&conn
->conn_data_lock
);
7941 if (!conn
->specific
) {
7942 conn
->specific
= malloc((key
+ 1) * sizeof(void *));
7943 for (i
= 0; i
< key
; i
++)
7944 conn
->specific
[i
] = NULL
;
7945 conn
->nSpecific
= key
+ 1;
7946 conn
->specific
[key
] = ptr
;
7947 } else if (key
>= conn
->nSpecific
) {
7948 conn
->specific
= (void **)
7949 realloc(conn
->specific
, (key
+ 1) * sizeof(void *));
7950 for (i
= conn
->nSpecific
; i
< key
; i
++)
7951 conn
->specific
[i
] = NULL
;
7952 conn
->nSpecific
= key
+ 1;
7953 conn
->specific
[key
] = ptr
;
7955 if (conn
->specific
[key
] && rxi_keyCreate_destructor
[key
])
7956 (*rxi_keyCreate_destructor
[key
]) (conn
->specific
[key
]);
7957 conn
->specific
[key
] = ptr
;
7959 MUTEX_EXIT(&conn
->conn_data_lock
);
7963 rx_SetServiceSpecific(struct rx_service
*svc
, int key
, void *ptr
)
7966 MUTEX_ENTER(&svc
->svc_data_lock
);
7967 if (!svc
->specific
) {
7968 svc
->specific
= malloc((key
+ 1) * sizeof(void *));
7969 for (i
= 0; i
< key
; i
++)
7970 svc
->specific
[i
] = NULL
;
7971 svc
->nSpecific
= key
+ 1;
7972 svc
->specific
[key
] = ptr
;
7973 } else if (key
>= svc
->nSpecific
) {
7974 svc
->specific
= (void **)
7975 realloc(svc
->specific
, (key
+ 1) * sizeof(void *));
7976 for (i
= svc
->nSpecific
; i
< key
; i
++)
7977 svc
->specific
[i
] = NULL
;
7978 svc
->nSpecific
= key
+ 1;
7979 svc
->specific
[key
] = ptr
;
7981 if (svc
->specific
[key
] && rxi_keyCreate_destructor
[key
])
7982 (*rxi_keyCreate_destructor
[key
]) (svc
->specific
[key
]);
7983 svc
->specific
[key
] = ptr
;
7985 MUTEX_EXIT(&svc
->svc_data_lock
);
7989 rx_GetSpecific(struct rx_connection
*conn
, int key
)
7992 MUTEX_ENTER(&conn
->conn_data_lock
);
7993 if (key
>= conn
->nSpecific
)
7996 ptr
= conn
->specific
[key
];
7997 MUTEX_EXIT(&conn
->conn_data_lock
);
8002 rx_GetServiceSpecific(struct rx_service
*svc
, int key
)
8005 MUTEX_ENTER(&svc
->svc_data_lock
);
8006 if (key
>= svc
->nSpecific
)
8009 ptr
= svc
->specific
[key
];
8010 MUTEX_EXIT(&svc
->svc_data_lock
);
8015 #endif /* !KERNEL */
8018 * processStats is a queue used to store the statistics for the local
8019 * process. Its contents are similar to the contents of the rpcStats
8020 * queue on a rx_peer structure, but the actual data stored within
8021 * this queue contains totals across the lifetime of the process (assuming
8022 * the stats have not been reset) - unlike the per peer structures
8023 * which can come and go based upon the peer lifetime.
8026 static struct opr_queue processStats
= { &processStats
, &processStats
};
8029 * peerStats is a queue used to store the statistics for all peer structs.
8030 * Its contents are the union of all the peer rpcStats queues.
8033 static struct opr_queue peerStats
= { &peerStats
, &peerStats
};
8036 * rxi_monitor_processStats is used to turn process wide stat collection
8040 static int rxi_monitor_processStats
= 0;
8043 * rxi_monitor_peerStats is used to turn per peer stat collection on and off
8046 static int rxi_monitor_peerStats
= 0;
8050 rxi_ClearRPCOpStat(rx_function_entry_v1_p rpc_stat
)
8052 rpc_stat
->invocations
= 0;
8053 rpc_stat
->bytes_sent
= 0;
8054 rpc_stat
->bytes_rcvd
= 0;
8055 rpc_stat
->queue_time_sum
.sec
= 0;
8056 rpc_stat
->queue_time_sum
.usec
= 0;
8057 rpc_stat
->queue_time_sum_sqr
.sec
= 0;
8058 rpc_stat
->queue_time_sum_sqr
.usec
= 0;
8059 rpc_stat
->queue_time_min
.sec
= 9999999;
8060 rpc_stat
->queue_time_min
.usec
= 9999999;
8061 rpc_stat
->queue_time_max
.sec
= 0;
8062 rpc_stat
->queue_time_max
.usec
= 0;
8063 rpc_stat
->execution_time_sum
.sec
= 0;
8064 rpc_stat
->execution_time_sum
.usec
= 0;
8065 rpc_stat
->execution_time_sum_sqr
.sec
= 0;
8066 rpc_stat
->execution_time_sum_sqr
.usec
= 0;
8067 rpc_stat
->execution_time_min
.sec
= 9999999;
8068 rpc_stat
->execution_time_min
.usec
= 9999999;
8069 rpc_stat
->execution_time_max
.sec
= 0;
8070 rpc_stat
->execution_time_max
.usec
= 0;
8074 * Given all of the information for a particular rpc
8075 * call, find or create (if requested) the stat structure for the rpc.
8078 * the queue of stats that will be updated with the new value
8080 * @param rxInterface
8081 * a unique number that identifies the rpc interface
8084 * the total number of functions in this interface. this is only
8085 * required if create is true
8088 * if true, this invocation was made to a server
8091 * the ip address of the remote host. this is only required if create
8092 * and addToPeerList are true
8095 * the port of the remote host. this is only required if create
8096 * and addToPeerList are true
8098 * @param addToPeerList
8099 * if != 0, add newly created stat to the global peer list
8102 * if a new stats structure is allocated, the counter will
8103 * be updated with the new number of allocated stat structures.
8104 * only required if create is true
8107 * if no stats structure exists, allocate one
8111 static rx_interface_stat_p
8112 rxi_FindRpcStat(struct opr_queue
*stats
, afs_uint32 rxInterface
,
8113 afs_uint32 totalFunc
, int isServer
, afs_uint32 remoteHost
,
8114 afs_uint32 remotePort
, int addToPeerList
,
8115 unsigned int *counter
, int create
)
8117 rx_interface_stat_p rpc_stat
= NULL
;
8118 struct opr_queue
*cursor
;
8121 * See if there's already a structure for this interface
8124 for (opr_queue_Scan(stats
, cursor
)) {
8125 rpc_stat
= opr_queue_Entry(cursor
, struct rx_interface_stat
, entry
);
8127 if ((rpc_stat
->stats
[0].interfaceId
== rxInterface
)
8128 && (rpc_stat
->stats
[0].remote_is_server
== isServer
))
8132 /* if they didn't ask us to create, we're done */
8134 if (opr_queue_IsEnd(stats
, cursor
))
8140 /* can't proceed without these */
8141 if (!totalFunc
|| !counter
)
8145 * Didn't find a match so allocate a new structure and add it to the
8149 if (opr_queue_IsEnd(stats
, cursor
) || (rpc_stat
== NULL
)
8150 || (rpc_stat
->stats
[0].interfaceId
!= rxInterface
)
8151 || (rpc_stat
->stats
[0].remote_is_server
!= isServer
)) {
8156 sizeof(rx_interface_stat_t
) +
8157 totalFunc
* sizeof(rx_function_entry_v1_t
);
8159 rpc_stat
= rxi_Alloc(space
);
8160 if (rpc_stat
== NULL
)
8163 *counter
+= totalFunc
;
8164 for (i
= 0; i
< totalFunc
; i
++) {
8165 rxi_ClearRPCOpStat(&(rpc_stat
->stats
[i
]));
8166 rpc_stat
->stats
[i
].remote_peer
= remoteHost
;
8167 rpc_stat
->stats
[i
].remote_port
= remotePort
;
8168 rpc_stat
->stats
[i
].remote_is_server
= isServer
;
8169 rpc_stat
->stats
[i
].interfaceId
= rxInterface
;
8170 rpc_stat
->stats
[i
].func_total
= totalFunc
;
8171 rpc_stat
->stats
[i
].func_index
= i
;
8173 opr_queue_Prepend(stats
, &rpc_stat
->entry
);
8174 if (addToPeerList
) {
8175 opr_queue_Prepend(&peerStats
, &rpc_stat
->entryPeers
);
8182 rx_ClearProcessRPCStats(afs_int32 rxInterface
)
8184 rx_interface_stat_p rpc_stat
;
8187 if (rxInterface
== -1)
8190 MUTEX_ENTER(&rx_rpc_stats
);
8191 rpc_stat
= rxi_FindRpcStat(&processStats
, rxInterface
, 0, 0,
8194 totalFunc
= rpc_stat
->stats
[0].func_total
;
8195 for (i
= 0; i
< totalFunc
; i
++)
8196 rxi_ClearRPCOpStat(&(rpc_stat
->stats
[i
]));
8198 MUTEX_EXIT(&rx_rpc_stats
);
8203 rx_ClearPeerRPCStats(afs_int32 rxInterface
, afs_uint32 peerHost
, afs_uint16 peerPort
)
8205 rx_interface_stat_p rpc_stat
;
8207 struct rx_peer
* peer
;
8209 if (rxInterface
== -1)
8212 peer
= rxi_FindPeer(peerHost
, peerPort
, 0);
8216 MUTEX_ENTER(&rx_rpc_stats
);
8217 rpc_stat
= rxi_FindRpcStat(&peer
->rpcStats
, rxInterface
, 0, 1,
8220 totalFunc
= rpc_stat
->stats
[0].func_total
;
8221 for (i
= 0; i
< totalFunc
; i
++)
8222 rxi_ClearRPCOpStat(&(rpc_stat
->stats
[i
]));
8224 MUTEX_EXIT(&rx_rpc_stats
);
8229 rx_CopyProcessRPCStats(afs_uint64 op
)
8231 rx_interface_stat_p rpc_stat
;
8232 rx_function_entry_v1_p rpcop_stat
=
8233 rxi_Alloc(sizeof(rx_function_entry_v1_t
));
8234 int currentFunc
= (op
& MAX_AFS_UINT32
);
8235 afs_int32 rxInterface
= (op
>> 32);
8237 if (!rxi_monitor_processStats
)
8240 if (rxInterface
== -1)
8243 if (rpcop_stat
== NULL
)
8246 MUTEX_ENTER(&rx_rpc_stats
);
8247 rpc_stat
= rxi_FindRpcStat(&processStats
, rxInterface
, 0, 0,
8250 memcpy(rpcop_stat
, &(rpc_stat
->stats
[currentFunc
]),
8251 sizeof(rx_function_entry_v1_t
));
8252 MUTEX_EXIT(&rx_rpc_stats
);
8254 rxi_Free(rpcop_stat
, sizeof(rx_function_entry_v1_t
));
8261 rx_CopyPeerRPCStats(afs_uint64 op
, afs_uint32 peerHost
, afs_uint16 peerPort
)
8263 rx_interface_stat_p rpc_stat
;
8264 rx_function_entry_v1_p rpcop_stat
=
8265 rxi_Alloc(sizeof(rx_function_entry_v1_t
));
8266 int currentFunc
= (op
& MAX_AFS_UINT32
);
8267 afs_int32 rxInterface
= (op
>> 32);
8268 struct rx_peer
*peer
;
8270 if (!rxi_monitor_peerStats
)
8273 if (rxInterface
== -1)
8276 if (rpcop_stat
== NULL
)
8279 peer
= rxi_FindPeer(peerHost
, peerPort
, 0);
8283 MUTEX_ENTER(&rx_rpc_stats
);
8284 rpc_stat
= rxi_FindRpcStat(&peer
->rpcStats
, rxInterface
, 0, 1,
8287 memcpy(rpcop_stat
, &(rpc_stat
->stats
[currentFunc
]),
8288 sizeof(rx_function_entry_v1_t
));
8289 MUTEX_EXIT(&rx_rpc_stats
);
8291 rxi_Free(rpcop_stat
, sizeof(rx_function_entry_v1_t
));
8298 rx_ReleaseRPCStats(void *stats
)
8301 rxi_Free(stats
, sizeof(rx_function_entry_v1_t
));
8305 * Given all of the information for a particular rpc
8306 * call, create (if needed) and update the stat totals for the rpc.
8309 * the queue of stats that will be updated with the new value
8311 * @param rxInterface
8312 * a unique number that identifies the rpc interface
8314 * @param currentFunc
8315 * the index of the function being invoked
8318 * the total number of functions in this interface
8321 * the amount of time this function waited for a thread
8324 * the amount of time this function invocation took to execute
8327 * the number bytes sent by this invocation
8330 * the number bytes received by this invocation
8333 * if true, this invocation was made to a server
8336 * the ip address of the remote host
8339 * the port of the remote host
8341 * @param addToPeerList
8342 * if != 0, add newly created stat to the global peer list
8345 * if a new stats structure is allocated, the counter will
8346 * be updated with the new number of allocated stat structures
8351 rxi_AddRpcStat(struct opr_queue
*stats
, afs_uint32 rxInterface
,
8352 afs_uint32 currentFunc
, afs_uint32 totalFunc
,
8353 struct clock
*queueTime
, struct clock
*execTime
,
8354 afs_uint64 bytesSent
, afs_uint64 bytesRcvd
, int isServer
,
8355 afs_uint32 remoteHost
, afs_uint32 remotePort
,
8356 int addToPeerList
, unsigned int *counter
)
8359 rx_interface_stat_p rpc_stat
;
8361 rpc_stat
= rxi_FindRpcStat(stats
, rxInterface
, totalFunc
, isServer
,
8362 remoteHost
, remotePort
, addToPeerList
, counter
,
8370 * Increment the stats for this function
8373 rpc_stat
->stats
[currentFunc
].invocations
++;
8374 rpc_stat
->stats
[currentFunc
].bytes_sent
+= bytesSent
;
8375 rpc_stat
->stats
[currentFunc
].bytes_rcvd
+= bytesRcvd
;
8376 clock_Add(&rpc_stat
->stats
[currentFunc
].queue_time_sum
, queueTime
);
8377 clock_AddSq(&rpc_stat
->stats
[currentFunc
].queue_time_sum_sqr
, queueTime
);
8378 if (clock_Lt(queueTime
, &rpc_stat
->stats
[currentFunc
].queue_time_min
)) {
8379 rpc_stat
->stats
[currentFunc
].queue_time_min
= *queueTime
;
8381 if (clock_Gt(queueTime
, &rpc_stat
->stats
[currentFunc
].queue_time_max
)) {
8382 rpc_stat
->stats
[currentFunc
].queue_time_max
= *queueTime
;
8384 clock_Add(&rpc_stat
->stats
[currentFunc
].execution_time_sum
, execTime
);
8385 clock_AddSq(&rpc_stat
->stats
[currentFunc
].execution_time_sum_sqr
,
8387 if (clock_Lt(execTime
, &rpc_stat
->stats
[currentFunc
].execution_time_min
)) {
8388 rpc_stat
->stats
[currentFunc
].execution_time_min
= *execTime
;
8390 if (clock_Gt(execTime
, &rpc_stat
->stats
[currentFunc
].execution_time_max
)) {
8391 rpc_stat
->stats
[currentFunc
].execution_time_max
= *execTime
;
8399 rxi_IncrementTimeAndCount(struct rx_peer
*peer
, afs_uint32 rxInterface
,
8400 afs_uint32 currentFunc
, afs_uint32 totalFunc
,
8401 struct clock
*queueTime
, struct clock
*execTime
,
8402 afs_uint64 bytesSent
, afs_uint64 bytesRcvd
,
8406 if (!(rxi_monitor_peerStats
|| rxi_monitor_processStats
))
8409 MUTEX_ENTER(&rx_rpc_stats
);
8411 if (rxi_monitor_peerStats
) {
8412 MUTEX_ENTER(&peer
->peer_lock
);
8413 rxi_AddRpcStat(&peer
->rpcStats
, rxInterface
, currentFunc
, totalFunc
,
8414 queueTime
, execTime
, bytesSent
, bytesRcvd
, isServer
,
8415 peer
->host
, peer
->port
, 1, &rxi_rpc_peer_stat_cnt
);
8416 MUTEX_EXIT(&peer
->peer_lock
);
8419 if (rxi_monitor_processStats
) {
8420 rxi_AddRpcStat(&processStats
, rxInterface
, currentFunc
, totalFunc
,
8421 queueTime
, execTime
, bytesSent
, bytesRcvd
, isServer
,
8422 0xffffffff, 0xffffffff, 0, &rxi_rpc_process_stat_cnt
);
8425 MUTEX_EXIT(&rx_rpc_stats
);
8429 * Increment the times and count for a particular rpc function.
8431 * Traditionally this call was invoked from rxgen stubs. Modern stubs
8432 * call rx_RecordCallStatistics instead, so the public version of this
8433 * function is left purely for legacy callers.
8436 * The peer who invoked the rpc
8438 * @param rxInterface
8439 * A unique number that identifies the rpc interface
8441 * @param currentFunc
8442 * The index of the function being invoked
8445 * The total number of functions in this interface
8448 * The amount of time this function waited for a thread
8451 * The amount of time this function invocation took to execute
8454 * The number bytes sent by this invocation
8457 * The number bytes received by this invocation
8460 * If true, this invocation was made to a server
8464 rx_IncrementTimeAndCount(struct rx_peer
*peer
, afs_uint32 rxInterface
,
8465 afs_uint32 currentFunc
, afs_uint32 totalFunc
,
8466 struct clock
*queueTime
, struct clock
*execTime
,
8467 afs_hyper_t
* bytesSent
, afs_hyper_t
* bytesRcvd
,
8473 sent64
= ((afs_uint64
)bytesSent
->high
<< 32) + bytesSent
->low
;
8474 rcvd64
= ((afs_uint64
)bytesRcvd
->high
<< 32) + bytesRcvd
->low
;
8476 rxi_IncrementTimeAndCount(peer
, rxInterface
, currentFunc
, totalFunc
,
8477 queueTime
, execTime
, sent64
, rcvd64
,
8484 * rx_MarshallProcessRPCStats - marshall an array of rpc statistics
8488 * IN callerVersion - the rpc stat version of the caller.
8490 * IN count - the number of entries to marshall.
8492 * IN stats - pointer to stats to be marshalled.
8494 * OUT ptr - Where to store the marshalled data.
8501 rx_MarshallProcessRPCStats(afs_uint32 callerVersion
, int count
,
8502 rx_function_entry_v1_t
* stats
, afs_uint32
** ptrP
)
8508 * We only support the first version
8510 for (ptr
= *ptrP
, i
= 0; i
< count
; i
++, stats
++) {
8511 *(ptr
++) = stats
->remote_peer
;
8512 *(ptr
++) = stats
->remote_port
;
8513 *(ptr
++) = stats
->remote_is_server
;
8514 *(ptr
++) = stats
->interfaceId
;
8515 *(ptr
++) = stats
->func_total
;
8516 *(ptr
++) = stats
->func_index
;
8517 *(ptr
++) = stats
->invocations
>> 32;
8518 *(ptr
++) = stats
->invocations
& MAX_AFS_UINT32
;
8519 *(ptr
++) = stats
->bytes_sent
>> 32;
8520 *(ptr
++) = stats
->bytes_sent
& MAX_AFS_UINT32
;
8521 *(ptr
++) = stats
->bytes_rcvd
>> 32;
8522 *(ptr
++) = stats
->bytes_rcvd
& MAX_AFS_UINT32
;
8523 *(ptr
++) = stats
->queue_time_sum
.sec
;
8524 *(ptr
++) = stats
->queue_time_sum
.usec
;
8525 *(ptr
++) = stats
->queue_time_sum_sqr
.sec
;
8526 *(ptr
++) = stats
->queue_time_sum_sqr
.usec
;
8527 *(ptr
++) = stats
->queue_time_min
.sec
;
8528 *(ptr
++) = stats
->queue_time_min
.usec
;
8529 *(ptr
++) = stats
->queue_time_max
.sec
;
8530 *(ptr
++) = stats
->queue_time_max
.usec
;
8531 *(ptr
++) = stats
->execution_time_sum
.sec
;
8532 *(ptr
++) = stats
->execution_time_sum
.usec
;
8533 *(ptr
++) = stats
->execution_time_sum_sqr
.sec
;
8534 *(ptr
++) = stats
->execution_time_sum_sqr
.usec
;
8535 *(ptr
++) = stats
->execution_time_min
.sec
;
8536 *(ptr
++) = stats
->execution_time_min
.usec
;
8537 *(ptr
++) = stats
->execution_time_max
.sec
;
8538 *(ptr
++) = stats
->execution_time_max
.usec
;
8544 * rx_RetrieveProcessRPCStats - retrieve all of the rpc statistics for
8549 * IN callerVersion - the rpc stat version of the caller
8551 * OUT myVersion - the rpc stat version of this function
8553 * OUT clock_sec - local time seconds
8555 * OUT clock_usec - local time microseconds
8557 * OUT allocSize - the number of bytes allocated to contain stats
8559 * OUT statCount - the number stats retrieved from this process.
8561 * OUT stats - the actual stats retrieved from this process.
8565 * Returns void. If successful, stats will != NULL.
8569 rx_RetrieveProcessRPCStats(afs_uint32 callerVersion
, afs_uint32
* myVersion
,
8570 afs_uint32
* clock_sec
, afs_uint32
* clock_usec
,
8571 size_t * allocSize
, afs_uint32
* statCount
,
8572 afs_uint32
** stats
)
8582 *myVersion
= RX_STATS_RETRIEVAL_VERSION
;
8585 * Check to see if stats are enabled
8588 MUTEX_ENTER(&rx_rpc_stats
);
8589 if (!rxi_monitor_processStats
) {
8590 MUTEX_EXIT(&rx_rpc_stats
);
8594 clock_GetTime(&now
);
8595 *clock_sec
= now
.sec
;
8596 *clock_usec
= now
.usec
;
8599 * Allocate the space based upon the caller version
8601 * If the client is at an older version than we are,
8602 * we return the statistic data in the older data format, but
8603 * we still return our version number so the client knows we
8604 * are maintaining more data than it can retrieve.
8607 if (callerVersion
>= RX_STATS_RETRIEVAL_FIRST_EDITION
) {
8608 space
= rxi_rpc_process_stat_cnt
* sizeof(rx_function_entry_v1_t
);
8609 *statCount
= rxi_rpc_process_stat_cnt
;
8612 * This can't happen yet, but in the future version changes
8613 * can be handled by adding additional code here
8617 if (space
> (size_t) 0) {
8619 ptr
= *stats
= rxi_Alloc(space
);
8622 struct opr_queue
*cursor
;
8624 for (opr_queue_Scan(&processStats
, cursor
)) {
8625 struct rx_interface_stat
*rpc_stat
=
8626 opr_queue_Entry(cursor
, struct rx_interface_stat
, entry
);
8628 * Copy the data based upon the caller version
8630 rx_MarshallProcessRPCStats(callerVersion
,
8631 rpc_stat
->stats
[0].func_total
,
8632 rpc_stat
->stats
, &ptr
);
8638 MUTEX_EXIT(&rx_rpc_stats
);
8643 * rx_RetrievePeerRPCStats - retrieve all of the rpc statistics for the peers
8647 * IN callerVersion - the rpc stat version of the caller
8649 * OUT myVersion - the rpc stat version of this function
8651 * OUT clock_sec - local time seconds
8653 * OUT clock_usec - local time microseconds
8655 * OUT allocSize - the number of bytes allocated to contain stats
8657 * OUT statCount - the number of stats retrieved from the individual
8660 * OUT stats - the actual stats retrieved from the individual peer structures.
8664 * Returns void. If successful, stats will != NULL.
8668 rx_RetrievePeerRPCStats(afs_uint32 callerVersion
, afs_uint32
* myVersion
,
8669 afs_uint32
* clock_sec
, afs_uint32
* clock_usec
,
8670 size_t * allocSize
, afs_uint32
* statCount
,
8671 afs_uint32
** stats
)
8681 *myVersion
= RX_STATS_RETRIEVAL_VERSION
;
8684 * Check to see if stats are enabled
8687 MUTEX_ENTER(&rx_rpc_stats
);
8688 if (!rxi_monitor_peerStats
) {
8689 MUTEX_EXIT(&rx_rpc_stats
);
8693 clock_GetTime(&now
);
8694 *clock_sec
= now
.sec
;
8695 *clock_usec
= now
.usec
;
8698 * Allocate the space based upon the caller version
8700 * If the client is at an older version than we are,
8701 * we return the statistic data in the older data format, but
8702 * we still return our version number so the client knows we
8703 * are maintaining more data than it can retrieve.
8706 if (callerVersion
>= RX_STATS_RETRIEVAL_FIRST_EDITION
) {
8707 space
= rxi_rpc_peer_stat_cnt
* sizeof(rx_function_entry_v1_t
);
8708 *statCount
= rxi_rpc_peer_stat_cnt
;
8711 * This can't happen yet, but in the future version changes
8712 * can be handled by adding additional code here
8716 if (space
> (size_t) 0) {
8718 ptr
= *stats
= rxi_Alloc(space
);
8721 struct opr_queue
*cursor
;
8723 for (opr_queue_Scan(&peerStats
, cursor
)) {
8724 struct rx_interface_stat
*rpc_stat
8725 = opr_queue_Entry(cursor
, struct rx_interface_stat
,
8729 * Copy the data based upon the caller version
8731 rx_MarshallProcessRPCStats(callerVersion
,
8732 rpc_stat
->stats
[0].func_total
,
8733 rpc_stat
->stats
, &ptr
);
8739 MUTEX_EXIT(&rx_rpc_stats
);
8744 * rx_FreeRPCStats - free memory allocated by
8745 * rx_RetrieveProcessRPCStats and rx_RetrievePeerRPCStats
8749 * IN stats - stats previously returned by rx_RetrieveProcessRPCStats or
8750 * rx_RetrievePeerRPCStats
8752 * IN allocSize - the number of bytes in stats.
8760 rx_FreeRPCStats(afs_uint32
* stats
, size_t allocSize
)
8762 rxi_Free(stats
, allocSize
);
8766 * rx_queryProcessRPCStats - see if process rpc stat collection is
8767 * currently enabled.
8773 * Returns 0 if stats are not enabled != 0 otherwise
8777 rx_queryProcessRPCStats(void)
8780 MUTEX_ENTER(&rx_rpc_stats
);
8781 rc
= rxi_monitor_processStats
;
8782 MUTEX_EXIT(&rx_rpc_stats
);
8787 * rx_queryPeerRPCStats - see if peer stat collection is currently enabled.
8793 * Returns 0 if stats are not enabled != 0 otherwise
8797 rx_queryPeerRPCStats(void)
8800 MUTEX_ENTER(&rx_rpc_stats
);
8801 rc
= rxi_monitor_peerStats
;
8802 MUTEX_EXIT(&rx_rpc_stats
);
8807 * rx_enableProcessRPCStats - begin rpc stat collection for entire process
8817 rx_enableProcessRPCStats(void)
8819 MUTEX_ENTER(&rx_rpc_stats
);
8820 rx_enable_stats
= 1;
8821 rxi_monitor_processStats
= 1;
8822 MUTEX_EXIT(&rx_rpc_stats
);
8826 * rx_enablePeerRPCStats - begin rpc stat collection per peer structure
8836 rx_enablePeerRPCStats(void)
8838 MUTEX_ENTER(&rx_rpc_stats
);
8839 rx_enable_stats
= 1;
8840 rxi_monitor_peerStats
= 1;
8841 MUTEX_EXIT(&rx_rpc_stats
);
8845 * rx_disableProcessRPCStats - stop rpc stat collection for entire process
8855 rx_disableProcessRPCStats(void)
8857 struct opr_queue
*cursor
, *store
;
8860 MUTEX_ENTER(&rx_rpc_stats
);
8863 * Turn off process statistics and if peer stats is also off, turn
8867 rxi_monitor_processStats
= 0;
8868 if (rxi_monitor_peerStats
== 0) {
8869 rx_enable_stats
= 0;
8872 for (opr_queue_ScanSafe(&processStats
, cursor
, store
)) {
8873 unsigned int num_funcs
= 0;
8874 struct rx_interface_stat
*rpc_stat
8875 = opr_queue_Entry(cursor
, struct rx_interface_stat
, entry
);
8877 opr_queue_Remove(&rpc_stat
->entry
);
8879 num_funcs
= rpc_stat
->stats
[0].func_total
;
8881 sizeof(rx_interface_stat_t
) +
8882 rpc_stat
->stats
[0].func_total
* sizeof(rx_function_entry_v1_t
);
8884 rxi_Free(rpc_stat
, space
);
8885 rxi_rpc_process_stat_cnt
-= num_funcs
;
8887 MUTEX_EXIT(&rx_rpc_stats
);
8891 * rx_disablePeerRPCStats - stop rpc stat collection for peers
8901 rx_disablePeerRPCStats(void)
8903 struct rx_peer
**peer_ptr
, **peer_end
;
8907 * Turn off peer statistics and if process stats is also off, turn
8911 rxi_monitor_peerStats
= 0;
8912 if (rxi_monitor_processStats
== 0) {
8913 rx_enable_stats
= 0;
8916 for (peer_ptr
= &rx_peerHashTable
[0], peer_end
=
8917 &rx_peerHashTable
[rx_hashTableSize
]; peer_ptr
< peer_end
;
8919 struct rx_peer
*peer
, *next
, *prev
;
8921 MUTEX_ENTER(&rx_peerHashTable_lock
);
8922 MUTEX_ENTER(&rx_rpc_stats
);
8923 for (prev
= peer
= *peer_ptr
; peer
; peer
= next
) {
8925 code
= MUTEX_TRYENTER(&peer
->peer_lock
);
8928 struct opr_queue
*cursor
, *store
;
8930 if (prev
== *peer_ptr
) {
8941 MUTEX_EXIT(&rx_peerHashTable_lock
);
8943 for (opr_queue_ScanSafe(&peer
->rpcStats
, cursor
, store
)) {
8944 unsigned int num_funcs
= 0;
8945 struct rx_interface_stat
*rpc_stat
8946 = opr_queue_Entry(cursor
, struct rx_interface_stat
,
8949 opr_queue_Remove(&rpc_stat
->entry
);
8950 opr_queue_Remove(&rpc_stat
->entryPeers
);
8951 num_funcs
= rpc_stat
->stats
[0].func_total
;
8953 sizeof(rx_interface_stat_t
) +
8954 rpc_stat
->stats
[0].func_total
*
8955 sizeof(rx_function_entry_v1_t
);
8957 rxi_Free(rpc_stat
, space
);
8958 rxi_rpc_peer_stat_cnt
-= num_funcs
;
8960 MUTEX_EXIT(&peer
->peer_lock
);
8962 MUTEX_ENTER(&rx_peerHashTable_lock
);
8972 MUTEX_EXIT(&rx_rpc_stats
);
8973 MUTEX_EXIT(&rx_peerHashTable_lock
);
8978 * rx_clearProcessRPCStats - clear the contents of the rpc stats according
8983 * IN clearFlag - flag indicating which stats to clear
8991 rx_clearProcessRPCStats(afs_uint32 clearFlag
)
8993 struct opr_queue
*cursor
;
8995 MUTEX_ENTER(&rx_rpc_stats
);
8997 for (opr_queue_Scan(&processStats
, cursor
)) {
8998 unsigned int num_funcs
= 0, i
;
8999 struct rx_interface_stat
*rpc_stat
9000 = opr_queue_Entry(cursor
, struct rx_interface_stat
, entry
);
9002 num_funcs
= rpc_stat
->stats
[0].func_total
;
9003 for (i
= 0; i
< num_funcs
; i
++) {
9004 if (clearFlag
& AFS_RX_STATS_CLEAR_INVOCATIONS
) {
9005 rpc_stat
->stats
[i
].invocations
= 0;
9007 if (clearFlag
& AFS_RX_STATS_CLEAR_BYTES_SENT
) {
9008 rpc_stat
->stats
[i
].bytes_sent
= 0;
9010 if (clearFlag
& AFS_RX_STATS_CLEAR_BYTES_RCVD
) {
9011 rpc_stat
->stats
[i
].bytes_rcvd
= 0;
9013 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_SUM
) {
9014 rpc_stat
->stats
[i
].queue_time_sum
.sec
= 0;
9015 rpc_stat
->stats
[i
].queue_time_sum
.usec
= 0;
9017 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_SQUARE
) {
9018 rpc_stat
->stats
[i
].queue_time_sum_sqr
.sec
= 0;
9019 rpc_stat
->stats
[i
].queue_time_sum_sqr
.usec
= 0;
9021 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_MIN
) {
9022 rpc_stat
->stats
[i
].queue_time_min
.sec
= 9999999;
9023 rpc_stat
->stats
[i
].queue_time_min
.usec
= 9999999;
9025 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_MAX
) {
9026 rpc_stat
->stats
[i
].queue_time_max
.sec
= 0;
9027 rpc_stat
->stats
[i
].queue_time_max
.usec
= 0;
9029 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_SUM
) {
9030 rpc_stat
->stats
[i
].execution_time_sum
.sec
= 0;
9031 rpc_stat
->stats
[i
].execution_time_sum
.usec
= 0;
9033 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_SQUARE
) {
9034 rpc_stat
->stats
[i
].execution_time_sum_sqr
.sec
= 0;
9035 rpc_stat
->stats
[i
].execution_time_sum_sqr
.usec
= 0;
9037 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_MIN
) {
9038 rpc_stat
->stats
[i
].execution_time_min
.sec
= 9999999;
9039 rpc_stat
->stats
[i
].execution_time_min
.usec
= 9999999;
9041 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_MAX
) {
9042 rpc_stat
->stats
[i
].execution_time_max
.sec
= 0;
9043 rpc_stat
->stats
[i
].execution_time_max
.usec
= 0;
9048 MUTEX_EXIT(&rx_rpc_stats
);
9052 * rx_clearPeerRPCStats - clear the contents of the rpc stats according
9057 * IN clearFlag - flag indicating which stats to clear
9065 rx_clearPeerRPCStats(afs_uint32 clearFlag
)
9067 struct opr_queue
*cursor
;
9069 MUTEX_ENTER(&rx_rpc_stats
);
9071 for (opr_queue_Scan(&peerStats
, cursor
)) {
9072 unsigned int num_funcs
, i
;
9073 struct rx_interface_stat
*rpc_stat
9074 = opr_queue_Entry(cursor
, struct rx_interface_stat
, entryPeers
);
9076 num_funcs
= rpc_stat
->stats
[0].func_total
;
9077 for (i
= 0; i
< num_funcs
; i
++) {
9078 if (clearFlag
& AFS_RX_STATS_CLEAR_INVOCATIONS
) {
9079 rpc_stat
->stats
[i
].invocations
= 0;
9081 if (clearFlag
& AFS_RX_STATS_CLEAR_BYTES_SENT
) {
9082 rpc_stat
->stats
[i
].bytes_sent
= 0;
9084 if (clearFlag
& AFS_RX_STATS_CLEAR_BYTES_RCVD
) {
9085 rpc_stat
->stats
[i
].bytes_rcvd
= 0;
9087 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_SUM
) {
9088 rpc_stat
->stats
[i
].queue_time_sum
.sec
= 0;
9089 rpc_stat
->stats
[i
].queue_time_sum
.usec
= 0;
9091 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_SQUARE
) {
9092 rpc_stat
->stats
[i
].queue_time_sum_sqr
.sec
= 0;
9093 rpc_stat
->stats
[i
].queue_time_sum_sqr
.usec
= 0;
9095 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_MIN
) {
9096 rpc_stat
->stats
[i
].queue_time_min
.sec
= 9999999;
9097 rpc_stat
->stats
[i
].queue_time_min
.usec
= 9999999;
9099 if (clearFlag
& AFS_RX_STATS_CLEAR_QUEUE_TIME_MAX
) {
9100 rpc_stat
->stats
[i
].queue_time_max
.sec
= 0;
9101 rpc_stat
->stats
[i
].queue_time_max
.usec
= 0;
9103 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_SUM
) {
9104 rpc_stat
->stats
[i
].execution_time_sum
.sec
= 0;
9105 rpc_stat
->stats
[i
].execution_time_sum
.usec
= 0;
9107 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_SQUARE
) {
9108 rpc_stat
->stats
[i
].execution_time_sum_sqr
.sec
= 0;
9109 rpc_stat
->stats
[i
].execution_time_sum_sqr
.usec
= 0;
9111 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_MIN
) {
9112 rpc_stat
->stats
[i
].execution_time_min
.sec
= 9999999;
9113 rpc_stat
->stats
[i
].execution_time_min
.usec
= 9999999;
9115 if (clearFlag
& AFS_RX_STATS_CLEAR_EXEC_TIME_MAX
) {
9116 rpc_stat
->stats
[i
].execution_time_max
.sec
= 0;
9117 rpc_stat
->stats
[i
].execution_time_max
.usec
= 0;
9122 MUTEX_EXIT(&rx_rpc_stats
);
9126 * rxi_rxstat_userok points to a routine that returns 1 if the caller
9127 * is authorized to enable/disable/clear RX statistics.
9129 static int (*rxi_rxstat_userok
) (struct rx_call
* call
) = NULL
;
9132 rx_SetRxStatUserOk(int (*proc
) (struct rx_call
* call
))
9134 rxi_rxstat_userok
= proc
;
9138 rx_RxStatUserOk(struct rx_call
*call
)
9140 if (!rxi_rxstat_userok
)
9142 return rxi_rxstat_userok(call
);
9147 * DllMain() -- Entry-point function called by the DllMainCRTStartup()
9148 * function in the MSVC runtime DLL (msvcrt.dll).
9150 * Note: the system serializes calls to this function.
9153 DllMain(HINSTANCE dllInstHandle
, /* instance handle for this DLL module */
9154 DWORD reason
, /* reason function is being called */
9155 LPVOID reserved
) /* reserved for future use */
9158 case DLL_PROCESS_ATTACH
:
9159 /* library is being attached to a process */
9163 case DLL_PROCESS_DETACH
:
9170 #endif /* AFS_NT40_ENV */
9173 int rx_DumpCalls(FILE *outputFile
, char *cookie
)
9175 #ifdef RXDEBUG_PACKET
9176 #ifdef KDUMP_RX_LOCK
9177 struct rx_call_rx_lock
*c
;
9184 #define RXDPRINTF sprintf
9185 #define RXDPRINTOUT output
9187 #define RXDPRINTF fprintf
9188 #define RXDPRINTOUT outputFile
9191 RXDPRINTF(RXDPRINTOUT
, "%s - Start dumping all Rx Calls - count=%u\r\n", cookie
, rx_stats
.nCallStructs
);
9193 WriteFile(outputFile
, output
, (DWORD
)strlen(output
), &zilch
, NULL
);
9196 for (c
= rx_allCallsp
; c
; c
= c
->allNextp
) {
9197 u_short rqc
, tqc
, iovqc
;
9199 MUTEX_ENTER(&c
->lock
);
9200 rqc
= opr_queue_Count(&c
->rq
);
9201 tqc
= opr_queue_Count(&c
->tq
);
9202 iovqc
= opr_queue_Count(&c
->app
.iovq
);
9204 RXDPRINTF(RXDPRINTOUT
, "%s - call=0x%p, id=%u, state=%u, mode=%u, conn=%p, epoch=%u, cid=%u, callNum=%u, connFlags=0x%x, flags=0x%x, "
9205 "rqc=%u,%u, tqc=%u,%u, iovqc=%u,%u, "
9206 "lstatus=%u, rstatus=%u, error=%d, timeout=%u, "
9207 "resendEvent=%d, keepAliveEvt=%d, delayedAckEvt=%d, delayedAbortEvt=%d, abortCode=%d, abortCount=%d, "
9208 "lastSendTime=%u, lastRecvTime=%u"
9209 #ifdef RX_ENABLE_LOCKS
9212 #ifdef RX_REFCOUNT_CHECK
9213 ", refCountBegin=%u, refCountResend=%u, refCountDelay=%u, "
9214 "refCountAlive=%u, refCountPacket=%u, refCountSend=%u, refCountAckAll=%u, refCountAbort=%u"
9217 cookie
, c
, c
->call_id
, (afs_uint32
)c
->state
, (afs_uint32
)c
->app
.mode
, c
->conn
, c
->conn
?c
->conn
->epoch
:0, c
->conn
?c
->conn
->cid
:0,
9218 c
->callNumber
?*c
->callNumber
:0, c
->conn
?c
->conn
->flags
:0, c
->flags
,
9219 (afs_uint32
)c
->rqc
, (afs_uint32
)rqc
, (afs_uint32
)c
->tqc
, (afs_uint32
)tqc
, (afs_uint32
)c
->iovqc
, (afs_uint32
)iovqc
,
9220 (afs_uint32
)c
->localStatus
, (afs_uint32
)c
->remoteStatus
, c
->error
, c
->timeout
,
9221 c
->resendEvent
?1:0, c
->keepAliveEvent
?1:0, c
->delayedAckEvent
?1:0, c
->delayedAbortEvent
?1:0,
9222 c
->abortCode
, c
->abortCount
, c
->lastSendTime
, c
->lastReceiveTime
9223 #ifdef RX_ENABLE_LOCKS
9224 , (afs_uint32
)c
->refCount
9226 #ifdef RX_REFCOUNT_CHECK
9227 , c
->refCDebug
[0],c
->refCDebug
[1],c
->refCDebug
[2],c
->refCDebug
[3],c
->refCDebug
[4],c
->refCDebug
[5],c
->refCDebug
[6],c
->refCDebug
[7]
9230 MUTEX_EXIT(&c
->lock
);
9233 WriteFile(outputFile
, output
, (DWORD
)strlen(output
), &zilch
, NULL
);
9236 RXDPRINTF(RXDPRINTOUT
, "%s - End dumping all Rx Calls\r\n", cookie
);
9238 WriteFile(outputFile
, output
, (DWORD
)strlen(output
), &zilch
, NULL
);
9240 #endif /* RXDEBUG_PACKET */