Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140158701
D3688.id8817.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D3688.id8817.diff
View Options
Index: sys/net/if_llatbl.h
===================================================================
--- sys/net/if_llatbl.h
+++ sys/net/if_llatbl.h
@@ -63,7 +63,8 @@
uint16_t mac16[3];
uint8_t mac8[20]; /* IB needs 20 bytes. */
} ll_addr;
- uint32_t spare0;
+ uint16_t r_flags; /* LLE runtime flags */
+ uint16_t r_kick; /* feedback from fast path */
uint64_t spare1;
struct lltable *lle_tbl;
@@ -84,6 +85,7 @@
LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */
struct callout lle_timer;
struct rwlock lle_lock;
+ struct mtx kick_mtx;
};
#define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock)
@@ -96,6 +98,12 @@
#define LLE_LOCK_DESTROY(lle) rw_destroy(&(lle)->lle_lock)
#define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED)
+#define LLE_KICKLOCK_INIT(lle) mtx_init(&(lle)->kick_mtx, "lle kick", \
+ NULL, MTX_DEF)
+#define LLE_KICKLOCK_DESTROY(lle) mtx_destroy(&(lle)->kick_mtx)
+#define LLE_KICKLOCK_LOCK(lle) mtx_lock(&(lle)->kick_mtx)
+#define LLE_KICKLOCK_UNLOCK(lle) mtx_unlock(&(lle)->kick_mtx)
+
#define LLE_IS_VALID(lle) (((lle) != NULL) && ((lle) != (void *)-1))
#define LLE_ADDREF(lle) do { \
@@ -188,6 +196,11 @@
#define LLE_LINKED 0x0040 /* linked to lookup structure */
/* LLE request flags */
#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
+#define LLE_UNLOCKED 0x4000 /* return lle unlocked */
+
+/* LLE flags used by fastpath code */
+#define RLLE_VALID 0x0001 /* entry is valid */
+#define RLLE_IFADDR LLE_IFADDR /* entry is ifaddr */
#define LLATBL_HASH(key, mask) \
(((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
Index: sys/net/if_llatbl.c
===================================================================
--- sys/net/if_llatbl.c
+++ sys/net/if_llatbl.c
@@ -631,6 +631,7 @@
if ((rtm->rtm_flags & RTF_ANNOUNCE))
lle->la_flags |= LLE_PUB;
lle->la_flags |= LLE_VALID;
+ lle->r_flags |= RLLE_VALID;
lle->la_expire = rtm->rtm_rmx.rmx_expire;
laflags = lle->la_flags;
Index: sys/netinet/if_ether.c
===================================================================
--- sys/netinet/if_ether.c
+++ sys/netinet/if_ether.c
@@ -78,6 +78,14 @@
static int arp_curpps;
static int arp_maxpps = 1;
+/* Simple ARP state machine */
+enum arp_llinfo_state {
+ ARP_LLINFO_INCOMPLETE = 0, /* No LLE data */
+ ARP_LLINFO_REACHABLE, /* LLE is valid */
+ ARP_LLINFO_VERIFY, /* LLE is valid, need refresh */
+ ARP_LLINFO_DELETED, /* LLE is deleted */
+};
+
SYSCTL_DECL(_net_link_ether);
static SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
static SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, "");
@@ -89,6 +97,7 @@
static VNET_DEFINE(int, arp_proxyall) = 0;
static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for
* 20 seconds */
+static VNET_DEFINE(int, arpt_rexmit) = 1; /* retransmit arp entries, sec*/
VNET_PCPUSTAT_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
VNET_PCPUSTAT_SYSINIT(arpstat);
@@ -100,6 +109,7 @@
#define V_arpt_keep VNET(arpt_keep)
#define V_arpt_down VNET(arpt_down)
+#define V_arpt_rexmit VNET(arpt_rexmit)
#define V_arp_maxtries VNET(arp_maxtries)
#define V_arp_proxyall VNET(arp_proxyall)
#define V_arp_maxhold VNET(arp_maxhold)
@@ -161,6 +171,7 @@
{
struct llentry *lle = (struct llentry *)arg;
struct ifnet *ifp;
+ int r_kick;
if (lle->la_flags & LLE_STATIC) {
return;
@@ -188,6 +199,55 @@
ifp = lle->lle_tbl->llt_ifp;
CURVNET_SET(ifp->if_vnet);
+ switch (lle->ln_state) {
+ case ARP_LLINFO_REACHABLE:
+
+ /*
+ * Expiration time is approaching.
+ * Let's try to refresh entry if it is still
+ * in use.
+ *
+ * Set r_kick to get feedback from
+ * fast path. Change state and re-schedule
+ * ourselves.
+ */
+ LLE_KICKLOCK_LOCK(lle);
+ lle->r_kick = 1;
+ LLE_KICKLOCK_UNLOCK(lle);
+ lle->ln_state = ARP_LLINFO_VERIFY;
+ callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit);
+ LLE_WUNLOCK(lle);
+ CURVNET_RESTORE();
+ return;
+ case ARP_LLINFO_VERIFY:
+ LLE_KICKLOCK_LOCK(lle);
+ r_kick = lle->r_kick;
+ LLE_KICKLOCK_UNLOCK(lle);
+
+ if (r_kick == 0 && lle->la_preempt > 0) {
+ /* Entry was used, issue refresh request */
+ struct in_addr dst;
+ dst = lle->r_l3addr.addr4;
+ lle->la_preempt--;
+ callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit);
+ LLE_WUNLOCK(lle);
+ arprequest(ifp, NULL, &dst, NULL);
+ CURVNET_RESTORE();
+ return;
+ }
+ /* Nothing happened. Reschedule if not too late */
+ if (lle->la_expire > time_uptime) {
+ callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit);
+ LLE_WUNLOCK(lle);
+ CURVNET_RESTORE();
+ return;
+ }
+ break;
+ case ARP_LLINFO_INCOMPLETE:
+ case ARP_LLINFO_DELETED:
+ break;
+ }
+
if ((lle->la_flags & LLE_DELETED) == 0) {
int evt;
@@ -353,26 +413,16 @@
if ((la->la_flags & LLE_VALID) &&
((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
- renew = 0;
- /*
- * If entry has an expiry time and it is approaching,
- * see if we need to send an ARP request within this
- * arpt_down interval.
- */
- if (!(la->la_flags & LLE_STATIC) &&
- time_uptime + la->la_preempt > la->la_expire) {
- renew = 1;
- la->la_preempt--;
- }
+ /* Check if we have feedback request from arptimer() */
+ if (la->r_kick != 0) {
+ LLE_KICKLOCK_LOCK(la);
+ la->r_kick = 0; /* Notify that entry was used */
+ LLE_KICKLOCK_UNLOCK(la);
+ }
if (pflags != NULL)
- *pflags = la->la_flags;
-
+ *pflags = la->la_flags & (LLE_VALID|LLE_IFADDR);
LLE_WUNLOCK(la);
-
- if (renew == 1)
- arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
-
return (0);
}
@@ -440,7 +490,7 @@
* m is the mbuf. May be NULL if we don't have a packet.
* dst is the next hop,
* desten is the storage to put LL address.
- * flags returns lle entry flags.
+ * flags returns subset of lle flags: LLE_VALID | LLE_IFADDR
*
* On success, desten and flags are filled in and the function returns 0;
* If the packet must be held pending resolution, we return EWOULDBLOCK
@@ -452,7 +502,6 @@
const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
{
struct llentry *la = 0;
- int renew;
if (pflags != NULL)
*pflags = 0;
@@ -472,40 +521,24 @@
}
IF_AFDATA_RLOCK(ifp);
- la = lla_lookup(LLTABLE(ifp), 0, dst);
- IF_AFDATA_RUNLOCK(ifp);
-
- if (la == NULL)
- return (arpresolve_full(ifp, is_gw, 1, m, dst, desten, pflags));
-
- if ((la->la_flags & LLE_VALID) &&
- ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
+ la = lla_lookup(LLTABLE(ifp), LLE_UNLOCKED, dst);
+ if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
+ /* Entry found, let's copy lle info */
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
- renew = 0;
- /*
- * If entry has an expiry time and it is approaching,
- * see if we need to send an ARP request within this
- * arpt_down interval.
- */
- if (!(la->la_flags & LLE_STATIC) &&
- time_uptime + la->la_preempt > la->la_expire) {
- renew = 1;
- la->la_preempt--;
- }
-
if (pflags != NULL)
- *pflags = la->la_flags;
-
- LLE_RUNLOCK(la);
-
- if (renew == 1)
- arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
-
+ *pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR);
+ /* Check if we have feedback request from arptimer() */
+ if (la->r_kick != 0) {
+ LLE_KICKLOCK_LOCK(la);
+ la->r_kick = 0; /* Notify that entry was used */
+ LLE_KICKLOCK_UNLOCK(la);
+ }
+ IF_AFDATA_RUNLOCK(ifp);
return (0);
}
- LLE_RUNLOCK(la);
+ IF_AFDATA_RUNLOCK(ifp);
- return (arpresolve_full(ifp, is_gw, 0, m, dst, desten, pflags));
+ return (arpresolve_full(ifp, is_gw, 1, m, dst, desten, pflags));
}
/*
@@ -1076,22 +1109,28 @@
memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen);
la->la_flags |= LLE_VALID;
+ la->r_flags |= RLLE_VALID;
+ la->r_kick = 0;
}
static void
arp_mark_lle_reachable(struct llentry *la)
{
- int canceled;
+ int canceled, wtime;
LLE_WLOCK_ASSERT(la);
+ la->ln_state = ARP_LLINFO_REACHABLE;
EVENTHANDLER_INVOKE(lle_event, la, LLENTRY_RESOLVED);
if (!(la->la_flags & LLE_STATIC)) {
LLE_ADDREF(la);
la->la_expire = time_uptime + V_arpt_keep;
+ wtime = V_arpt_keep - V_arp_maxtries * V_arpt_rexmit;
+ if (wtime < 0)
+ V_arpt_keep;
canceled = callout_reset(&la->lle_timer,
- hz * V_arpt_keep, arptimer, la);
+ hz * wtime, arptimer, la);
if (canceled)
LLE_REMREF(la);
}
Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -998,6 +998,7 @@
LLE_WUNLOCK(lle);
LLE_LOCK_DESTROY(lle);
+ LLE_KICKLOCK_DESTROY(lle);
free(lle, M_LLTABLE);
}
@@ -1019,6 +1020,7 @@
lle->base.lle_refcnt = 1;
lle->base.lle_free = in_lltable_destroy_lle;
LLE_LOCK_INIT(&lle->base);
+ LLE_KICKLOCK_INIT(&lle->base);
callout_init(&lle->base.lle_timer, 1);
return (&lle->base);
@@ -1242,9 +1244,12 @@
return (NULL);
}
lle->la_flags = flags;
+ if (flags & LLE_STATIC)
+ lle->r_flags |= RLLE_VALID;
if ((flags & LLE_IFADDR) == LLE_IFADDR) {
bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
lle->la_flags |= (LLE_VALID | LLE_STATIC);
+ lle->r_flags |= RLLE_IFADDR;
}
return (lle);
@@ -1268,6 +1273,9 @@
if (lle == NULL)
return (NULL);
+ if (flags & LLE_UNLOCKED)
+ return (lle);
+
if (flags & LLE_EXCLUSIVE)
LLE_WLOCK(lle);
else
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 21, 11:47 PM (14 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27125073
Default Alt Text
D3688.id8817.diff (9 KB)
Attached To
Mode
D3688: Remove LLE read lock from IPv4 fast path.
Attached
Detach File
Event Timeline
Log In to Comment