svn commit: r185820 - projects/arpv2_merge_1/sys/net
Kip Macy
kmacy at FreeBSD.org
Tue Dec 9 18:10:45 PST 2008
Author: kmacy
Date: Wed Dec 10 02:10:44 2008
New Revision: 185820
URL: http://svn.freebsd.org/changeset/base/185820
Log:
add if_llatbl.[ch]
Added:
projects/arpv2_merge_1/sys/net/if_llatbl.c (contents, props changed)
projects/arpv2_merge_1/sys/net/if_llatbl.h (contents, props changed)
Added: projects/arpv2_merge_1/sys/net/if_llatbl.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/arpv2_merge_1/sys/net/if_llatbl.c Wed Dec 10 02:10:44 2008 (r185820)
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2007 Qing Li, Luigi Rizzo, Alessandro Cerri. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/mutex.h>
+#include <sys/vimage.h>
+
+#include <vm/uma.h>
+
+#include <netinet/in.h>
+#include <net/if_llatbl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_var.h>
+#include <net/route.h>
+#include <netinet/if_ether.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
+
+static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables);
+
+extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
+ u_char *);
+
+/*
+ * Dump arp state for a specific address family.
+ */
+int
+lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
+{
+ struct lltable *llt;
+ int error = 0;
+
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af == af) {
+ error = llt->llt_dump(llt, wr);
+ if (error != 0)
+ goto done;
+ }
+ }
+done:
+ IFNET_RUNLOCK();
+ return (error);
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+void
+llentry_free(struct llentry *lle)
+{
+ struct lltable *llt = lle->lle_tbl;
+
+ LIST_REMOVE(lle, lle_next);
+
+ if (lle->la_hold != NULL)
+ m_freem(lle->la_hold);
+ llt->llt_free(llt, lle);
+}
+
+/*
+ * Free all entries from given table and free itself.
+ * Since lltables collects from all of the intefaces,
+ * the caller of this function must acquire IFNET_WLOCK().
+ */
+void
+lltable_free(struct lltable *llt)
+{
+ struct llentry *lle, *next;
+ int i;
+
+ KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
+
+ IFNET_WLOCK();
+ SLIST_REMOVE(&lltables, llt, lltable, llt_link);
+ IFNET_WUNLOCK();
+
+ for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
+ callout_drain(&lle->la_timer);
+ llentry_free(lle);
+ }
+ }
+
+ free(llt, M_LLTABLE);
+}
+
+void
+lltable_drain(int af)
+{
+ struct lltable *llt;
+ struct llentry *lle;
+ register int i;
+
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af != af)
+ continue;
+
+ for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ if (lle->la_hold) {
+ m_freem(lle->la_hold);
+ lle->la_hold = NULL;
+ }
+ }
+ }
+ }
+ IFNET_RUNLOCK();
+}
+
+/*
+ * Create a new lltable.
+ */
+struct lltable *
+lltable_init(struct ifnet *ifp, int af)
+{
+ struct lltable *llt;
+ register int i;
+
+ llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK);
+ if (llt == NULL)
+ return (NULL);
+
+ llt->llt_af = af;
+ llt->llt_ifp = ifp;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
+ LIST_INIT(&llt->lle_head[i]);
+
+ IFNET_WLOCK();
+ SLIST_INSERT_HEAD(&lltables, llt, llt_link);
+ IFNET_WUNLOCK();
+
+ return (llt);
+}
+
+/*
+ * Called in route_output when adding/deleting a route to an interface.
+ */
+int
+lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
+{
+ struct sockaddr_dl *dl =
+ (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY];
+ struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST];
+ struct ifnet *ifp;
+ struct lltable *llt;
+ struct llentry *lle;
+ u_int flags = 0;
+
+ if (dl == NULL || dl->sdl_family != AF_LINK) {
+ log(LOG_INFO, "%s: invalid dl\n", __func__);
+ return EINVAL;
+ }
+ ifp = ifnet_byindex(dl->sdl_index);
+ if (ifp == NULL) {
+ log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
+ __func__, dl->sdl_index);
+ return EINVAL;
+ }
+
+ switch (rtm->rtm_type) {
+ case RTM_ADD:
+ if (rtm->rtm_flags & RTF_ANNOUNCE) {
+ flags |= LLE_PUB;
+#ifdef INET
+ if (dst->sa_family == AF_INET &&
+ ((struct sockaddr_inarp *)dst)->sin_other != 0) {
+ struct rtentry *rt = rtalloc1(dst, 0, 0);
+ if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
+ log(LOG_INFO, "%s: RTM_ADD publish "
+ "(proxy only) is invalid\n",
+ __func__);
+ rtfree(rt);
+ return EINVAL;
+ }
+ rtfree(rt);
+
+ flags |= LLE_PROXY;
+ }
+#endif
+ }
+ flags |= LLE_CREATE;
+ break;
+
+ case RTM_DELETE:
+ flags |= LLE_DELETE;
+ break;
+
+ case RTM_CHANGE:
+ break;
+
+ default:
+ return EINVAL; /* XXX not implemented yet */
+ }
+
+ /*
+ * XXXXXXXX:
+ * REVISE this approach if possible.
+ */
+ IFNET_WLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af == dst->sa_family &&
+ llt->llt_ifp == ifp)
+ break;
+ }
+ IFNET_WUNLOCK();
+ KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
+
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(llt, flags, dst);
+ if (lle != NULL) {
+ if (flags & LLE_CREATE) {
+ /* qing: if we delay the delete, then if a subsequent
+ * "arp add" on the same host 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 |= LLE_VALID;
+ lle->la_flags &= ~LLE_DELETED;
+#ifdef INET6
+ /*
+ * ND6
+ */
+ if (dst->sa_family == AF_INET6)
+ lle->ln_state = ND6_LLINFO_REACHABLE;
+#endif
+ /*
+ * "arp" and "ndp" always sets the (RTF_STATIC | RTF_HOST) flags
+ */
+ 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;
+#ifdef INET
+ /* gratuious ARP */
+ if ((lle->la_flags & LLE_PUB) &&
+ dst->sa_family == AF_INET) {
+ arprequest(ifp,
+ &((struct sockaddr_in *)dst)->sin_addr,
+ &((struct sockaddr_in *)dst)->sin_addr,
+ ((lle->la_flags & LLE_PROXY) ?
+ (u_char *)IF_LLADDR(ifp) :
+ (u_char *)LLADDR(dl)));
+ }
+#endif
+ }
+ } else {
+ if (flags & LLE_DELETE) {
+ IF_AFDATA_UNLOCK(ifp);
+ return EINVAL;
+ }
+ }
+
+ IF_AFDATA_UNLOCK(ifp);
+ return 0;
+}
Added: projects/arpv2_merge_1/sys/net/if_llatbl.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/arpv2_merge_1/sys/net/if_llatbl.h Wed Dec 10 02:10:44 2008 (r185820)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2007 Qing Li, Luigi Rizzo, Alessandro Cerri. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _NET_IF_LLATBL_H_
+#define _NET_IF_LLATBL_H_
+
+#include <netinet/in.h>
+
+struct ifnet;
+struct sysctl_req;
+struct rt_msghdr;
+struct rt_addrinfo;
+
+struct llentry;
+LIST_HEAD(llentries, llentry);
+
+struct llentry {
+ LIST_ENTRY(llentry) lle_next;
+ struct lltable *lle_tbl;
+ struct llentries *lle_head;
+ struct mbuf *la_hold;
+ time_t la_expire;
+ uint16_t la_flags;
+ uint16_t la_asked;
+ uint16_t la_preempt;
+ uint16_t ln_byhint;
+ int16_t ln_state; /* IPv6 has ND6_LLINFO_NOSTATE == -2 */
+ uint16_t ln_router;
+ time_t ln_ntick;
+ union {
+ uint64_t mac_aligned;
+ uint16_t mac16[3];
+ } ll_addr;
+
+ /* XXX af-private? */
+ union {
+ struct callout ln_timer_ch;
+ struct callout la_timer;
+ } lle_timer;
+ /* NB: struct sockaddr must immediately follow */
+};
+
+#define ln_timer_ch lle_timer.ln_timer_ch
+#define la_timer lle_timer.la_timer
+
+/* XXX bad name */
+#define L3_ADDR(lle) ((struct sockaddr *)(&lle[1]))
+#define L3_ADDR_LEN(lle) (((struct sockaddr *)(&lle[1]))->sa_len)
+
+#ifndef LLTBL_HASHTBL_SIZE
+#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */
+#endif
+
+#ifndef LLTBL_HASHMASK
+#define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1)
+#endif
+
+struct lltable {
+ SLIST_ENTRY(lltable) llt_link;
+ struct llentries lle_head[LLTBL_HASHTBL_SIZE];
+ int llt_af;
+ struct ifnet *llt_ifp;
+
+ struct llentry * (*llt_new)(const struct sockaddr *, u_int);
+ void (*llt_free)(struct lltable *, struct llentry *);
+ struct llentry * (*llt_lookup)(struct lltable *, u_int flags,
+ const struct sockaddr *l3addr);
+ int (*llt_rtcheck)(struct ifnet *,
+ const struct sockaddr *);
+ int (*llt_dump)(struct lltable *,
+ struct sysctl_req *);
+};
+MALLOC_DECLARE(M_LLTABLE);
+
+/*
+ * flags to be passed to arplookup.
+ */
+#define LLE_DELETED 0x0001 /* entry must be deleted */
+#define LLE_STATIC 0x0002 /* entry is static */
+#define LLE_IFADDR 0x0004 /* entry is interface addr */
+#define LLE_VALID 0x0008 /* ll_addr is valid */
+#define LLE_PROXY 0x0010 /* proxy entry ??? */
+#define LLE_PUB 0x0020 /* publish entry ??? */
+#define LLE_CREATE 0x8000 /* create on a lookup miss */
+#define LLE_DELETE 0x4000 /* delete on a lookup - match LLE_IFADDR */
+
+#define LLATBL_HASH(key, mask) \
+ (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
+
+struct lltable *lltable_init(struct ifnet *, int);
+void lltable_free(struct lltable *);
+void lltable_drain(int);
+int lltable_sysctl_dumparp(int, struct sysctl_req *);
+
+void llentry_free(struct llentry *);
+
+/*
+ * Generic link layer address lookup function.
+ */
+static __inline struct llentry *
+lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+{
+ return llt->llt_lookup(llt, flags, l3addr);
+}
+
+int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
+#endif /* _NET_IF_LLATBL_H_ */
More information about the svn-src-projects
mailing list