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 #include <afsconfig.h>
11 #include "afs/param.h"
14 #include "rx/rx_kcommon.h"
15 #include "rx_atomic.h"
16 #include "rx_internal.h"
18 #define SECONDS_TO_SLEEP 0
19 #define NANO_SECONDS_TO_SLEEP 100000000 /* 100 milliseconds */
20 #define LOOPS_PER_WAITCHECK 10 /* once per second */
27 unsigned short usr_rx_port = 0;
29 struct usr_ifnet *usr_ifnet = NULL;
30 struct usr_in_ifaddr *usr_in_ifaddr = NULL;
32 void rxk_InitializeSocket(void);
33 extern int afs_osi_CheckTimedWaits(void);
36 afs_rxevent_daemon(void)
44 tv.tv_sec = SECONDS_TO_SLEEP;
45 tv.tv_nsec = NANO_SECONDS_TO_SLEEP;
46 usr_thread_sleep(&tv);
48 * Check for shutdown, don't try to stop the listener
50 if (afs_termState == AFSOP_STOP_RXEVENT
51 || afs_termState == AFSOP_STOP_RXK_LISTENER) {
53 afs_termState = AFSOP_STOP_COMPLETE;
54 afs_osi_Wakeup(&afs_termState);
57 rxevent_RaiseEvents(&temp);
58 if (++i >= LOOPS_PER_WAITCHECK) {
60 afs_osi_CheckTimedWaits();
66 /* Loop to listen on a socket. Return setting *newcallp if this
67 * thread should become a server thread. */
69 rxi_ListenerProc(osi_socket usockp, int *tnop, struct rx_call **newcallp)
77 * Use the rxk_GetPacketProc and rxk_PacketArrivalProc routines
78 * to allocate rx_packet buffers and pass them to the RX layer
82 /* See if a check for additional packets was issued */
85 tp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
86 usr_assert(tp != NULL);
87 rc = rxi_ReadPacket(usockp, tp, &host, &port);
89 tp = rxi_ReceivePacket(tp, usockp, host, port, tnop, newcallp);
90 if (newcallp && *newcallp) {
100 if (afs_termState == AFSOP_STOP_RXEVENT) {
101 afs_termState = AFSOP_STOP_RXK_LISTENER;
102 afs_osi_Wakeup(&afs_termState);
107 /* This is the listener process request loop. The listener process loop
108 * becomes a server thread when rxi_ListenerProc returns, and stays
109 * server thread until rxi_ServerProc returns. */
114 osi_socket sock = (osi_socket) rx_socket;
115 struct rx_call *newcall;
116 struct usr_socket *usockp;
119 * Initialize the rx_socket and start the receiver threads
121 rxk_InitializeSocket();
123 usockp = (struct usr_socket *)rx_socket;
124 assert(usockp != NULL);
130 rxi_ListenerProc(sock, &threadID, &newcall);
131 /* assert(threadID != -1); */
132 /* assert(newcall != NULL); */
133 sock = OSI_NULLSOCKET;
134 rxi_ServerProc(threadID, newcall, &sock);
135 if (sock == OSI_NULLSOCKET) {
142 /* This is the server process request loop. The server process loop
143 * becomes a listener thread when rxi_ServerProc returns, and stays
144 * listener thread until rxi_ListenerProc returns. */
146 rx_ServerProc(void *unused)
150 struct rx_call *newcall = NULL;
152 rxi_MorePackets(rx_maxReceiveWindow + 2); /* alloc more packets */
153 rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */
154 /* threadID is used for making decisions in GetCall. Get it by bumping
155 * number of threads handling incoming calls */
156 threadID = rxi_availProcs++;
159 sock = OSI_NULLSOCKET;
160 rxi_ServerProc(threadID, newcall, &sock);
161 if (sock == OSI_NULLSOCKET) {
166 rxi_ListenerProc(sock, &threadID, &newcall);
167 /* assert(threadID != -1); */
168 /* assert(newcall != NULL); */
174 * At this point, RX wants a socket, but still has not initialized the
175 * rx_port variable or the pointers to the packet allocater and arrival
176 * routines. Allocate the socket buffer here, but don't open it until
177 * we start the receiver threads.
180 rxk_NewSocketHost(afs_uint32 ahost, short aport)
182 struct usr_socket *usockp;
184 usockp = afs_osi_Alloc(sizeof(struct usr_socket));
185 usr_assert(usockp != NULL);
189 return (osi_socket *)usockp;
193 rxk_NewSocket(short aport)
195 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
199 * This routine is called from rxk_Listener. By this time rx_port
200 * is set to 7001 and rx_socket points to the socket buffer
201 * we allocated in rxk_NewSocket. Now is the time to bind our
202 * socket and start the receiver threads.
205 rxk_InitializeSocket(void)
208 #ifdef AFS_USR_AIX_ENV
209 unsigned long len, optval, optval0, optlen;
210 #else /* AFS_USR_AIX_ENV */
211 socklen_t len, optlen;
213 #endif /* AFS_USR_AIX_ENV */
214 struct usr_socket *usockp;
215 struct sockaddr_in lcladdr;
217 usr_assert(rx_socket != NULL);
218 usockp = (struct usr_socket *)rx_socket;
220 sock = socket(PF_INET, SOCK_DGRAM, 0);
221 usr_assert(sock >= 0);
223 memset((void *)&lcladdr, 0, sizeof(struct sockaddr_in));
224 lcladdr.sin_family = AF_INET;
225 lcladdr.sin_port = htons(usr_rx_port);
226 lcladdr.sin_addr.s_addr = INADDR_ANY;
227 rc = bind(sock, (struct sockaddr *)&lcladdr, sizeof(struct sockaddr_in));
229 len = sizeof(struct sockaddr_in);
230 rc = getsockname(sock, (struct sockaddr *)&lcladdr, &len);
232 #ifdef AFS_USR_LINUX_ENV
238 rc = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&optval,
241 optlen = sizeof(optval);
242 rc = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&optval, &optlen);
244 /* usr_assert(optval == optval0); */
245 #ifdef AFS_USR_LINUX_ENV
251 rc = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&optval,
254 optlen = sizeof(optval);
255 rc = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&optval, &optlen);
257 /* usr_assert(optval == optval0); */
259 #ifdef AFS_USR_AIX_ENV
261 rc = setsockopt(sock, SOL_SOCKET, SO_CKSUMRECV, (void *)&optval,
264 #endif /* AFS_USR_AIX_ENV */
267 fcntl(sock, F_SETFD, FD_CLOEXEC);
271 usockp->port = lcladdr.sin_port;
274 * Set the value of rx_port to reflect the address we actually
275 * are listening on, since the kernel is probably already using 7001.
277 rx_port = usockp->port;
281 rxk_FreeSocket(struct usr_socket *sockp)
287 osi_StopListener(void)
289 rxk_FreeSocket((struct usr_socket *)rx_socket);
293 osi_NetSend(osi_socket sockp, struct sockaddr_in *addr, struct iovec *iov,
294 int nio, afs_int32 size, int stack)
298 struct usr_socket *usockp = (struct usr_socket *)sockp;
300 struct iovec tmpiov[64];
303 * The header is in the first iovec
305 usr_assert(nio > 0 && nio <= 64);
306 for (i = 0; i < nio; i++) {
307 tmpiov[i].iov_base = iov[i].iov_base;
308 tmpiov[i].iov_len = iov[i].iov_len;
311 memset(&msg, 0, sizeof(msg));
312 msg.msg_name = (void *)addr;
313 msg.msg_namelen = sizeof(struct sockaddr_in);
314 msg.msg_iov = &tmpiov[0];
315 msg.msg_iovlen = nio;
317 rc = sendmsg(usockp->sock, &msg, 0);
321 usr_assert(rc == size);
327 shutdown_rxkernel(void)
344 rxi_Recvmsg(osi_socket socket, struct msghdr *msg_p, int flags)
346 struct usr_socket *usock = (struct usr_socket *)socket;
349 ret = recvmsg(usock->sock, msg_p, flags);
350 } while (ret == -1 && errno == EAGAIN);