1 /* Copyright Transarc Corporation 1998 - All Rights Reserved.
3 * rx_kcommon.c - Common kernel RX code for all system types.
6 #include "../afs/param.h"
7 #include "../rx/rx_kcommon.h"
10 #include "../h/tihdr.h"
12 #include "../afs/hpux_110.h"
14 #include "../afsint/afsint.h"
16 afs_int32 rxi_Findcbi();
17 extern struct interfaceAddr afs_cb_interface;
19 #ifndef RXK_LISTENER_ENV
20 int (*rxk_GetPacketProc)(); /* set to packet allocation procedure */
21 int (*rxk_PacketArrivalProc)();
24 rxk_ports_t rxk_ports;
25 rxk_portRocks_t rxk_portRocks;
29 /* add a port to the monitored list, port # is in network order */
30 static int rxk_AddPort(u_short aport, char * arock)
33 unsigned short *tsp, ts;
36 zslot = -1; /* look for an empty slot simultaneously */
37 for(i=0,tsp=rxk_ports;i<MAXRXPORTS;i++,tsp++) {
38 if (((ts = *tsp) == 0) && (zslot == -1))
44 /* otherwise allocate a new port slot */
45 if (zslot < 0) return E2BIG; /* all full */
46 rxk_ports[zslot] = aport;
47 rxk_portRocks[zslot] = arock;
51 /* remove as port from the monitored list, port # is in network order */
55 register unsigned short *tsp;
57 for(i=0,tsp=rxk_ports;i<MAXRXPORTS;i++,tsp++) {
59 /* found it, adjust ref count and free the port reference if all gone */
64 /* otherwise port not found */
68 void rxk_shutdownPorts(void)
71 for (i=0; i<MAXRXPORTS;i++) {
74 #if ! defined(AFS_SUN5_ENV) && ! defined(UKERNEL) && ! defined(RXK_LISTENER_ENV)
75 soclose((struct socket *)rxk_portRocks[i]);
77 rxk_portRocks[i] = (char *)0;
82 osi_socket rxi_GetUDPSocket(port)
85 struct osi_socket *sockp;
86 sockp = (struct osi_socket *) rxk_NewSocket(port);
87 if (sockp == (struct osi_socket *) 0) return OSI_NULLSOCKET;
88 rxk_AddPort(port, (char *) sockp);
89 return (osi_socket)sockp;
93 void osi_Panic(msg, a1, a2, a3)
97 msg = "Unknown AFS panic";
99 printf(msg, a1, a2, a3);
100 #ifdef AFS_LINUX20_ENV
101 *((char*)0xffffffff) = 42;
108 * osi_utoa() - write the NUL-terminated ASCII decimal form of the given
109 * unsigned long value into the given buffer. Returns 0 on success,
110 * and a value less than 0 on failure. The contents of the buffer is
111 * defined only on success.
115 osi_utoa(char *buf, size_t len, unsigned long val)
117 long k; /* index of first byte of string value */
119 /* we definitely need room for at least one digit and NUL */
125 /* compute the string form from the high end of the buffer */
128 for (k = len - 2; k >= 0; k--) {
129 buf[k] = val % 10 + '0';
136 /* did we finish converting val to string form? */
142 /* this should never happen */
148 /* this should never happen */
154 /* if necessary, relocate string to beginning of buf[] */
159 * We need to achieve the effect of calling
161 * memmove(buf, &buf[k], len - k);
163 * However, since memmove() is not available in all
164 * kernels, we explicitly do an appropriate copy.
170 while((*dst++ = *src++) != '\0')
178 * osi_AssertFailK() -- used by the osi_Assert() macro.
180 * It essentially does
182 * osi_Panic("assertion failed: %s, file: %s, line: %d", expr, file, line);
184 * Since the kernel version of osi_Panic() only passes its first
185 * argument to the native panic(), we construct a single string and hand
186 * that to osi_Panic().
189 osi_AssertFailK(const char *expr, const char *file, int line)
191 static const char msg0[] = "assertion failed: ";
192 static const char msg1[] = ", file: ";
193 static const char msg2[] = ", line: ";
194 static const char msg3[] = "\n";
197 * These buffers add up to 1K, which is a pleasantly nice round
198 * value, but probably not vital.
203 /* check line number conversion */
205 if (osi_utoa(linebuf, sizeof linebuf, line) < 0) {
206 osi_Panic("osi_AssertFailK: error in osi_utoa()\n");
211 #define ADDBUF(BUF, STR) \
212 if (strlen(BUF) + strlen((char *)(STR)) + 1 <= sizeof BUF) { \
213 strcat(BUF, (char *)(STR)); \
222 ADDBUF(buf, linebuf);
231 /* This is the server process request loop. Kernel server
232 * processes never become listener threads */
237 rxi_MorePackets(rx_maxReceiveWindow+2); /* alloc more packets */
238 rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */
239 /* threadID is used for making decisions in GetCall. Get it by bumping
240 * number of threads handling incoming calls */
241 threadID = rxi_availProcs++;
243 #ifdef RX_ENABLE_LOCKS
245 #endif /* RX_ENABLE_LOCKS */
246 rxi_ServerProc(threadID, NULL, NULL);
247 #ifdef RX_ENABLE_LOCKS
249 #endif /* RX_ENABLE_LOCKS */
251 #endif /* !UKERNEL */
253 #ifndef RXK_LISTENER_ENV
254 static int MyPacketProc(ahandle, asize)
255 int asize; /* this includes the Rx header */
258 register struct rx_packet *tp;
260 /* If this is larger than we expected, increase rx_maxReceiveDataSize */
261 /* If we can't scrounge enough cbufs, then we have to drop the packet,
262 * but we should set a flag so we magic up some more at our leisure.
265 if ((asize >= 0) && (asize <= RX_MAX_PACKET_SIZE)) {
266 tp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
267 if (tp && (tp->length + RX_HEADER_SIZE) < asize ) {
268 if (0 < rxi_AllocDataBuf(tp, asize - (tp->length + RX_HEADER_SIZE),
269 RX_PACKET_CLASS_RECV_CBUF)) {
272 MUTEX_ENTER(&rx_stats_mutex);
273 rx_stats.noPacketBuffersOnRead++;
274 MUTEX_EXIT(&rx_stats_mutex);
279 * XXX if packet is too long for our buffer,
280 * should do this at a higher layer and let other
281 * end know we're losing.
283 MUTEX_ENTER(&rx_stats_mutex);
284 rx_stats.bogusPacketOnRead++;
285 MUTEX_EXIT(&rx_stats_mutex);
286 /* I DON"T LIKE THIS PRINTF -- PRINTFS MAKE THINGS VERY VERY SLOOWWW */
287 printf("rx: packet dropped: bad ulen=%d\n", asize);
292 /* otherwise we have a packet, set appropriate values */
293 *ahandle = (char *) tp;
297 static int MyArrivalProc(ahandle, afrom, arock, asize)
298 register struct rx_packet *ahandle;
299 register struct sockaddr_in *afrom;
302 /* handle basic rx packet */
303 ahandle->length = asize - RX_HEADER_SIZE;
304 rxi_DecodePacketHeader(ahandle);
305 ahandle = rxi_ReceivePacket(ahandle, (struct socket *) arock,
306 afrom->sin_addr.s_addr, afrom->sin_port,
309 /* free the packet if it has been returned */
310 if (ahandle) rxi_FreePacket(ahandle);
313 #endif /* !RXK_LISTENER_ENV */
316 rxi_StartListener() {
317 /* if kernel, give name of appropriate procedures */
318 #ifndef RXK_LISTENER_ENV
319 rxk_GetPacketProc = MyPacketProc;
320 rxk_PacketArrivalProc = MyArrivalProc;
325 /* Called from rxi_FindPeer, when initializing a clear rx_peer structure,
326 to get interesting information. */
327 void rxi_InitPeerParams(pp)
328 register struct rx_peer *pp;
334 #ifdef AFS_USERSPACE_IP_ADDR
335 i = rxi_Findcbi(pp->host);
338 /* pp->timeout.usec = 0; */
339 pp->ifMTU = RX_REMOTE_PACKET_SIZE;
342 /* pp->timeout.usec = 0; */
343 pp->ifMTU = MIN(RX_MAX_PACKET_SIZE, rx_MyMaxSendSize);
346 mtu = ntohl(afs_cb_interface.mtu[i]);
347 /* Diminish the packet size to one based on the MTU given by
349 if (mtu > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
350 rxmtu = mtu - RX_IPUDP_SIZE;
351 if (rxmtu < pp->ifMTU) pp->ifMTU = rxmtu;
354 else { /* couldn't find the interface, so assume the worst */
355 pp->ifMTU = RX_REMOTE_PACKET_SIZE;
357 #else /* AFS_USERSPACE_IP_ADDR */
358 struct in_ifaddr *ifad = (struct in_ifaddr *) 0;
361 /* At some time we need to iterate through rxi_FindIfnet() to find the
364 ifn = rxi_FindIfnet(pp->host, &ifad);
365 if (ifn == NULL) { /* not local */
367 /* pp->timeout.usec = 0; */
368 pp->ifMTU = RX_REMOTE_PACKET_SIZE;
371 /* pp->timeout.usec = 0; */
372 pp->ifMTU = MIN(RX_MAX_PACKET_SIZE, rx_MyMaxSendSize);
375 #ifdef IFF_POINTOPOINT
376 if (ifn->if_flags & IFF_POINTOPOINT) {
377 /* wish we knew the bit rate and the chunk size, sigh. */
379 pp->ifMTU = RX_PP_PACKET_SIZE;
381 #endif /* IFF_POINTOPOINT */
382 /* Diminish the packet size to one based on the MTU given by
384 if (ifn->if_mtu > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
385 rxmtu = ifn->if_mtu - RX_IPUDP_SIZE;
386 if (rxmtu < pp->ifMTU) pp->ifMTU = rxmtu;
389 else { /* couldn't find the interface, so assume the worst */
390 pp->ifMTU = RX_REMOTE_PACKET_SIZE;
392 #endif/* else AFS_USERSPACE_IP_ADDR */
393 #else /* ADAPT_MTU */
394 pp->rateFlag = 2; /* start timing after two full packets */
396 pp->ifMTU = OLD_MAX_PACKET_SIZE;
397 #endif /* else ADAPT_MTU */
398 pp->ifMTU = rxi_AdjustIfMTU(pp->ifMTU);
399 pp->maxMTU = OLD_MAX_PACKET_SIZE; /* for compatibility with old guys */
400 pp->natMTU = MIN(pp->ifMTU, OLD_MAX_PACKET_SIZE);
401 pp->ifDgramPackets = MIN(rxi_nDgramPackets,
402 rxi_AdjustDgramPackets(RX_MAX_FRAGS, pp->ifMTU));
403 pp->maxDgramPackets = 1;
405 /* Initialize slow start parameters */
406 pp->MTU = MIN(pp->natMTU, pp->maxMTU);
408 pp->nDgramPackets = 1;
413 /* The following code is common to several system types, but not all. The
414 * separate ones are found in the system specific subdirectories.
418 #if ! defined(AFS_AIX_ENV) && ! defined(AFS_SUN5_ENV) && ! defined(UKERNEL) && ! defined(AFS_LINUX20_ENV)
419 /* Routine called during the afsd "-shutdown" process to put things back to
422 static struct protosw parent_proto; /* udp proto switch */
424 void shutdown_rxkernel(void)
426 register struct protosw *tpro, *last;
427 last = inetdomain.dom_protoswNPROTOSW;
428 for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
429 if (tpro->pr_protocol == IPPROTO_UDP) {
430 /* restore original udp protocol switch */
431 bcopy((void *)&parent_proto, (void *)tpro, sizeof(parent_proto));
432 bzero((void *)&parent_proto, sizeof(parent_proto));
437 printf("shutdown_rxkernel: no udp proto");
439 #endif /* !AIX && !SUN && !NCR && !UKERNEL */
441 #if !defined(AFS_SUN5_ENV) && !defined(AFS_SGI62_ENV)
442 /* Determine what the network interfaces are for this machine. */
444 #define ADDRSPERSITE 16
445 static afs_uint32 myNetAddrs[ADDRSPERSITE];
446 static int myNetMTUs[ADDRSPERSITE];
447 static int myNetFlags[ADDRSPERSITE];
448 static int numMyNetAddrs = 0;
450 #ifdef AFS_USERSPACE_IP_ADDR
453 int i, j, different = 0;
456 afs_uint32 addrs[ADDRSPERSITE];
457 int mtus[ADDRSPERSITE];
459 bzero((void *)addrs, sizeof(addrs));
460 bzero((void *)mtus, sizeof(mtus));
462 for (i=0; i<afs_cb_interface.numberOfInterfaces; i++) {
463 rxmtu = (ntohl(afs_cb_interface.mtu[i]) - RX_IPUDP_SIZE);
464 ifinaddr = ntohl(afs_cb_interface.addr_in[i]);
465 if (myNetAddrs[i] != ifinaddr) different++;
468 rxmtu = rxi_AdjustIfMTU(rxmtu);
469 maxmtu = rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags-1) * UDP_HDR_SIZE);
470 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
471 addrs[i++] = ifinaddr;
472 if ( ( ifinaddr != 0x7f000001 ) && (maxmtu > rx_maxReceiveSize) ) {
473 rx_maxReceiveSize = MIN( RX_MAX_PACKET_SIZE, maxmtu);
474 rx_maxReceiveSize = MIN( rx_maxReceiveSize, rx_maxReceiveSizeUser);
478 rx_maxJumboRecvSize = RX_HEADER_SIZE +
479 ( rxi_nDgramPackets * RX_JUMBOBUFFERSIZE) +
480 ((rxi_nDgramPackets-1) * RX_JUMBOHEADERSIZE);
481 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
484 for (j=0; j<i; j++) {
485 myNetMTUs[j] = mtus[j];
486 myNetAddrs[j] = addrs[j];
493 /* Returns the afs_cb_interface inxex which best matches address.
494 * If none is found, we return -1.
496 afs_int32 rxi_Findcbi(addr)
500 afs_uint32 myAddr, thisAddr, netMask, subnetMask;
501 afs_int32 rvalue = -1;
504 if (numMyNetAddrs == 0)
505 (void) rxi_GetcbiInfo();
507 myAddr = ntohl(addr);
509 if ( IN_CLASSA(myAddr) ) netMask = IN_CLASSA_NET;
510 else if ( IN_CLASSB(myAddr) ) netMask = IN_CLASSB_NET;
511 else if ( IN_CLASSC(myAddr) ) netMask = IN_CLASSC_NET;
514 for (j=0; j<afs_cb_interface.numberOfInterfaces; j++) {
515 thisAddr = ntohl(afs_cb_interface.addr_in[j]);
516 subnetMask = ntohl(afs_cb_interface.subnetmask[j]);
517 if ((myAddr & netMask) == (thisAddr & netMask)) {
518 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
519 if (myAddr == thisAddr) {
524 if (match_value < 3) {
529 if (match_value < 2) {
541 #else /* AFS_USERSPACE_IP_ADDR */
543 #if !defined(AFS_AIX41_ENV) && !defined(AFS_DUX40_ENV)
544 #define IFADDR2SA(f) (&((f)->ifa_addr))
545 #else /* AFS_AIX41_ENV */
546 #define IFADDR2SA(f) ((f)->ifa_addr)
554 register struct ifnet *ifn;
555 register int rxmtu, maxmtu;
556 afs_uint32 addrs[ADDRSPERSITE];
557 int mtus[ADDRSPERSITE];
558 struct ifaddr *ifad; /* ifnet points to a if_addrlist of ifaddrs */
561 bzero(addrs, sizeof(addrs));
562 bzero(mtus, sizeof(mtus));
564 for (ifn = ifnet; ifn != NULL && i < ADDRSPERSITE; ifn = ifn->if_next) {
565 rxmtu = (ifn->if_mtu - RX_IPUDP_SIZE);
566 for (ifad = ifn->if_addrlist; ifad != NULL && i < ADDRSPERSITE;
567 ifad = ifad->ifa_next){
568 if (IFADDR2SA(ifad)->sa_family == AF_INET) {
569 ifinaddr = ntohl(((struct sockaddr_in *) IFADDR2SA(ifad))->sin_addr.s_addr);
570 if (myNetAddrs[i] != ifinaddr) {
574 rxmtu = rxi_AdjustIfMTU(rxmtu);
575 maxmtu = rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags-1) * UDP_HDR_SIZE);
576 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
577 addrs[i++] = ifinaddr;
578 if ( ( ifinaddr != 0x7f000001 ) &&
579 (maxmtu > rx_maxReceiveSize) ) {
580 rx_maxReceiveSize = MIN( RX_MAX_PACKET_SIZE, maxmtu);
581 rx_maxReceiveSize = MIN( rx_maxReceiveSize, rx_maxReceiveSizeUser);
587 rx_maxJumboRecvSize = RX_HEADER_SIZE
588 + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE
589 + (rxi_nDgramPackets-1) * RX_JUMBOHEADERSIZE;
590 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
594 for (j=0; j< i; j++) {
595 myNetMTUs[j] = mtus[j];
596 myNetAddrs[j] = addrs[j];
602 /* Returns ifnet which best matches address */
604 rxi_FindIfnet(addr, pifad)
606 struct in_ifaddr **pifad;
610 extern struct in_ifaddr *in_ifaddr;
611 struct in_ifaddr *ifa;
612 struct sockaddr_in *sin;
614 if (numMyNetAddrs == 0)
615 (void) rxi_GetIFInfo();
617 ppaddr = ntohl(addr);
619 /* if we're given an address, skip everything until we find it */
623 if (((ppaddr & (*pifad)->ia_subnetmask) == (*pifad)->ia_subnet))
624 match_value = 2; /* don't find matching nets, just subnets */
625 *pifad = (*pifad)->ia_next;
628 for (ifa = *pifad; ifa; ifa = ifa->ia_next ) {
629 if ((ppaddr & ifa->ia_netmask) == ifa->ia_net) {
630 if ((ppaddr & ifa->ia_subnetmask) == ifa->ia_subnet) {
632 if ( sin->sin_addr.s_addr == ppaddr) { /* ie, ME!!! */
637 if (match_value < 3) {
643 if (match_value < 2) {
648 } /* if net matches */
649 } /* for all in_ifaddrs */
652 return (*pifad ? (*pifad)->ia_ifp : NULL );
654 #endif /* else AFS_USERSPACE_IP_ADDR */
655 #endif /* !SUN5 && !SGI62 */
658 /* rxk_NewSocket, rxk_FreeSocket and osi_NetSend are from the now defunct
659 * afs_osinet.c. One could argue that rxi_NewSocket could go into the
660 * system specific subdirectories for all systems. But for the moment,
661 * most of it is simple to follow common code.
663 #if !defined(UKERNEL)
664 #if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV)
665 /* rxk_NewSocket creates a new socket on the specified port. The port is
666 * in network byte order.
668 struct osi_socket *rxk_NewSocket(short aport)
670 register afs_int32 code;
671 struct socket *newSocket;
672 register struct mbuf *nam;
673 struct sockaddr_in myaddr;
675 #ifdef AFS_HPUX110_ENV
676 /* prototype copied from kernel source file streams/str_proto.h */
677 extern MBLKP allocb_wait(int, int);
679 int addrsize = sizeof(struct sockaddr_in);
685 AFS_STATCNT(osi_NewSocket);
686 #if defined(AFS_HPUX102_ENV)
687 #if defined(AFS_HPUX110_ENV)
688 /* blocking socket */
689 code = socreate(AF_INET, &newSocket, SOCK_DGRAM, 0, 0);
690 #else /* AFS_HPUX110_ENV */
691 code = socreate(AF_INET, &newSocket, SOCK_DGRAM, 0, SS_NOWAIT);
692 #endif /* else AFS_HPUX110_ENV */
695 code = socreate(AF_INET, &newSocket, SOCK_DGRAM,IPPROTO_UDP);
697 code = socreate(AF_INET, &newSocket, SOCK_DGRAM, 0);
698 #endif /* AFS_SGI65_ENV */
699 #endif /* AFS_HPUX102_ENV */
700 if (code) return (struct osi_socket *) 0;
702 myaddr.sin_family = AF_INET;
703 myaddr.sin_port = aport;
704 myaddr.sin_addr.s_addr = 0;
706 #ifdef AFS_HPUX110_ENV
707 bindnam = allocb_wait((addrsize+SO_MSGOFFSET+1), BPRI_MED);
710 return(struct osi_socket *) 0;
712 bcopy((caddr_t)&myaddr, (caddr_t)bindnam->b_rptr+SO_MSGOFFSET, addrsize);
713 bindnam->b_wptr = bindnam->b_rptr + (addrsize+SO_MSGOFFSET+1);
715 code = sobind(newSocket, bindnam, addrsize);
719 return(struct osi_socket *) 0;
723 #else /* AFS_HPUX110_ENV */
724 code = soreserve(newSocket, 50000, 50000);
726 code = soreserve(newSocket, 32766, 32766);
728 osi_Panic("osi_NewSocket: last attempt to reserve 32K failed!\n");
731 nam = m_getclr(M_WAIT, MT_SONAME);
732 #else /* AFS_OSF_ENV */
733 nam = m_get(M_WAIT, MT_SONAME);
736 #if !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_SGI64_ENV)
739 return (struct osi_socket *) 0;
741 nam->m_len = sizeof(myaddr);
743 myaddr.sin_len = nam->m_len;
744 #endif /* AFS_OSF_ENV */
745 bcopy(&myaddr, mtod(nam, caddr_t), sizeof(myaddr));
747 BHV_PDATA(&bhv) = (void*)newSocket;
748 code = sobind(&bhv, nam);
751 code = sobind(newSocket, nam);
755 #ifndef AFS_SGI65_ENV
758 return (struct osi_socket *) 0;
760 #endif /* else AFS_HPUX110_ENV */
762 return (struct osi_socket *) newSocket;
766 /* free socket allocated by rxk_NewSocket */
767 int rxk_FreeSocket(asocket)
768 register struct socket *asocket;
770 AFS_STATCNT(osi_FreeSocket);
774 #endif /* !SUN5 && !LINUX20 */
776 #if defined(RXK_LISTENER_ENV) || defined(AFS_SUN5_ENV)
778 * Run RX event daemon every second (5 times faster than rest of systems)
787 #ifdef RX_ENABLE_LOCKS
789 #endif /* RX_ENABLE_LOCKS */
792 rxevent_RaiseEvents(&temp);
795 #ifdef RX_ENABLE_LOCKS
797 #endif /* RX_ENABLE_LOCKS */
798 afs_osi_Wait(500, (char *)0, 0);
799 if (afs_termState == AFSOP_STOP_RXEVENT )
801 #ifdef RXK_LISTENER_ENV
802 afs_termState = AFSOP_STOP_RXK_LISTENER;
804 afs_termState = AFSOP_STOP_COMPLETE;
806 afs_osi_Wakeup(&afs_termState);
813 #ifdef RXK_LISTENER_ENV
815 /* rxk_ReadPacket returns 1 if valid packet, 0 on error. */
816 int rxk_ReadPacket(osi_socket so, struct rx_packet *p, int *host, int *port)
819 struct sockaddr_in from;
822 register afs_int32 tlen;
823 afs_int32 savelen; /* was using rlen but had aliasing problems */
824 rx_computelen(p, tlen);
825 rx_SetDataSize(p, tlen); /* this is the size of the user data area */
827 tlen += RX_HEADER_SIZE; /* now this is the size of the entire packet */
828 rlen = rx_maxJumboRecvSize; /* this is what I am advertising. Only check
829 * it once in order to avoid races. */
832 tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF);
840 /* add some padding to the last iovec, it's just to make sure that the
841 * read doesn't return more data than we expect, and is done to get around
842 * our problems caused by the lack of a length field in the rx header. */
843 savelen = p->wirevec[p->niovecs-1].iov_len;
844 p->wirevec[p->niovecs-1].iov_len = savelen + RX_EXTRABUFFERSIZE;
846 nbytes = tlen + sizeof(afs_int32);
847 code = osi_NetReceive(rx_socket, &from, p->wirevec, p->niovecs,
850 /* restore the vec to its correct state */
851 p->wirevec[p->niovecs-1].iov_len = savelen;
854 p->length = nbytes - RX_HEADER_SIZE;;
855 if ((nbytes > tlen) || (p->length & 0x8000)) { /* Bogus packet */
857 rxi_MorePackets(rx_initSendWindow);
859 MUTEX_ENTER(&rx_stats_mutex);
860 rx_stats.bogusPacketOnRead++;
861 rx_stats.bogusHost = from.sin_addr.s_addr;
862 MUTEX_EXIT(&rx_stats_mutex);
863 dpf(("B: bogus packet from [%x,%d] nb=%d", from.sin_addr.s_addr,
864 from.sin_port,nbytes));
869 /* Extract packet header. */
870 rxi_DecodePacketHeader(p);
872 *host = from.sin_addr.s_addr;
873 *port = from.sin_port;
874 if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
875 MUTEX_ENTER(&rx_stats_mutex);
876 rx_stats.packetsRead[p->header.type-1]++;
877 MUTEX_EXIT(&rx_stats_mutex);
880 /* Free any empty packet buffers at the end of this packet */
881 rxi_TrimDataBufs(p, 1);
892 * Listen for packets on socket. This thread is typically started after
893 * rx_Init has called rxi_StartListener(), but nevertheless, ensures that
894 * the start state is set before proceeding.
896 * Note that this thread is outside the AFS global lock for much of
899 * In many OS's, the socket receive code sleeps interruptibly. That's not what
900 * we want here. So we need to either block all signals (including SIGKILL
901 * and SIGSTOP) or reset the thread's signal state to unsignalled when the
902 * OS's socket receive routine returns as a result of a signal.
904 int rxk_ListenerPid; /* Used to signal process to wakeup at shutdown */
908 * Run the listener as a kernel process.
910 void rxk_Listener(void)
913 void rxk_ListenerProc(void);
914 if (newproc(rxk_ListenerProc, syscid, 59))
915 osi_Panic("rxk_Listener: failed to fork listener process!\n");
918 void rxk_ListenerProc(void)
919 #else /* AFS_SUN5_ENV */
920 void rxk_Listener(void)
921 #endif /* AFS_SUN5_ENV */
923 struct rx_packet *rxp = NULL;
927 #ifdef AFS_LINUX20_ENV
928 rxk_ListenerPid = current->pid;
931 rxk_ListenerPid = ttoproc(curthread)->p_pidp->pid_id;
932 #endif /* AFS_SUN5_ENV */
933 #if defined(RX_ENABLE_LOCKS) && !defined(AFS_SUN5_ENV)
935 #endif /* RX_ENABLE_LOCKS && !AFS_SUN5_ENV */
937 while (afs_termState != AFSOP_STOP_RXK_LISTENER) {
939 rxi_RestoreDataBufs(rxp);
942 rxp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
944 osi_Panic("rxk_Listener: No more Rx buffers!\n");
946 if (!(code = rxk_ReadPacket(rx_socket, rxp, &host, &port))) {
948 rxp = rxi_ReceivePacket(rxp, rx_socket, host, port);
951 if (afs_termState == AFSOP_STOP_RXK_LISTENER)
956 #ifdef RX_ENABLE_LOCKS
958 #endif /* RX_ENABLE_LOCKS */
959 if (afs_termState == AFSOP_STOP_RXK_LISTENER) {
960 afs_termState = AFSOP_STOP_COMPLETE;
961 afs_osi_Wakeup(&afs_termState);
966 #endif /* AFS_SUN5_ENV */
969 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_SUN5_ENV)
970 /* The manner of stopping the rx listener thread may vary. Most unix's should
971 * be able to call soclose.
973 void osi_StopListener(void)
978 #endif /* RXK_LISTENER_ENV */
980 #endif /* !NCR && !UKERNEL */