aboutsummaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2014-11-15 18:54:07 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2014-11-15 18:54:07 +0000
commitb4b1367ae445f81d591a0fa3fc1c062b90f212f2 (patch)
tree1fee30c03fdef5eb309a0458e2610c5e8997fa29 /sys/net
parentf7bab8d0dd8d6cf0d76499bff7e4f477a00fd202 (diff)
downloadsrc-b4b1367ae445f81d591a0fa3fc1c062b90f212f2.tar.gz
src-b4b1367ae445f81d591a0fa3fc1c062b90f212f2.zip
* Move lle creation/deletion from lla_lookup to separate functions:
lla_lookup(LLE_CREATE) -> lla_create lla_lookup(LLE_DELETE) -> lla_delete Assume lla_create to return LLE_EXCLUSIVE lock for lle. * Rework lla_rt_output to perform all lle changes under afdata WLOCK. * change arp_ifscrub() ackquire afdata WLOCK, the same as arp_ifinit().
Notes
Notes: svn path=/projects/routing/; revision=274553
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_llatbl.c125
-rw-r--r--sys/net/if_llatbl.h45
2 files changed, 89 insertions, 81 deletions
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index 84ea6c688afd..3f4e7378abaa 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 4f21fdea4473..7bde86a54145 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.
+ * Various LLE 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);
}
+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>