summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2009-10-15 06:12:04 +0000
committerqingli <qingli@FreeBSD.org>2009-10-15 06:12:04 +0000
commit7d73ff246e2dbd1177593d18743221c6cbbb1316 (patch)
treeb91f0e890b219154a0cc352c650f972f6dd5750d
parent2ae8c0517d918f59e4147a624115484eb78780ba (diff)
downloadFreeBSD-src-7d73ff246e2dbd1177593d18743221c6cbbb1316.zip
FreeBSD-src-7d73ff246e2dbd1177593d18743221c6cbbb1316.tar.gz
This patch fixes the following issues in the ARP operation:
1. There is a regression issue in the ARP code. The incomplete ARP entry was timing out too quickly (1 second timeout), as such, a new entry is created each time arpresolve() is called. Therefore the maximum attempts made is always 1. Consequently the error code returned to the application is always 0. 2. Set the expiration of each incomplete entry to a 20-second lifetime. 3. Return "incomplete" entries to the application. Reviewed by: kmacy MFC after: 3 days
-rw-r--r--sys/netinet/if_ether.c17
-rw-r--r--sys/netinet/in.c11
2 files changed, 18 insertions, 10 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index be62921..45cee89 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -88,11 +88,14 @@ VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for
/* timer values */
static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20
* minutes */
+static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for
+ * 20 seconds */
static VNET_DEFINE(int, arp_maxtries) = 5;
static VNET_DEFINE(int, arp_proxyall);
static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
#define V_arpt_keep VNET(arpt_keep)
+#define V_arpt_down VNET(arpt_down)
#define V_arp_maxtries VNET(arp_maxtries)
#define V_arp_proxyall VNET(arp_proxyall)
#define V_arpstat VNET(arpstat)
@@ -309,7 +312,7 @@ retry:
}
if ((la->la_flags & LLE_VALID) &&
- ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
+ ((la->la_flags & LLE_STATIC) || la->la_expire > time_second)) {
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
/*
* If entry has an expiry time and it is approaching,
@@ -317,7 +320,7 @@ retry:
* arpt_down interval.
*/
if (!(la->la_flags & LLE_STATIC) &&
- time_uptime + la->la_preempt > la->la_expire) {
+ time_second + la->la_preempt > la->la_expire) {
arprequest(ifp, NULL,
&SIN(dst)->sin_addr, IF_LLADDR(ifp));
@@ -337,7 +340,7 @@ retry:
goto done;
}
- renew = (la->la_asked == 0 || la->la_expire != time_uptime);
+ renew = (la->la_asked == 0 || la->la_expire != time_second);
if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) {
flags |= LLE_EXCLUSIVE;
LLE_RUNLOCK(la);
@@ -370,12 +373,12 @@ retry:
error = EWOULDBLOCK; /* First request. */
else
error =
- (rt0->rt_flags & RTF_GATEWAY) ? EHOSTDOWN : EHOSTUNREACH;
+ (rt0->rt_flags & RTF_GATEWAY) ? EHOSTUNREACH : EHOSTDOWN;
if (renew) {
LLE_ADDREF(la);
- la->la_expire = time_uptime;
- callout_reset(&la->la_timer, hz, arptimer, la);
+ la->la_expire = time_second;
+ callout_reset(&la->la_timer, hz * V_arpt_down, arptimer, la);
la->la_asked++;
LLE_WUNLOCK(la);
arprequest(ifp, NULL, &SIN(dst)->sin_addr,
@@ -687,7 +690,7 @@ match:
EVENTHANDLER_INVOKE(arp_update_event, la);
if (!(la->la_flags & LLE_STATIC)) {
- la->la_expire = time_uptime + V_arpt_keep;
+ la->la_expire = time_second + V_arpt_keep;
callout_reset(&la->la_timer, hz * V_arpt_keep,
arptimer, la);
}
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index dc4a8e1..c124513 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1440,7 +1440,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
struct sockaddr_dl *sdl;
/* skip deleted entries */
- if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
+ if ((lle->la_flags & LLE_DELETED) == LLE_DELETED)
continue;
/* Skip if jailed and not a valid IP of the prison. */
if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
@@ -1472,10 +1472,15 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
sdl = &arpc.sdl;
sdl->sdl_family = AF_LINK;
sdl->sdl_len = sizeof(*sdl);
- sdl->sdl_alen = ifp->if_addrlen;
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
- bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+ if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+ } else {
+ sdl->sdl_alen = 0;
+ bzero(LLADDR(sdl), ifp->if_addrlen);
+ }
arpc.rtm.rtm_rmx.rmx_expire =
lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
OpenPOWER on IntegriCloud