Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/if_ether.c
Show First 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Timeout routine. Age arp_tab entries periodically. | * Timeout routine. Age arp_tab entries periodically. | ||||
*/ | */ | ||||
static void | static void | ||||
arptimer(void *arg) | arptimer(void *arg) | ||||
{ | { | ||||
struct llentry *lle = (struct llentry *)arg; | struct llentry *lle = (struct llentry *)arg; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int r_skip_req; | |||||
if (lle->la_flags & LLE_STATIC) { | if (lle->la_flags & LLE_STATIC) { | ||||
return; | return; | ||||
} | } | ||||
LLE_WLOCK(lle); | LLE_WLOCK(lle); | ||||
if (callout_pending(&lle->lle_timer)) { | if (callout_pending(&lle->lle_timer)) { | ||||
/* | /* | ||||
* Here we are a bit odd here in the treatment of | * Here we are a bit odd here in the treatment of | ||||
Show All 16 Lines | arptimer(void *arg) | ||||
ifp = lle->lle_tbl->llt_ifp; | ifp = lle->lle_tbl->llt_ifp; | ||||
CURVNET_SET(ifp->if_vnet); | CURVNET_SET(ifp->if_vnet); | ||||
switch (lle->ln_state) { | switch (lle->ln_state) { | ||||
case ARP_LLINFO_REACHABLE: | case ARP_LLINFO_REACHABLE: | ||||
/* | /* | ||||
* Expiration time is approaching. | * Expiration time is approaching. | ||||
* Let's try to refresh entry if it is still | * Request usage feedback from the datapath. | ||||
* in use. | * Change state and re-schedule ourselves. | ||||
* | |||||
* Set r_skip_req to get feedback from | |||||
* fast path. Change state and re-schedule | |||||
* ourselves. | |||||
*/ | */ | ||||
LLE_REQ_LOCK(lle); | llentry_request_feedback(lle); | ||||
lle->r_skip_req = 1; | |||||
LLE_REQ_UNLOCK(lle); | |||||
lle->ln_state = ARP_LLINFO_VERIFY; | lle->ln_state = ARP_LLINFO_VERIFY; | ||||
callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); | callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); | ||||
LLE_WUNLOCK(lle); | LLE_WUNLOCK(lle); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return; | return; | ||||
case ARP_LLINFO_VERIFY: | case ARP_LLINFO_VERIFY: | ||||
LLE_REQ_LOCK(lle); | if (llentry_get_hittime(lle) > 0 && lle->la_preempt > 0) { | ||||
r_skip_req = lle->r_skip_req; | |||||
LLE_REQ_UNLOCK(lle); | |||||
if (r_skip_req == 0 && lle->la_preempt > 0) { | |||||
/* Entry was used, issue refresh request */ | /* Entry was used, issue refresh request */ | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
struct in_addr dst; | struct in_addr dst; | ||||
dst = lle->r_l3addr.addr4; | dst = lle->r_l3addr.addr4; | ||||
lle->la_preempt--; | lle->la_preempt--; | ||||
callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); | callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); | ||||
LLE_WUNLOCK(lle); | LLE_WUNLOCK(lle); | ||||
▲ Show 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | if (flags & LLE_ADDRONLY) { | ||||
ll_len = ifp->if_addrlen; | ll_len = ifp->if_addrlen; | ||||
} else { | } else { | ||||
lladdr = la->r_linkdata; | lladdr = la->r_linkdata; | ||||
ll_len = la->r_hdrlen; | ll_len = la->r_hdrlen; | ||||
} | } | ||||
bcopy(lladdr, desten, ll_len); | bcopy(lladdr, desten, ll_len); | ||||
/* Notify LLE code that the entry was used by datapath */ | /* Notify LLE code that the entry was used by datapath */ | ||||
llentry_mark_used(la); | llentry_provide_feedback(la); | ||||
if (pflags != NULL) | if (pflags != NULL) | ||||
*pflags = la->la_flags & (LLE_VALID|LLE_IFADDR); | *pflags = la->la_flags & (LLE_VALID|LLE_IFADDR); | ||||
if (plle) { | if (plle) { | ||||
LLE_ADDREF(la); | LLE_ADDREF(la); | ||||
*plle = la; | *plle = la; | ||||
} | } | ||||
LLE_WUNLOCK(la); | LLE_WUNLOCK(la); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, | ||||
la = lla_lookup(LLTABLE(ifp), plle ? LLE_EXCLUSIVE : LLE_UNLOCKED, dst); | la = lla_lookup(LLTABLE(ifp), plle ? LLE_EXCLUSIVE : LLE_UNLOCKED, dst); | ||||
if (la != NULL && (la->r_flags & RLLE_VALID) != 0) { | if (la != NULL && (la->r_flags & RLLE_VALID) != 0) { | ||||
/* Entry found, let's copy lle info */ | /* Entry found, let's copy lle info */ | ||||
bcopy(la->r_linkdata, desten, la->r_hdrlen); | bcopy(la->r_linkdata, desten, la->r_hdrlen); | ||||
if (pflags != NULL) | if (pflags != NULL) | ||||
*pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR); | *pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR); | ||||
/* Notify the LLE handling code that the entry was used. */ | /* Notify the LLE handling code that the entry was used. */ | ||||
llentry_mark_used(la); | llentry_provide_feedback(la); | ||||
if (plle) { | if (plle) { | ||||
LLE_ADDREF(la); | LLE_ADDREF(la); | ||||
*plle = la; | *plle = la; | ||||
LLE_WUNLOCK(la); | LLE_WUNLOCK(la); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
if (plle && la) | if (plle && la) | ||||
▲ Show 20 Lines • Show All 552 Lines • ▼ Show 20 Lines | arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, | ||||
if (memcmp(la->r_linkdata, linkhdr, linkhdrsize) != 0 || | if (memcmp(la->r_linkdata, linkhdr, linkhdrsize) != 0 || | ||||
(la->la_flags & LLE_VALID) == 0) { | (la->la_flags & LLE_VALID) == 0) { | ||||
/* Try to perform LLE update */ | /* Try to perform LLE update */ | ||||
if (lltable_try_set_entry_addr(ifp, la, linkhdr, linkhdrsize, | if (lltable_try_set_entry_addr(ifp, la, linkhdr, linkhdrsize, | ||||
lladdr_off) == 0) | lladdr_off) == 0) | ||||
return; | return; | ||||
/* Clear fast path feedback request if set */ | /* Clear fast path feedback request if set */ | ||||
la->r_skip_req = 0; | llentry_mark_used(la); | ||||
} | } | ||||
arp_mark_lle_reachable(la); | arp_mark_lle_reachable(la); | ||||
/* | /* | ||||
* The packets are all freed within the call to the output | * The packets are all freed within the call to the output | ||||
* routine. | * routine. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 287 Lines • Show Last 20 Lines |