Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if_llatbl.c
Show First 20 Lines • Show All 311 Lines • ▼ Show 20 Lines | lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle, | ||||
memcpy(lle->r_linkdata, linkhdr, linkhdrsize); | memcpy(lle->r_linkdata, linkhdr, linkhdrsize); | ||||
lle->r_hdrlen = linkhdrsize; | lle->r_hdrlen = linkhdrsize; | ||||
lle->ll_addr = &lle->r_linkdata[lladdr_off]; | lle->ll_addr = &lle->r_linkdata[lladdr_off]; | ||||
lle->la_flags |= LLE_VALID; | lle->la_flags |= LLE_VALID; | ||||
lle->r_flags |= RLLE_VALID; | lle->r_flags |= RLLE_VALID; | ||||
} | } | ||||
/* | bool | ||||
* Tries to update @lle link-level address. | lltable_acquire_wlock(struct ifnet *ifp, struct llentry *lle) | ||||
* Since update requires AFDATA WLOCK, function | |||||
* drops @lle lock, acquires AFDATA lock and then acquires | |||||
* @lle lock to maintain lock order. | |||||
* | |||||
* Returns 1 on success. | |||||
*/ | |||||
int | |||||
lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, | |||||
const char *linkhdr, size_t linkhdrsize, int lladdr_off) | |||||
{ | { | ||||
NET_EPOCH_ASSERT(); | |||||
/* Perform real LLE update */ | /* Perform real LLE update */ | ||||
/* use afdata WLOCK to update fields */ | /* use afdata WLOCK to update fields */ | ||||
LLE_WLOCK_ASSERT(lle); | |||||
LLE_ADDREF(lle); | |||||
LLE_WUNLOCK(lle); | LLE_WUNLOCK(lle); | ||||
IF_AFDATA_WLOCK(ifp); | IF_AFDATA_WLOCK(ifp); | ||||
LLE_WLOCK(lle); | LLE_WLOCK(lle); | ||||
/* | /* | ||||
* Since we droppped LLE lock, other thread might have deleted | * Since we droppped LLE lock, other thread might have deleted | ||||
* this lle. Check and return | * this lle. Check and return | ||||
*/ | */ | ||||
if ((lle->la_flags & LLE_DELETED) != 0) { | if ((lle->la_flags & LLE_DELETED) != 0) { | ||||
IF_AFDATA_WUNLOCK(ifp); | IF_AFDATA_WUNLOCK(ifp); | ||||
LLE_FREE_LOCKED(lle); | return (false); | ||||
return (0); | |||||
} | } | ||||
return (true); | |||||
} | |||||
/* | |||||
* Tries to update @lle link-level address. | |||||
* Since update requires AFDATA WLOCK, function | |||||
* drops @lle lock, acquires AFDATA lock and then acquires | |||||
* @lle lock to maintain lock order. | |||||
* | |||||
* Returns 1 on success. | |||||
*/ | |||||
int | |||||
lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, | |||||
const char *linkhdr, size_t linkhdrsize, int lladdr_off) | |||||
{ | |||||
if (!lltable_acquire_wlock(ifp, lle)) | |||||
return (0); | |||||
/* Update data */ | /* Update data */ | ||||
lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off); | lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off); | ||||
IF_AFDATA_WUNLOCK(ifp); | IF_AFDATA_WUNLOCK(ifp); | ||||
LLE_REMREF(lle); | |||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* Helper function used to pre-compute full/partial link-layer | * Helper function used to pre-compute full/partial link-layer | ||||
* header data suitable for feeding into if_output(). | * header data suitable for feeding into if_output(). | ||||
*/ | */ | ||||
int | int | ||||
Show All 16 Lines | if (error == 0) { | ||||
*bufsize = ereq.bufsize; | *bufsize = ereq.bufsize; | ||||
*lladdr_off = ereq.lladdr_off; | *lladdr_off = ereq.lladdr_off; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Searches for the child entry matching @family inside @lle. | |||||
* Returns the entry or NULL. | |||||
*/ | |||||
struct llentry * | |||||
llentry_lookup_family(struct llentry *lle, int family) | |||||
{ | |||||
struct llentry *child_lle; | |||||
if (lle == NULL) | |||||
return (NULL); | |||||
CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) { | |||||
if (child_lle->r_family == family) | |||||
return (child_lle); | |||||
} | |||||
return (NULL); | |||||
} | |||||
void | |||||
llentry_request_feedback(struct llentry *lle) | |||||
zlei: This has been committed in main. Better to exclude this to help reviewing :) | |||||
Done Inline ActionsYeah, I’ll commit another part of the diff and update this one today. melifaro: Yeah, I’ll commit another part of the diff and update this one today.
Could you actually rebase… | |||||
{ | |||||
struct llentry *child_lle; | |||||
LLE_REQ_LOCK(lle); | |||||
lle->r_skip_req = 1; | |||||
LLE_REQ_UNLOCK(lle); | |||||
CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) { | |||||
LLE_REQ_LOCK(child_lle); | |||||
child_lle->r_skip_req = 1; | |||||
LLE_REQ_UNLOCK(child_lle); | |||||
} | |||||
} | |||||
static time_t | |||||
llentry_get_hittime_raw(struct llentry *lle) | |||||
{ | |||||
time_t lle_hittime = 0; | |||||
LLE_REQ_LOCK(lle); | |||||
if ((lle->r_skip_req == 0) && (lle_hittime < lle->lle_hittime)) | |||||
lle_hittime = lle->lle_hittime; | |||||
LLE_REQ_UNLOCK(lle); | |||||
return (lle_hittime); | |||||
} | |||||
time_t | |||||
llentry_get_hittime(struct llentry *lle) | |||||
{ | |||||
time_t lle_hittime = 0; | |||||
struct llentry *child_lle; | |||||
lle_hittime = llentry_get_hittime_raw(lle); | |||||
CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) { | |||||
time_t hittime = llentry_get_hittime_raw(child_lle); | |||||
if (hittime > lle_hittime) | |||||
lle_hittime = hittime; | |||||
} | |||||
return (lle_hittime); | |||||
} | |||||
/* | |||||
* Update link-layer header for given @lle after | * Update link-layer header for given @lle after | ||||
* interface lladdr was changed. | * interface lladdr was changed. | ||||
*/ | */ | ||||
static int | static int | ||||
llentry_update_ifaddr(struct lltable *llt, struct llentry *lle, void *farg) | llentry_update_ifaddr(struct lltable *llt, struct llentry *lle, void *farg) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
u_char linkhdr[LLE_MAX_LINKHDR]; | u_char linkhdr[LLE_MAX_LINKHDR]; | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | |||||
lltable_delete_addr(struct lltable *llt, u_int flags, | lltable_delete_addr(struct lltable *llt, u_int flags, | ||||
const struct sockaddr *l3addr) | const struct sockaddr *l3addr) | ||||
{ | { | ||||
struct llentry *lle; | struct llentry *lle; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
ifp = llt->llt_ifp; | ifp = llt->llt_ifp; | ||||
IF_AFDATA_WLOCK(ifp); | IF_AFDATA_WLOCK(ifp); | ||||
lle = lla_lookup(llt, LLE_EXCLUSIVE, l3addr); | lle = lla_lookup(llt, LLE_SF(LLE_EXCLUSIVE, l3addr->sa_family), l3addr); | ||||
if (lle == NULL) { | if (lle == NULL) { | ||||
IF_AFDATA_WUNLOCK(ifp); | IF_AFDATA_WUNLOCK(ifp); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) { | if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) { | ||||
IF_AFDATA_WUNLOCK(ifp); | IF_AFDATA_WUNLOCK(ifp); | ||||
LLE_WUNLOCK(lle); | LLE_WUNLOCK(lle); | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | lltable_free_entry(struct lltable *llt, struct llentry *lle) | ||||
llt->llt_free_entry(llt, lle); | llt->llt_free_entry(llt, lle); | ||||
} | } | ||||
int | int | ||||
lltable_link_entry(struct lltable *llt, struct llentry *lle) | lltable_link_entry(struct lltable *llt, struct llentry *lle) | ||||
{ | { | ||||
return (llt->llt_link_entry(llt, lle)); | return (llt->llt_link_entry(llt, lle)); | ||||
} | |||||
void | |||||
lltable_link_child_entry(struct llentry *parent_lle, struct llentry *child_lle) | |||||
{ | |||||
child_lle->lle_parent = parent_lle; | |||||
child_lle->lle_tbl = parent_lle->lle_tbl; | |||||
child_lle->la_flags |= LLE_LINKED; | |||||
CK_SLIST_INSERT_HEAD(&parent_lle->lle_children, child_lle, lle_child_next); | |||||
} | |||||
void | |||||
lltable_unlink_child_entry(struct llentry *child_lle) | |||||
{ | |||||
struct llentry *parent_lle = child_lle->lle_parent; | |||||
Not Done Inline ActionsI'm not familiar with CK_SLIST, but it seems that child_lle is not removed from child_lle->lle_parent->lle_children . zlei: I'm not familiar with `CK_SLIST`, but it seems that `child_lle` is not removed from `child_lle… | |||||
Done Inline ActionsYeah, this looks misleading. The rationale here is the following - we never delete a child wo deleting a parent, so we dont need to bother w/ll and the complexity of the lock ordering. I’ll look at this once again melifaro: Yeah, this looks misleading. The rationale here is the following - we never delete a child wo… | |||||
CK_SLIST_REMOVE(&parent_lle->lle_children, child_lle, llentry, lle_child_next); | |||||
} | } | ||||
int | int | ||||
lltable_unlink_entry(struct lltable *llt, struct llentry *lle) | lltable_unlink_entry(struct lltable *llt, struct llentry *lle) | ||||
{ | { | ||||
return (llt->llt_unlink_entry(lle)); | return (llt->llt_unlink_entry(lle)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 271 Lines • Show Last 20 Lines |
This has been committed in main. Better to exclude this to help reviewing :)