diff options
author | melifaro <melifaro@FreeBSD.org> | 2015-08-08 17:48:54 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2015-08-08 17:48:54 +0000 |
commit | 20bb5966e2075bde042b8b62c236e29d6e8934da (patch) | |
tree | 731dce9358d789a8c3034ce0eea54d4f64dad724 /sys/net | |
parent | 2039dd9ad41e9d94f6bf6471ffcf42c381368b69 (diff) | |
download | FreeBSD-src-20bb5966e2075bde042b8b62c236e29d6e8934da.zip FreeBSD-src-20bb5966e2075bde042b8b62c236e29d6e8934da.tar.gz |
MFP r274553:
* Move lle creation/deletion from lla_lookup to separate functions:
lla_lookup(LLE_CREATE) -> lla_create
lla_lookup(LLE_DELETE) -> lla_delete
lla_create now returns with LLE_EXCLUSIVE lock for lle.
* Provide typedefs for new/existing lltable callbacks.
Reviewed by: ae
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_llatbl.c | 125 | ||||
-rw-r--r-- | sys/net/if_llatbl.h | 47 |
2 files changed, 90 insertions, 82 deletions
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index 84ea6c6..3f4e737 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -147,8 +147,7 @@ llentry_alloc(struct ifnet *ifp, struct lltable *lt, if ((la == NULL) && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) { IF_AFDATA_WLOCK(ifp); - la = lla_lookup(lt, (LLE_CREATE | LLE_EXCLUSIVE), - (struct sockaddr *)dst); + la = lla_create(lt, 0, (struct sockaddr *)dst); IF_AFDATA_WUNLOCK(ifp); } @@ -259,7 +258,7 @@ lltable_init(struct ifnet *ifp, int af) } /* - * Called in route_output when adding/deleting a route to an interface. + * Called in route_output when rtm_flags contains RTF_LLDATA. */ int lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) @@ -270,8 +269,8 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) struct ifnet *ifp; struct lltable *llt; struct llentry *lle; - u_int laflags = 0, flags = 0; - int error = 0; + u_int laflags = 0; + int error; KASSERT(dl != NULL && dl->sdl_family == AF_LINK, ("%s: invalid dl\n", __func__)); @@ -283,24 +282,6 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) return EINVAL; } - switch (rtm->rtm_type) { - case RTM_ADD: - if (rtm->rtm_flags & RTF_ANNOUNCE) - flags |= LLE_PUB; - flags |= LLE_CREATE; - break; - - case RTM_DELETE: - flags |= LLE_DELETE; - break; - - case RTM_CHANGE: - break; - - default: - return EINVAL; /* XXX not implemented yet */ - } - /* XXX linked list may be too expensive */ LLTABLE_RLOCK(); SLIST_FOREACH(llt, &V_lltables, llt_link) { @@ -311,58 +292,62 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) LLTABLE_RUNLOCK(); KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n")); - if (flags & LLE_CREATE) - flags |= LLE_EXCLUSIVE; - - IF_AFDATA_LOCK(ifp); - lle = lla_lookup(llt, flags, dst); - IF_AFDATA_UNLOCK(ifp); - if (LLE_IS_VALID(lle)) { - if (flags & LLE_CREATE) { - /* - * If we delay the delete, then a subsequent - * "arp add" should look up this entry, reset the - * LLE_DELETED flag, and reset the expiration timer - */ - bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen); - lle->la_flags |= (flags & LLE_PUB); - lle->la_flags |= LLE_VALID; - lle->la_flags &= ~LLE_DELETED; + error = 0; + + switch (rtm->rtm_type) { + case RTM_ADD: + /* Add static LLE */ + IF_AFDATA_WLOCK(ifp); + lle = lla_create(llt, 0, dst); + if (lle == NULL) { + IF_AFDATA_WUNLOCK(ifp); + return (ENOMEM); + } + + + bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen); + if ((rtm->rtm_flags & RTF_ANNOUNCE)) + lle->la_flags |= LLE_PUB; + lle->la_flags |= LLE_VALID; #ifdef INET6 - /* - * ND6 - */ - if (dst->sa_family == AF_INET6) - lle->ln_state = ND6_LLINFO_REACHABLE; + /* + * ND6 + */ + if (dst->sa_family == AF_INET6) + lle->ln_state = ND6_LLINFO_REACHABLE; #endif - /* - * NB: arp and ndp always set (RTF_STATIC | RTF_HOST) - */ - - if (rtm->rtm_rmx.rmx_expire == 0) { - lle->la_flags |= LLE_STATIC; - lle->la_expire = 0; - } else - lle->la_expire = rtm->rtm_rmx.rmx_expire; - laflags = lle->la_flags; - LLE_WUNLOCK(lle); + /* + * NB: arp and ndp always set (RTF_STATIC | RTF_HOST) + */ + + if (rtm->rtm_rmx.rmx_expire == 0) { + lle->la_flags |= LLE_STATIC; + lle->la_expire = 0; + } else + lle->la_expire = rtm->rtm_rmx.rmx_expire; + laflags = lle->la_flags; + LLE_WUNLOCK(lle); + IF_AFDATA_WUNLOCK(ifp); #ifdef INET - /* gratuitous ARP */ - if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) - arprequest(ifp, - &((struct sockaddr_in *)dst)->sin_addr, - &((struct sockaddr_in *)dst)->sin_addr, - (u_char *)LLADDR(dl)); + /* gratuitous ARP */ + if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) + arprequest(ifp, + &((struct sockaddr_in *)dst)->sin_addr, + &((struct sockaddr_in *)dst)->sin_addr, + (u_char *)LLADDR(dl)); #endif - } else { - if (flags & LLE_EXCLUSIVE) - LLE_WUNLOCK(lle); - else - LLE_RUNLOCK(lle); - } - } else if ((lle == NULL) && (flags & LLE_DELETE)) - error = EINVAL; + break; + + case RTM_DELETE: + IF_AFDATA_WLOCK(ifp); + error = lla_delete(llt, 0, dst); + IF_AFDATA_WUNLOCK(ifp); + return (error == 0 ? 0 : ENOENT); + + default: + error = EINVAL; + } return (error); } diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index 4f21fde..69c340c 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -144,25 +144,33 @@ struct llentry { #define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1) #endif +typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags, + const struct sockaddr *l3addr); +typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags, + const struct sockaddr *l3addr); +typedef int (llt_delete_t)(struct lltable *, u_int flags, + const struct sockaddr *l3addr); +typedef void (llt_prefix_free_t)(struct lltable *, + const struct sockaddr *prefix, const struct sockaddr *mask, u_int flags); +typedef int (llt_dump_t)(struct lltable *, struct sysctl_req *); + struct lltable { SLIST_ENTRY(lltable) llt_link; struct llentries lle_head[LLTBL_HASHTBL_SIZE]; int llt_af; struct ifnet *llt_ifp; - void (*llt_prefix_free)(struct lltable *, - const struct sockaddr *prefix, - const struct sockaddr *mask, - u_int flags); - struct llentry * (*llt_lookup)(struct lltable *, u_int flags, - const struct sockaddr *l3addr); - int (*llt_dump)(struct lltable *, - struct sysctl_req *); + llt_lookup_t *llt_lookup; + llt_create_t *llt_create; + llt_delete_t *llt_delete; + llt_prefix_free_t *llt_prefix_free; + llt_dump_t *llt_dump; }; + MALLOC_DECLARE(M_LLTABLE); /* - * flags to be passed to arplookup. + * LLentry flags */ #define LLE_DELETED 0x0001 /* entry must be deleted */ #define LLE_STATIC 0x0002 /* entry is static */ @@ -170,9 +178,8 @@ MALLOC_DECLARE(M_LLTABLE); #define LLE_VALID 0x0008 /* ll_addr is valid */ #define LLE_PUB 0x0020 /* publish entry ??? */ #define LLE_LINKED 0x0040 /* linked to lookup structure */ +/* LLE request flags */ #define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */ -#define LLE_DELETE 0x4000 /* delete on a lookup - match LLE_IFADDR */ -#define LLE_CREATE 0x8000 /* create on a lookup miss */ #define LLATBL_HASH(key, mask) \ (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask) @@ -196,9 +203,25 @@ struct llentry *llentry_alloc(struct ifnet *, struct lltable *, static __inline struct llentry * lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) { - return llt->llt_lookup(llt, flags, l3addr); + + return (llt->llt_lookup(llt, flags, l3addr)); } +static __inline struct llentry * +lla_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) +{ + + return (llt->llt_create(llt, flags, l3addr)); +} + +static __inline int +lla_delete(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) +{ + + return (llt->llt_delete(llt, flags, l3addr)); +} + + int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *); #include <sys/eventhandler.h> |