From b72c14c4cfdae85c469bcc1b88659e5bd6fb620c Mon Sep 17 00:00:00 2001 From: Derek Atkins Date: Wed, 8 Jan 2003 05:35:25 +0000 Subject: [PATCH] linux-fast-netdown-20020107 notice the NETUNREACH quickly and mark a host down --- src/rx/rx.c | 6 +++--- src/rx/rx_packet.c | 40 ++++++++++++++++++++++++++++++---------- src/rx/rx_prototypes.h | 8 ++++---- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index 4b71a6aca..ab1dc0cd3 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -4635,9 +4635,9 @@ static void rxi_SendList(struct rx_call *call, struct rx_packet **list, CALL_HOLD(call, RX_CALL_REFCOUNT_SEND); MUTEX_EXIT(&call->lock); if (len > 1) { - rxi_SendPacketList(conn, list, len, istack); + rxi_SendPacketList(call, conn, list, len, istack); } else { - rxi_SendPacket(conn, list[0], istack); + rxi_SendPacket(call, conn, list[0], istack); } MUTEX_ENTER(&call->lock); CALL_RELE(call, RX_CALL_REFCOUNT_SEND); @@ -5083,7 +5083,7 @@ void rxi_Send(register struct rx_call *call, register struct rx_packet *p, /* Actually send the packet, filling in more connection-specific fields */ CALL_HOLD(call, RX_CALL_REFCOUNT_SEND); MUTEX_EXIT(&call->lock); - rxi_SendPacket(conn, p, istack); + rxi_SendPacket(call, conn, p, istack); MUTEX_ENTER(&call->lock); CALL_RELE(call, RX_CALL_REFCOUNT_SEND); diff --git a/src/rx/rx_packet.c b/src/rx/rx_packet.c index e6b306603..f9a6ab839 100644 --- a/src/rx/rx_packet.c +++ b/src/rx/rx_packet.c @@ -1434,14 +1434,15 @@ static void rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket, } /* Send the packet to appropriate destination for the specified - * connection. The header is first encoded and placed in the packet. + * call. The header is first encoded and placed in the packet. */ -void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, - int istack) +void rxi_SendPacket(struct rx_call * call, struct rx_connection * conn, + struct rx_packet *p, int istack) { #if defined(KERNEL) int waslocked; #endif + int code; struct sockaddr_in addr; register struct rx_peer *peer = conn->peer; osi_socket socket; @@ -1514,14 +1515,24 @@ void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, waslocked = ISAFS_GLOCK(); if (waslocked) AFS_GUNLOCK(); #endif - if (osi_NetSend(socket, &addr, p->wirevec, p->niovecs, - p->length+RX_HEADER_SIZE, istack)){ + if ((code = osi_NetSend(socket, &addr, p->wirevec, p->niovecs, + p->length+RX_HEADER_SIZE, istack)) != 0) { /* send failed, so let's hurry up the resend, eh? */ MUTEX_ENTER(&rx_stats_mutex); rx_stats.netSendFailures++; MUTEX_EXIT(&rx_stats_mutex); p->retryTime = p->timeSent; /* resend it very soon */ clock_Addmsec(&(p->retryTime), 10 + (((afs_uint32) p->backoff) << 8)); + +#if defined(KERNEL) && defined(AFS_LINUX_ENV) + /* Linux is nice -- it can tell us right away that we cannot + * reach this recipient by returning an ENETUNREACH error + * code. So, when this happens let's "down" the host NOW so + * we don't sit around waiting for this host to timeout later. + */ + if (call && code == -ENETUNREACH) + call->lastReceiveTime = 0; +#endif } #ifdef KERNEL if (waslocked) AFS_GLOCK(); @@ -1546,8 +1557,8 @@ void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, /* Send a list of packets to appropriate destination for the specified * connection. The headers are first encoded and placed in the packets. */ -void rxi_SendPacketList(struct rx_connection * conn, struct rx_packet **list, - int len, int istack) +void rxi_SendPacketList(struct rx_call * call, struct rx_connection * conn, + struct rx_packet **list, int len, int istack) { #if defined(AFS_SUN5_ENV) && defined(KERNEL) int waslocked; @@ -1557,7 +1568,7 @@ void rxi_SendPacketList(struct rx_connection * conn, struct rx_packet **list, osi_socket socket; struct rx_packet *p = NULL; struct iovec wirevec[RX_MAXIOVECS]; - int i, length; + int i, length, code; afs_uint32 serial; afs_uint32 temp; struct rx_jumboHeader *jp; @@ -1677,7 +1688,7 @@ void rxi_SendPacketList(struct rx_connection * conn, struct rx_packet **list, waslocked = ISAFS_GLOCK(); if (!istack && waslocked) AFS_GUNLOCK(); #endif - if (osi_NetSend(socket, &addr, &wirevec[0], len+1, length, istack)){ + if ((code = osi_NetSend(socket, &addr, &wirevec[0], len+1, length, istack)) != 0){ /* send failed, so let's hurry up the resend, eh? */ MUTEX_ENTER(&rx_stats_mutex); rx_stats.netSendFailures++; @@ -1687,6 +1698,15 @@ void rxi_SendPacketList(struct rx_connection * conn, struct rx_packet **list, p->retryTime = p->timeSent; /* resend it very soon */ clock_Addmsec(&(p->retryTime), 10 + (((afs_uint32) p->backoff) << 8)); } +#if defined(KERNEL) && defined(AFS_LINUX_ENV) + /* Linux is nice -- it can tell us right away that we cannot + * reach this recipient by returning an ENETUNREACH error + * code. So, when this happens let's "down" the host NOW so + * we don't sit around waiting for this host to timeout later. + */ + if (call && code == -ENETUNREACH) + call->lastReceiveTime = 0; +#endif } #if defined(AFS_SUN5_ENV) && defined(KERNEL) if (!istack && waslocked) AFS_GLOCK(); @@ -1773,7 +1793,7 @@ struct rx_packet *rxi_SendSpecial(register struct rx_call *call, } if (call) rxi_Send(call, p, istack); - else rxi_SendPacket(conn, p, istack); + else rxi_SendPacket((struct rx_call *)0, conn, p, istack); if (saven) { /* means we truncated the packet above. We probably don't */ /* really need to do this, but it seems safer this way, given that */ /* sneaky optionalPacket... */ diff --git a/src/rx/rx_prototypes.h b/src/rx/rx_prototypes.h index d7d8950dd..579d355f5 100644 --- a/src/rx/rx_prototypes.h +++ b/src/rx/rx_prototypes.h @@ -384,10 +384,10 @@ extern struct rx_packet *rxi_ReceiveDebugPacket(register struct rx_packet *ap, osi_socket asocket, afs_int32 ahost, short aport, int istack); extern struct rx_packet *rxi_ReceiveVersionPacket(register struct rx_packet *ap, osi_socket asocket, afs_int32 ahost, short aport, int istack); -extern void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, - int istack); -extern void rxi_SendPacketList(struct rx_connection * conn, struct rx_packet **list, - int len, int istack); +extern void rxi_SendPacket(struct rx_call * call, struct rx_connection * conn, + struct rx_packet *p, int istack); +extern void rxi_SendPacketList(struct rx_call * call, struct rx_connection * conn, + struct rx_packet **list, int len, int istack); extern struct rx_packet *rxi_SendSpecial(register struct rx_call *call, register struct rx_connection *conn, struct rx_packet *optionalPacket, int type, char *data, int nbytes, int istack); -- 2.39.5