route table is now replicated across all cpus (ncpus, not ncpus2).
Note that cloned routes are not replicated.
This removes one of the few remaining obstacles to being able
to run the network protocol stacks without the BGL.
Primary-Design-by: Jeffrey Hsu
Work-by: Jeffrey Hsu and Matthew Dillon
*
* Machine independant code should not directly include this file.
*
- * $DragonFly: src/sys/i386/include/Attic/thread.h,v 1.13 2005/06/16 21:12:46 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/thread.h,v 1.14 2006/01/31 19:05:30 dillon Exp $
*/
#ifndef _MACHINE_THREAD_H_
}
#define mycpu _get_mycpu()
-#define mycpuid _get_mycpu()->gd_cpuid
+
+#ifdef SMP
+#define mycpuid (_get_mycpu()->gd_cpuid)
+#else
+#define mycpuid 0
+#endif
/*
* note: curthread is never NULL, but curproc can be. Also note that
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.90 2005/12/10 18:50:36 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.91 2006/01/31 19:05:33 dillon Exp $
*/
/*
#endif
}
+void
+lwkt_migratecpu(int cpuid)
+{
+#ifdef SMP
+ globaldata_t rgd;
+
+ rgd = globaldata_find(cpuid);
+ lwkt_setcpu_self(rgd);
+#endif
+}
+
/*
* Remote IPI for cpu migration (called while in a critical section so we
* do not have to enter another one). The thread has already been moved to
* $OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp $
* $NetBSD: if_bridge.c,v 1.31 2005/06/01 19:45:34 jdc Exp $
* $FreeBSD: src/sys/net/if_bridge.c,v 1.26 2005/10/13 23:05:55 thompsa Exp $
- * $DragonFly: src/sys/net/bridge/if_bridge.c,v 1.4 2006/01/14 11:05:17 swildner Exp $
+ * $DragonFly: src/sys/net/bridge/if_bridge.c,v 1.5 2006/01/31 19:05:37 dillon Exp $
*/
/*
eh = mtod(m, struct ether_header *);
+ /*
+ * Various ifp's are used below, release the serializer for
+ * the bridge ifp so other ifp serializers can be acquired.
+ */
+ lwkt_serialize_exit(ifp->if_serializer);
+
/*
* If the interface is learning, and the source
* address is valid and not multicast, record
if ((bif->bif_flags & IFBIF_STP) != 0 &&
bif->bif_state == BSTP_IFSTATE_LEARNING) {
m_freem(m);
- return;
+ goto done;
}
/*
dst_if = bridge_rtlookup(sc, eh->ether_dhost);
if (src_if == dst_if) {
m_freem(m);
- return;
+ goto done;
}
} else {
/* ...forward it to all interfaces. */
#endif
) {
if (bridge_pfil(&m, ifp, src_if, PFIL_IN) != 0)
- return;
+ goto done;
if (m == NULL)
- return;
+ goto done;
}
if (dst_if == NULL) {
- lwkt_serialize_exit(ifp->if_serializer);
bridge_broadcast(sc, src_if, m, 1);
- lwkt_serialize_enter(ifp->if_serializer);
- return;
+ goto done;
}
/*
*/
if ((dst_if->if_flags & IFF_RUNNING) == 0) {
m_freem(m);
- return;
+ goto done;
}
bif = bridge_lookup_member_if(sc, dst_if);
if (bif == NULL) {
/* Not a member of the bridge (anymore?) */
m_freem(m);
- return;
+ goto done;
}
if (bif->bif_flags & IFBIF_STP) {
case BSTP_IFSTATE_DISABLED:
case BSTP_IFSTATE_BLOCKING:
m_freem(m);
- return;
+ goto done;
}
}
#endif
) {
if (bridge_pfil(&m, sc->sc_ifp, dst_if, PFIL_OUT) != 0)
- return;
+ goto done;
if (m == NULL)
- return;
+ goto done;
}
- lwkt_serialize_exit(ifp->if_serializer);
bridge_enqueue(sc, dst_if, m);
+
+ /*
+ * ifp's serializer was held on entry and is expected to be held
+ * on return.
+ */
+done:
lwkt_serialize_enter(ifp->if_serializer);
}
*
* @(#)if.c 8.3 (Berkeley) 1/4/94
* $FreeBSD: src/sys/net/if.c,v 1.185 2004/03/13 02:35:03 brooks Exp $
- * $DragonFly: src/sys/net/if.c,v 1.43 2005/11/28 17:13:45 dillon Exp $
+ * $DragonFly: src/sys/net/if.c,v 1.44 2006/01/31 19:05:35 dillon Exp $
*/
#include "opt_compat.h"
struct ifaddr *ifa;
struct radix_node_head *rnh;
int i;
+ int cpu, origcpu;
struct domain *dp;
EVENTHANDLER_INVOKE(ifnet_detach_event, ifp);
* the entire routing table looking for routes which point
* to this interface...oh well...
*/
- for (i = 1; i <= AF_MAX; i++) {
- if ((rnh = rt_tables[i]) == NULL)
- continue;
- rnh->rnh_walktree(rnh, if_rtdel, ifp);
+ origcpu = mycpuid;
+ for (cpu = 0; cpu < ncpus2; cpu++) {
+ lwkt_migratecpu(cpu);
+ for (i = 1; i <= AF_MAX; i++) {
+ if ((rnh = rt_tables[mycpuid][i]) == NULL)
+ continue;
+ rnh->rnh_walktree(rnh, if_rtdel, ifp);
+ }
}
+ lwkt_migratecpu(origcpu);
/* Announce that the interface is gone. */
rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/net/netisr.c,v 1.24 2006/01/14 11:05:17 swildner Exp $
+ * $DragonFly: src/sys/net/netisr.c,v 1.25 2006/01/31 19:05:35 dillon Exp $
*/
/*
return (&netisr_cpu[0].td_msgport);
}
+lwkt_port_t
+cpu_portfn(int cpu)
+{
+ return (&netisr_cpu[cpu].td_msgport);
+}
+
/* ARGSUSED */
lwkt_port_t
cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused,
*
* @(#)netisr.h 8.1 (Berkeley) 6/10/93
* $FreeBSD: src/sys/net/netisr.h,v 1.21.2.5 2002/02/09 23:02:39 luigi Exp $
- * $DragonFly: src/sys/net/netisr.h,v 1.21 2005/01/19 17:30:52 dillon Exp $
+ * $DragonFly: src/sys/net/netisr.h,v 1.22 2006/01/31 19:05:35 dillon Exp $
*/
#ifndef _NET_NETISR_H_
extern lwkt_port netisr_afree_rport;
lwkt_port_t cpu0_portfn(struct mbuf **mptr);
+lwkt_port_t cpu_portfn(int cpu);
void netisr_dispatch(int, struct mbuf *);
int netisr_queue(int, struct mbuf *);
void netisr_register(int, lwkt_portfn_t, netisr_fn_t);
*
* @(#)radix.c 8.4 (Berkeley) 11/2/94
* $FreeBSD: src/sys/net/radix.c,v 1.20.2.3 2002/04/28 05:40:25 suz Exp $
- * $DragonFly: src/sys/net/radix.c,v 1.12 2006/01/14 11:05:17 swildner Exp $
+ * $DragonFly: src/sys/net/radix.c,v 1.13 2006/01/31 19:05:35 dillon Exp $
*/
/*
static int max_keylen;
static char *rn_zeros, *rn_ones;
-static char *addmask_key;
static int rn_lexobetter(char *m, char *n);
static struct radix_mask *
int b = 0, mlen, m0, j;
boolean_t maskduplicated, isnormal;
static int last_zeroed = 0;
+ char *addmask_key;
if ((mlen = clen(netmask)) > max_keylen)
mlen = max_keylen;
skip = 1;
if (mlen <= skip)
return (mask_rnhead->rnh_nodes);
+ R_Malloc(addmask_key, char *, max_keylen);
+ if (addmask_key == NULL)
+ return NULL;
if (skip > 1)
bcopy(rn_ones + 1, addmask_key + 1, skip - 1);
if ((m0 = mlen) > skip)
if (mlen <= skip) {
if (m0 >= last_zeroed)
last_zeroed = mlen;
+ Free(addmask_key);
return (mask_rnhead->rnh_nodes);
}
if (m0 < last_zeroed)
if (bcmp(addmask_key, x->rn_key, mlen) != 0)
x = NULL;
if (x != NULL || search)
- return (x);
+ goto out;
R_Malloc(x, struct radix_node *, max_keylen + 2 * (sizeof *x));
if ((saved_x = x) == NULL)
- return (NULL);
+ goto out;
bzero(x, max_keylen + 2 * (sizeof *x));
netmask = cp = (char *)(x + 2);
bcopy(addmask_key, cp, mlen);
if (maskduplicated) {
log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
Free(saved_x);
- return (x);
+ goto out;
}
/*
* Calculate index of mask, and check for normalcy.
x->rn_bit = -1 - b;
if (isnormal)
x->rn_flags |= RNF_NORMAL;
+out:
+ Free(addmask_key);
return (x);
}
"rn_init: radix functions require max_keylen be set\n");
return;
}
- R_Malloc(rn_zeros, char *, 3 * max_keylen);
+ R_Malloc(rn_zeros, char *, 2 * max_keylen);
if (rn_zeros == NULL)
panic("rn_init");
- bzero(rn_zeros, 3 * max_keylen);
+ bzero(rn_zeros, 2 * max_keylen);
rn_ones = cp = rn_zeros + max_keylen;
- addmask_key = cplim = rn_ones + max_keylen;
+ cplim = rn_ones + max_keylen;
while (cp < cplim)
*cp++ = -1;
if (rn_inithead((void **)&mask_rnhead, 0) == 0)
*
* @(#)route.c 8.3 (Berkeley) 1/9/95
* $FreeBSD: src/sys/net/route.c,v 1.59.2.10 2003/01/17 08:04:00 ru Exp $
- * $DragonFly: src/sys/net/route.c,v 1.23 2006/01/14 11:05:17 swildner Exp $
+ * $DragonFly: src/sys/net/route.c,v 1.24 2006/01/31 19:05:35 dillon Exp $
*/
#include "opt_inet.h"
#include <sys/globaldata.h>
#include <sys/thread.h>
#include <sys/thread2.h>
+#include <sys/msgport2.h>
#include <net/if.h>
#include <net/route.h>
+#include <net/netisr.h>
#include <netinet/in.h>
#include <net/ip_mroute/ip_mroute.h>
#define rtstat rtstatistics_percpu[0]
#endif
-struct radix_node_head *rt_tables[AF_MAX+1];
+struct radix_node_head *rt_tables[MAXCPU][AF_MAX+1];
+struct lwkt_port *rt_ports[MAXCPU];
static void rt_maskedcopy (struct sockaddr *, struct sockaddr *,
struct sockaddr *);
-static void rtable_init (void **);
+static void rtable_init(void);
+static void rtable_service_loop(void *dummy);
+static void rtinit_rtrequest_callback(int, int, struct rt_addrinfo *,
+ struct rtentry *, void *);
+
+#ifdef SMP
+static int rtredirect_msghandler(struct lwkt_msg *lmsg);
+static int rtrequest1_msghandler(struct lwkt_msg *lmsg);
+#endif
SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RW, 0, "Routing");
+/*
+ * Initialize the route table(s) for protocol domains and
+ * create a helper thread which will be responsible for updating
+ * route table entries on each cpu.
+ */
+void
+route_init(void)
+{
+ int cpu, origcpu;
+ thread_t rtd;
+
+ for (cpu = 0; cpu < ncpus; ++cpu)
+ bzero(&rtstatistics_percpu[cpu], sizeof(struct rtstatistics));
+ rn_init(); /* initialize all zeroes, all ones, mask table */
+ origcpu = mycpuid;
+ for (cpu = 0; cpu < ncpus; cpu++) {
+ lwkt_migratecpu(cpu);
+ rtable_init();
+ lwkt_create(rtable_service_loop, NULL, &rtd, NULL,
+ TDF_STOPREQ, cpu, "rtable_cpu %d", cpu);
+ rt_ports[cpu] = &rtd->td_msgport;
+ lwkt_schedule(rtd);
+ }
+ lwkt_migratecpu(origcpu);
+}
+
static void
-rtable_init(void **table)
+rtable_init(void)
{
struct domain *dom;
- SLIST_FOREACH(dom, &domains, dom_next)
- if (dom->dom_rtattach)
- dom->dom_rtattach(&table[dom->dom_family],
- dom->dom_rtoffset);
+ SLIST_FOREACH(dom, &domains, dom_next) {
+ if (dom->dom_rtattach) {
+ dom->dom_rtattach(
+ (void **)&rt_tables[mycpuid][dom->dom_family],
+ dom->dom_rtoffset);
+ }
+ }
}
-void
-route_init(void)
+/*
+ * Our per-cpu table management protocol thread. All route table operations
+ * are chained through all cpus in order starting at cpu #0 in order to
+ * maintain duplicate route tables on each cpu. Having a spearate route
+ * table management thread allows the protocol and interrupt threads to
+ * issue route table changes.
+ */
+static void
+rtable_service_loop(void *dummy __unused)
{
-#ifdef SMP
- int ccpu;
-
- for (ccpu = 0; ccpu < ncpus; ++ccpu)
- bzero(&rtstatistics_percpu[ccpu], sizeof(struct rtstatistics));
-#else
- bzero(&rtstat, sizeof(struct rtstatistics));
-#endif
+ struct lwkt_msg *lmsg;
+ thread_t td = curthread;
- rn_init(); /* initialize all zeroes, all ones, mask table */
- rtable_init((void **)rt_tables);
+ while ((lmsg = lwkt_waitport(&td->td_msgport, NULL)) != NULL) {
+ lmsg->ms_cmd.cm_func(lmsg);
+ }
}
/*
struct rtentry *
_rtlookup(struct sockaddr *dst, boolean_t generate_report, u_long ignore)
{
- struct radix_node_head *rnh = rt_tables[dst->sa_family];
+ struct radix_node_head *rnh = rt_tables[mycpuid][dst->sa_family];
struct rtentry *rt;
if (rnh == NULL)
--rt->rt_refcnt;
if (rt->rt_refcnt == 0) {
- struct radix_node_head *rnh = rt_tables[rt_key(rt)->sa_family];
+ struct radix_node_head *rnh =
+ rt_tables[mycpuid][rt_key(rt)->sa_family];
if (rnh->rnh_close)
rnh->rnh_close((struct radix_node *)rt, rnh);
}
}
-/*
- * Force a routing table entry to the specified destination to go through
- * the given gateway. Normally called as a result of a routing redirect
- * message from the network layer.
- *
- * N.B.: must be called at splnet
- */
-void
-rtredirect(struct sockaddr *dst, struct sockaddr *gateway,
- struct sockaddr *netmask, int flags, struct sockaddr *src)
+static int
+rtredirect_oncpu(struct sockaddr *dst, struct sockaddr *gateway,
+ struct sockaddr *netmask, int flags, struct sockaddr *src)
{
struct rtentry *rt = NULL;
struct rt_addrinfo rtinfo;
else if (stat != NULL)
(*stat)++;
+ return error;
+}
+
+#ifdef SMP
+
+struct netmsg_rtredirect {
+ struct lwkt_msg lmsg;
+ struct sockaddr *dst;
+ struct sockaddr *gateway;
+ struct sockaddr *netmask;
+ int flags;
+ struct sockaddr *src;
+};
+
+#endif
+
+/*
+ * Force a routing table entry to the specified
+ * destination to go through the given gateway.
+ * Normally called as a result of a routing redirect
+ * message from the network layer.
+ *
+ * N.B.: must be called at splnet
+ */
+void
+rtredirect(struct sockaddr *dst, struct sockaddr *gateway,
+ struct sockaddr *netmask, int flags, struct sockaddr *src)
+{
+ struct rt_addrinfo rtinfo;
+ int error;
+#ifdef SMP
+ struct netmsg_rtredirect msg;
+
+ lwkt_initmsg(&msg.lmsg, &curthread->td_msgport, 0,
+ lwkt_cmd_func(rtredirect_msghandler), lwkt_cmd_op_none);
+ msg.dst = dst;
+ msg.gateway = gateway;
+ msg.netmask = netmask;
+ msg.flags = flags;
+ msg.src = src;
+ error = lwkt_domsg(rtable_portfn(0), &msg.lmsg);
+#else
+ error = rtredirect_oncpu(dst, gateway, netmask, flags, src);
+#endif
bzero(&rtinfo, sizeof(struct rt_addrinfo));
rtinfo.rti_info[RTAX_DST] = dst;
rtinfo.rti_info[RTAX_GATEWAY] = gateway;
rt_missmsg(RTM_REDIRECT, &rtinfo, flags, error);
}
+#ifdef SMP
+
+static int
+rtredirect_msghandler(struct lwkt_msg *lmsg)
+{
+ struct netmsg_rtredirect *msg = (void *)lmsg;
+ int nextcpu;
+
+ rtredirect_oncpu(msg->dst, msg->gateway, msg->netmask,
+ msg->flags, msg->src);
+ nextcpu = mycpuid + 1;
+ if (nextcpu < ncpus)
+ lwkt_forwardmsg(rtable_portfn(nextcpu), &msg->lmsg);
+ else
+ lwkt_replymsg(&msg->lmsg, 0);
+ return (0);
+}
+
+#endif
+
/*
* Routing table ioctl interface.
*/
return rtrequest1(req, &rtinfo, ret_nrt);
}
+int
+rtrequest_global(
+ int req,
+ struct sockaddr *dst,
+ struct sockaddr *gateway,
+ struct sockaddr *netmask,
+ int flags)
+{
+ struct rt_addrinfo rtinfo;
+
+ bzero(&rtinfo, sizeof(struct rt_addrinfo));
+ rtinfo.rti_info[RTAX_DST] = dst;
+ rtinfo.rti_info[RTAX_GATEWAY] = gateway;
+ rtinfo.rti_info[RTAX_NETMASK] = netmask;
+ rtinfo.rti_flags = flags;
+ return rtrequest1_global(req, &rtinfo, NULL, NULL);
+}
+
+#ifdef SMP
+
+struct netmsg_rtq {
+ struct lwkt_msg lmsg;
+ int req;
+ struct rt_addrinfo *rtinfo;
+ rtrequest1_callback_func_t callback;
+ void *arg;
+};
+
+#endif
+
+int
+rtrequest1_global(int req, struct rt_addrinfo *rtinfo,
+ rtrequest1_callback_func_t callback, void *arg)
+{
+ int error;
+#ifdef SMP
+ struct netmsg_rtq msg;
+
+ lwkt_initmsg(&msg.lmsg, &curthread->td_msgport, 0,
+ lwkt_cmd_func(rtrequest1_msghandler), lwkt_cmd_op_none);
+ msg.lmsg.ms_error = -1;
+ msg.req = req;
+ msg.rtinfo = rtinfo;
+ msg.callback = callback;
+ msg.arg = arg;
+ error = lwkt_domsg(rtable_portfn(0), &msg.lmsg);
+#else
+ struct rtentry *rt = NULL;
+
+ error = rtrequest1(req, rtinfo, &rt);
+ if (rt)
+ --rt->rt_refcnt;
+ if (callback)
+ callback(req, error, rtinfo, rt, arg);
+#endif
+ return (error);
+}
+
+/*
+ * Handle a route table request on the current cpu. Since the route table's
+ * are supposed to be identical on each cpu, an error occuring later in the
+ * message chain is considered system-fatal.
+ */
+#ifdef SMP
+
+static int
+rtrequest1_msghandler(struct lwkt_msg *lmsg)
+{
+ struct netmsg_rtq *msg = (void *)lmsg;
+ struct rtentry *rt = NULL;
+ int nextcpu;
+ int error;
+
+ error = rtrequest1(msg->req, msg->rtinfo, &rt);
+ if (rt)
+ --rt->rt_refcnt;
+ if (msg->callback)
+ msg->callback(msg->req, error, msg->rtinfo, rt, msg->arg);
+
+ /*
+ * RTM_DELETE's are propogated even if an error occurs, since a
+ * cloned route might be undergoing deletion and cloned routes
+ * are not necessarily replicated. An overall error is returned
+ * only if no cpus have the route in question.
+ */
+ if (msg->lmsg.ms_error < 0 || error == 0)
+ msg->lmsg.ms_error = error;
+
+ nextcpu = mycpuid + 1;
+ if (error && msg->req != RTM_DELETE) {
+ if (mycpuid != 0) {
+ panic("rtrequest1_msghandler: rtrequest table "
+ "error was not on cpu #0: %p", msg);
+ }
+ lwkt_replymsg(&msg->lmsg, error);
+ } else if (nextcpu < ncpus) {
+ lwkt_forwardmsg(rtable_portfn(nextcpu), &msg->lmsg);
+ } else {
+ lwkt_replymsg(&msg->lmsg, msg->lmsg.ms_error);
+ }
+ return (0);
+}
+
+#endif
+
int
rtrequest1(int req, struct rt_addrinfo *rtinfo, struct rtentry **ret_nrt)
{
/*
* Find the correct routing tree to use for this Address Family
*/
- if ((rnh = rt_tables[dst->sa_family]) == NULL)
+ if ((rnh = rt_tables[mycpuid][dst->sa_family]) == NULL)
gotoerr(EAFNOSUPPORT);
/*
("rnh_deladdr returned flags 0x%x", rn->rn_flags));
rt = (struct rtentry *)rn;
+ /* ref to prevent a deletion race */
+ ++rt->rt_refcnt;
+
/* Free any routes cloned from this one. */
if ((rt->rt_flags & (RTF_CLONING | RTF_PRCLONING)) &&
rt_mask(rt) != NULL) {
KASSERT(rt->rt_refcnt >= 0,
("rtrequest1(DELETE): refcnt %ld", rt->rt_refcnt));
if (ret_nrt != NULL) {
+ /* leave ref intact for return */
*ret_nrt = rt;
- } else if (rt->rt_refcnt == 0) {
- rt->rt_refcnt++; /* refcnt > 0 required for rtfree() */
+ } else {
+ /* deref / attempt to destroy */
rtfree(rt);
}
break;
char *space, *oldspace;
int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
struct rtentry *rt = rt0;
- struct radix_node_head *rnh = rt_tables[dst->sa_family];
+ struct radix_node_head *rnh = rt_tables[mycpuid][dst->sa_family];
/*
* A host route with the destination equal to the gateway
rtinit(struct ifaddr *ifa, int cmd, int flags)
{
struct sockaddr *dst, *deldst, *netmask;
- struct rtentry *rt;
struct mbuf *m = NULL;
struct radix_node_head *rnh;
struct radix_node *rn;
* Look up an rtentry that is in the routing tree and
* contains the correct info.
*/
- if ((rnh = rt_tables[dst->sa_family]) == NULL ||
+ if ((rnh = rt_tables[mycpuid][dst->sa_family]) == NULL ||
(rn = rnh->rnh_lookup((char *)dst,
(char *)netmask, rnh)) == NULL ||
((struct rtentry *)rn)->rt_ifa != ifa ||
rtinfo.rti_info[RTAX_NETMASK] = netmask;
rtinfo.rti_flags = flags | ifa->ifa_flags;
rtinfo.rti_ifa = ifa;
- error = rtrequest1(cmd, &rtinfo, &rt);
- if (error == 0 && rt != NULL) {
- /*
- * notify any listening routing agents of the change
- */
- rt_newaddrmsg(cmd, ifa, error, rt);
+ error = rtrequest1_global(cmd, &rtinfo, rtinit_rtrequest_callback, ifa);
+ if (m != NULL)
+ m_free(m);
+ return (error);
+}
+
+static void
+rtinit_rtrequest_callback(int cmd, int error,
+ struct rt_addrinfo *rtinfo, struct rtentry *rt,
+ void *arg)
+{
+ struct ifaddr *ifa = arg;
+
+ if (error == 0 && rt) {
+ if (mycpuid == 0) {
+ ++rt->rt_refcnt;
+ rt_newaddrmsg(cmd, ifa, error, rt);
+ --rt->rt_refcnt;
+ }
if (cmd == RTM_DELETE) {
- /*
- * If we are deleting, and we found an entry, then
- * it's been removed from the tree.. now throw it away.
- */
if (rt->rt_refcnt == 0) {
- rt->rt_refcnt++; /* make a 1->0 transition */
+ ++rt->rt_refcnt;
rtfree(rt);
}
- } else if (cmd == RTM_ADD) {
- /*
- * We just wanted to add it.. we don't actually
- * need a reference.
- */
- rt->rt_refcnt--;
}
}
- if (m != NULL)
- m_free(m);
- return (error);
}
/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
*
* @(#)route.h 8.4 (Berkeley) 1/9/95
* $FreeBSD: src/sys/net/route.h,v 1.36.2.5 2002/02/01 11:48:01 ru Exp $
- * $DragonFly: src/sys/net/route.h,v 1.14 2005/05/01 04:05:35 hmp Exp $
+ * $DragonFly: src/sys/net/route.h,v 1.15 2006/01/31 19:05:35 dillon Exp $
*/
#ifndef _NET_ROUTE_H_
#define rti_author rti_info[RTAX_AUTHOR]
#define rti_bcastaddr rti_info[RTAX_BRD]
-extern struct radix_node_head *rt_tables[AF_MAX+1];
+extern struct radix_node_head *rt_tables[MAXCPU][AF_MAX+1];
+extern struct lwkt_port *rt_ports[MAXCPU];
struct ifmultiaddr;
struct proc;
return _rtlookup(dst, RTL_REPORTMSG, RTL_DOCLONE);
}
+typedef void (*rtrequest1_callback_func_t)(int, int, struct rt_addrinfo *,
+ struct rtentry *, void *);
+
void rtfree (struct rtentry *);
int rtinit (struct ifaddr *, int, int);
int rtioctl (u_long, caddr_t, struct thread *);
struct sockaddr *, int, struct sockaddr *);
int rtrequest (int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **);
+int rtrequest_global (int, struct sockaddr *,
+ struct sockaddr *, struct sockaddr *, int);
int rtrequest1 (int, struct rt_addrinfo *, struct rtentry **);
+int rtrequest1_global (int, struct rt_addrinfo *, rtrequest1_callback_func_t, void *);
static __inline void
RTFREE(struct rtentry *rt)
--rt->rt_refcnt;
}
+static __inline
+struct lwkt_port *
+rtable_portfn(int cpu)
+{
+ return (rt_ports[cpu]);
+}
+
int in_inithead(void **, int);
#endif
*
* @(#)rtsock.c 8.7 (Berkeley) 10/12/95
* $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $
- * $DragonFly: src/sys/net/rtsock.c,v 1.29 2005/07/15 17:54:47 eirikn Exp $
+ * $DragonFly: src/sys/net/rtsock.c,v 1.30 2006/01/31 19:05:35 dillon Exp $
*/
#include "opt_sctp.h"
return (0);
}
+static void route_output_add_callback(int, int, struct rt_addrinfo *,
+ struct rtentry *, void *);
+static void route_output_delete_callback(int, int, struct rt_addrinfo *,
+ struct rtentry *, void *);
+static void route_output_change_callback(int, int, struct rt_addrinfo *,
+ struct rtentry *, void *);
+static void route_output_lock_callback(int, int, struct rt_addrinfo *,
+ struct rtentry *, void *);
+
/*ARGSUSED*/
static int
route_output(struct mbuf *m, struct socket *so, ...)
{
struct rt_msghdr *rtm = NULL;
- struct rtentry *rt = NULL;
- struct rtentry *saved_nrt = NULL;
+ struct rtentry *rt;
struct radix_node_head *rnh;
- struct ifaddr *ifa = NULL;
struct rawcb *rp = NULL;
struct pr_output_info *oi;
struct rt_addrinfo rtinfo;
switch (rtm->rtm_type) {
case RTM_ADD:
- if (rtinfo.rti_gateway == NULL)
- gotoerr(EINVAL);
- error = rtrequest1(RTM_ADD, &rtinfo, &saved_nrt);
- if (error == 0 && saved_nrt != NULL) {
- rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
- &saved_nrt->rt_rmx);
- saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
- saved_nrt->rt_rmx.rmx_locks |=
- (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
- --saved_nrt->rt_refcnt;
- saved_nrt->rt_genmask = rtinfo.rti_genmask;
+ if (rtinfo.rti_gateway == NULL) {
+ error = EINVAL;
+ } else {
+ error = rtrequest1_global(RTM_ADD, &rtinfo,
+ route_output_add_callback, rtm);
}
break;
case RTM_DELETE:
- error = rtrequest1(RTM_DELETE, &rtinfo, &saved_nrt);
- if (error == 0) {
- if ((rt = saved_nrt))
- rt->rt_refcnt++;
- if (fillrtmsg(&rtm, rt, &rtinfo) != 0)
- gotoerr(ENOBUFS);
- }
+ /*
+ * note: &rtm passed as argument so 'rtm' can be replaced.
+ */
+ error = rtrequest1_global(RTM_DELETE, &rtinfo,
+ route_output_delete_callback, &rtm);
break;
case RTM_GET:
- case RTM_CHANGE:
- case RTM_LOCK:
- if ((rnh = rt_tables[rtinfo.rti_dst->sa_family]) == NULL)
- gotoerr(EAFNOSUPPORT);
+ rnh = rt_tables[mycpuid][rtinfo.rti_dst->sa_family];
+ if (rnh == NULL) {
+ error = EAFNOSUPPORT;
+ break;
+ }
rt = (struct rtentry *)
rnh->rnh_lookup((char *)rtinfo.rti_dst,
(char *)rtinfo.rti_netmask, rnh);
- if (rt == NULL)
- gotoerr(ESRCH);
- rt->rt_refcnt++;
-
- switch(rtm->rtm_type) {
- case RTM_GET:
- if (fillrtmsg(&rtm, rt, &rtinfo) != 0)
- gotoerr(ENOBUFS);
- break;
- case RTM_CHANGE:
- /*
- * new gateway could require new ifaddr, ifp;
- * flags may also be different; ifp may be specified
- * by ll sockaddr when protocol address is ambiguous
- */
- if (((rt->rt_flags & RTF_GATEWAY) &&
- rtinfo.rti_gateway != NULL) ||
- rtinfo.rti_ifpaddr != NULL ||
- (rtinfo.rti_ifaaddr != NULL &&
- sa_equal(rtinfo.rti_ifaaddr,
- rt->rt_ifa->ifa_addr))) {
- error = rt_getifa(&rtinfo);
- if (error != 0)
- gotoerr(error);
- }
- if (rtinfo.rti_gateway != NULL) {
- error = rt_setgate(rt, rt_key(rt),
- rtinfo.rti_gateway);
- if (error != 0)
- gotoerr(error);
- }
- if ((ifa = rtinfo.rti_ifa) != NULL) {
- struct ifaddr *oifa = rt->rt_ifa;
-
- if (oifa != ifa) {
- if (oifa && oifa->ifa_rtrequest)
- oifa->ifa_rtrequest(RTM_DELETE,
- rt, &rtinfo);
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
- rt->rt_ifa = ifa;
- rt->rt_ifp = rtinfo.rti_ifp;
- }
- }
- rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
- &rt->rt_rmx);
- if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
- rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &rtinfo);
- if (rtinfo.rti_genmask != NULL)
- rt->rt_genmask = rtinfo.rti_genmask;
- /*
- * Fall into
- */
- case RTM_LOCK:
- rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
- rt->rt_rmx.rmx_locks |=
- (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+ if (rt == NULL) {
+ error = ESRCH;
break;
}
-
+ rt->rt_refcnt++;
+ if (fillrtmsg(&rtm, rt, &rtinfo) != 0)
+ gotoerr(ENOBUFS);
+ --rt->rt_refcnt;
+ break;
+ case RTM_CHANGE:
+ error = rtrequest1_global(RTM_GET, &rtinfo,
+ route_output_change_callback, rtm);
+ break;
+ case RTM_LOCK:
+ error = rtrequest1_global(RTM_GET, &rtinfo,
+ route_output_lock_callback, rtm);
break;
default:
- gotoerr(EOPNOTSUPP);
+ error = EOPNOTSUPP;
+ break;
}
flush:
else
rtm->rtm_flags |= RTF_DONE;
}
- if (rt != NULL)
- rtfree(rt);
+
/*
* Check to see if we don't want our own messages.
*/
return (error);
}
+static void
+route_output_add_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
+ struct rtentry *rt, void *arg)
+{
+ struct rt_msghdr *rtm = arg;
+
+ if (error == 0 && rt != NULL) {
+ rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
+ &rt->rt_rmx);
+ rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
+ rt->rt_rmx.rmx_locks |=
+ (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+ rt->rt_genmask = rtinfo->rti_genmask;
+ }
+}
+
+static void
+route_output_delete_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
+ struct rtentry *rt, void *arg)
+{
+ struct rt_msghdr **rtm = arg;
+
+ if (error == 0 && rt) {
+ ++rt->rt_refcnt;
+ if (fillrtmsg(rtm, rt, rtinfo) != 0) {
+ error = ENOBUFS;
+ /* XXX no way to return the error */
+ }
+ --rt->rt_refcnt;
+ }
+}
+
+static void
+route_output_change_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
+ struct rtentry *rt, void *arg)
+{
+ struct rt_msghdr *rtm = arg;
+ struct ifaddr *ifa;
+
+ if (error)
+ goto done;
+
+ /*
+ * new gateway could require new ifaddr, ifp;
+ * flags may also be different; ifp may be specified
+ * by ll sockaddr when protocol address is ambiguous
+ */
+ if (((rt->rt_flags & RTF_GATEWAY) && rtinfo->rti_gateway != NULL) ||
+ rtinfo->rti_ifpaddr != NULL || (rtinfo->rti_ifaaddr != NULL &&
+ sa_equal(rtinfo->rti_ifaaddr, rt->rt_ifa->ifa_addr))
+ ) {
+ error = rt_getifa(rtinfo);
+ if (error != 0)
+ goto done;
+ }
+ if (rtinfo->rti_gateway != NULL) {
+ error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway);
+ if (error != 0)
+ goto done;
+ }
+ if ((ifa = rtinfo->rti_ifa) != NULL) {
+ struct ifaddr *oifa = rt->rt_ifa;
+
+ if (oifa != ifa) {
+ if (oifa && oifa->ifa_rtrequest)
+ oifa->ifa_rtrequest(RTM_DELETE, rt, rtinfo);
+ IFAFREE(rt->rt_ifa);
+ IFAREF(ifa);
+ rt->rt_ifa = ifa;
+ rt->rt_ifp = rtinfo->rti_ifp;
+ }
+ }
+ rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
+ if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, rtinfo);
+ if (rtinfo->rti_genmask != NULL)
+ rt->rt_genmask = rtinfo->rti_genmask;
+done:
+ /* XXX no way to return error */
+ ;
+}
+
+static void
+route_output_lock_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
+ struct rtentry *rt, void *arg)
+{
+ struct rt_msghdr *rtm = arg;
+
+ rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
+ rt->rt_rmx.rmx_locks |=
+ (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+}
+
static void
rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
{
u_int namelen = arg2;
struct radix_node_head *rnh;
int i, error = EINVAL;
+ int origcpu;
u_char af;
struct walkarg w;
namelen--;
if (req->newptr)
return (EPERM);
- if (namelen != 3)
+ if (namelen != 3 && namelen != 4)
return (EINVAL);
af = name[0];
bzero(&w, sizeof w);
w.w_arg = name[2];
w.w_req = req;
+ /*
+ * Optional third argument specifies cpu, used primarily for
+ * debugging the route table.
+ */
+ if (namelen == 4) {
+ if (name[3] < 0 || name[3] >= ncpus)
+ return (EINVAL);
+ origcpu = mycpuid;
+ lwkt_migratecpu(name[3]);
+ } else {
+ origcpu = -1;
+ }
crit_enter();
switch (w.w_op) {
-
case NET_RT_DUMP:
case NET_RT_FLAGS:
for (i = 1; i <= AF_MAX; i++)
- if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
+ if ((rnh = rt_tables[mycpuid][i]) &&
+ (af == 0 || af == i) &&
(error = rnh->rnh_walktree(rnh,
sysctl_dumpentry, &w)))
break;
crit_exit();
if (w.w_tmem != NULL)
free(w.w_tmem, M_RTABLE);
+ if (origcpu >= 0)
+ lwkt_migratecpu(origcpu);
return (error);
}
*
* @(#)if_ether.c 8.1 (Berkeley) 6/10/93
* $FreeBSD: src/sys/netinet/if_ether.c,v 1.64.2.23 2003/04/11 07:23:15 fjoe Exp $
- * $DragonFly: src/sys/netinet/if_ether.c,v 1.30 2005/12/21 16:40:25 corecode Exp $
+ * $DragonFly: src/sys/netinet/if_ether.c,v 1.31 2006/01/31 19:05:39 dillon Exp $
*/
/*
u_short la_asked; /* #times we QUERIED following expiration */
};
-static LIST_HEAD(, llinfo_arp) llinfo_arp;
+static LIST_HEAD(, llinfo_arp) llinfo_arp_list[MAXCPU];
static int arp_maxtries = 5;
static int useloopback = 1; /* use loopback interface for local traffic */
static void in_arpinput (struct mbuf *);
#endif
-static struct callout arptimer_ch;
+static struct callout arptimer_ch[MAXCPU];
/*
* Timeout routine. Age arp_tab entries periodically.
struct llinfo_arp *la, *nla;
crit_enter();
- LIST_FOREACH_MUTABLE(la, &llinfo_arp, la_le, nla) {
+ LIST_FOREACH_MUTABLE(la, &llinfo_arp_list[mycpuid], la_le, nla) {
if (la->la_rt->rt_expire && la->la_rt->rt_expire <= time_second)
- arptfree(la); /* might remove la from llinfo_arp! */
+ arptfree(la);
}
- callout_reset(&arptimer_ch, arpt_prune * hz, arptimer, NULL);
+ callout_reset(&arptimer_ch[mycpuid], arpt_prune * hz, arptimer, NULL);
crit_exit();
}
struct llinfo_arp *la = rt->rt_llinfo;
struct sockaddr_dl null_sdl = { sizeof null_sdl, AF_LINK };
- static boolean_t arpinit_done;
+ static boolean_t arpinit_done[MAXCPU];
- if (!arpinit_done) {
- arpinit_done = TRUE;
- callout_init(&arptimer_ch);
- callout_reset(&arptimer_ch, hz, arptimer, NULL);
+ if (!arpinit_done[mycpuid]) {
+ arpinit_done[mycpuid] = TRUE;
+ callout_init(&arptimer_ch[mycpuid]);
+ callout_reset(&arptimer_ch[mycpuid], hz, arptimer, NULL);
}
if (rt->rt_flags & RTF_GATEWAY)
return;
bzero(la, sizeof *la);
la->la_rt = rt;
rt->rt_flags |= RTF_LLINFO;
- LIST_INSERT_HEAD(&llinfo_arp, la, la_le);
+ LIST_INSERT_HEAD(&llinfo_arp_list[mycpuid], la, la_le);
#ifdef INET
/*
&log_arp_wrong_iface, 0,
"log arp packets arriving on the wrong interface");
+#ifdef BRIDGE
+#define BRIDGE_TEST (do_bridge)
+#else
+#define BRIDGE_TEST (0) /* cc will optimise the test away */
+#endif
+
+static void
+arp_update_oncpu(struct mbuf *m, in_addr_t saddr, boolean_t create,
+ boolean_t dologging)
+{
+ struct arphdr *ah = mtod(m, struct arphdr *);
+ struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct llinfo_arp *la;
+ struct sockaddr_dl *sdl;
+ struct rtentry *rt;
+ int cpu = mycpuid;
+
+ la = arplookup(saddr, create, FALSE);
+ if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
+ struct in_addr isaddr = { saddr };
+
+ /* the following is not an error when doing bridging */
+ if (!BRIDGE_TEST && rt->rt_ifp != ifp) {
+ if (dologging && log_arp_wrong_iface && cpu == 0) {
+ log(LOG_ERR,
+ "arp: %s is on %s "
+ "but got reply from %*D on %s\n",
+ inet_ntoa(isaddr),
+ rt->rt_ifp->if_xname,
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ ifp->if_xname);
+ }
+ return;
+ }
+ if (sdl->sdl_alen &&
+ bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
+ if (rt->rt_expire != 0) {
+ if (dologging && cpu == 0) {
+ log(LOG_INFO,
+ "arp: %s moved from %*D to %*D on %s\n",
+ inet_ntoa(isaddr),
+ ifp->if_addrlen, (u_char *)LLADDR(sdl),
+ ":", ifp->if_addrlen,
+ (u_char *)ar_sha(ah), ":",
+ ifp->if_xname);
+ }
+ } else {
+ if (dologging && cpu == 0) {
+ log(LOG_ERR,
+ "arp: %*D attempts to modify permanent entry for %s on %s\n",
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ inet_ntoa(isaddr), ifp->if_xname);
+ }
+ return;
+ }
+ }
+ /*
+ * sanity check for the address length.
+ * XXX this does not work for protocols with variable address
+ * length. -is
+ */
+ if (dologging && sdl->sdl_alen && sdl->sdl_alen != ah->ar_hln &&
+ cpu == 0)
+ {
+ log(LOG_WARNING,
+ "arp from %*D: new addr len %d, was %d",
+ ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
+ ah->ar_hln, sdl->sdl_alen);
+ }
+ if (ifp->if_addrlen != ah->ar_hln) {
+ if (dologging && cpu == 0) {
+ log(LOG_WARNING,
+ "arp from %*D: addr len: new %d, i/f %d (ignored)",
+ ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
+ ah->ar_hln, ifp->if_addrlen);
+ }
+ return;
+ }
+ memcpy(LLADDR(sdl), ar_sha(ah), sdl->sdl_alen = ah->ar_hln);
+ /*
+ * If we receive an arp from a token-ring station over
+ * a token-ring nic then try to save the source
+ * routing info.
+ */
+ if (ifp->if_type == IFT_ISO88025) {
+ struct iso88025_header *th =
+ (struct iso88025_header *)m->m_pkthdr.header;
+ struct iso88025_sockaddr_dl_data *trld =
+ SDL_ISO88025(sdl);
+ int rif_len;
+
+ rif_len = TR_RCF_RIFLEN(th->rcf);
+ if ((th->iso88025_shost[0] & TR_RII) &&
+ (rif_len > 2)) {
+ trld->trld_rcf = th->rcf;
+ trld->trld_rcf ^= htons(TR_RCF_DIR);
+ memcpy(trld->trld_route, th->rd, rif_len - 2);
+ trld->trld_rcf &= ~htons(TR_RCF_BCST_MASK);
+ /*
+ * Set up source routing information for
+ * reply packet (XXX)
+ */
+ m->m_data -= rif_len;
+ m->m_len += rif_len;
+ m->m_pkthdr.len += rif_len;
+ } else {
+ th->iso88025_shost[0] &= ~TR_RII;
+ trld->trld_rcf = 0;
+ }
+ m->m_data -= 8;
+ m->m_len += 8;
+ m->m_pkthdr.len += 8;
+ th->rcf = trld->trld_rcf;
+ }
+ if (rt->rt_expire != 0)
+ rt->rt_expire = time_second + arpt_keep;
+ rt->rt_flags &= ~RTF_REJECT;
+ la->la_asked = 0;
+ la->la_preempt = arp_maxtries;
+
+ /*
+ * This particular cpu might have been holding an mbuf
+ * pending ARP resolution. If so, transmit the mbuf now.
+ */
+ if (la->la_hold != NULL) {
+ m_adj(la->la_hold, sizeof(struct ether_header));
+ lwkt_serialize_enter(ifp->if_serializer);
+ (*ifp->if_output)(ifp, la->la_hold, rt_key(rt), rt);
+ lwkt_serialize_exit(ifp->if_serializer);
+ la->la_hold = NULL;
+ }
+ }
+}
+
+#ifdef SMP
+
+struct netmsg_arp_update {
+ struct lwkt_msg lmsg;
+ struct mbuf *m;
+ in_addr_t saddr;
+ boolean_t create;
+};
+
+static int arp_update_msghandler(struct lwkt_msg *lmsg);
+
+#endif
+
+/*
+ * Called from arpintr() - this routine is run from a single cpu.
+ */
static void
in_arpinput(struct mbuf *m)
{
struct ether_header *eh;
struct arc_header *arh;
struct iso88025_header *th = (struct iso88025_header *)NULL;
- struct iso88025_sockaddr_dl_data *trld;
- struct llinfo_arp *la = NULL;
struct rtentry *rt;
struct ifaddr *ifa;
struct in_ifaddr *ia;
- struct sockaddr_dl *sdl;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
- int op, rif_len;
+#ifdef SMP
+ struct netmsg_arp_update msg;
+#endif
+ int op;
int req_len;
req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr));
op = ntohs(ah->ar_op);
memcpy(&isaddr, ar_spa(ah), sizeof isaddr);
memcpy(&itaddr, ar_tpa(ah), sizeof itaddr);
-#ifdef BRIDGE
-#define BRIDGE_TEST (do_bridge)
-#else
-#define BRIDGE_TEST (0) /* cc will optimise the test away */
-#endif
/*
* For a bridge, we want to check the address irrespective
* of the receive interface. (This will change slightly
itaddr = myaddr;
goto reply;
}
- la = arplookup(isaddr.s_addr, (itaddr.s_addr == myaddr.s_addr), FALSE);
- if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
- /* the following is not an error when doing bridging */
- if (!BRIDGE_TEST && rt->rt_ifp != ifp) {
- if (log_arp_wrong_iface)
- log(LOG_ERR,
- "arp: %s is on %s but got reply from %*D on %s\n",
- inet_ntoa(isaddr),
- rt->rt_ifp->if_xname,
- ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
- ifp->if_xname);
- goto reply;
- }
- if (sdl->sdl_alen &&
- bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
- if (rt->rt_expire)
- log(LOG_INFO,
- "arp: %s moved from %*D to %*D on %s\n",
- inet_ntoa(isaddr),
- ifp->if_addrlen, (u_char *)LLADDR(sdl), ":",
- ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
- ifp->if_xname);
- else {
- log(LOG_ERR,
- "arp: %*D attempts to modify permanent entry for %s on %s\n",
- ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
- inet_ntoa(isaddr), ifp->if_xname);
- goto reply;
- }
- }
- /*
- * sanity check for the address length.
- * XXX this does not work for protocols with variable address
- * length. -is
- */
- if (sdl->sdl_alen &&
- sdl->sdl_alen != ah->ar_hln) {
- log(LOG_WARNING,
- "arp from %*D: new addr len %d, was %d",
- ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
- ah->ar_hln, sdl->sdl_alen);
- }
- if (ifp->if_addrlen != ah->ar_hln) {
- log(LOG_WARNING,
- "arp from %*D: addr len: new %d, i/f %d (ignored)",
- ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
- ah->ar_hln, ifp->if_addrlen);
- goto reply;
- }
- memcpy(LLADDR(sdl), ar_sha(ah), sdl->sdl_alen = ah->ar_hln);
- /*
- * If we receive an arp from a token-ring station over
- * a token-ring nic then try to save the source
- * routing info.
- */
- if (ifp->if_type == IFT_ISO88025) {
- th = (struct iso88025_header *)m->m_pkthdr.header;
- trld = SDL_ISO88025(sdl);
- rif_len = TR_RCF_RIFLEN(th->rcf);
- if ((th->iso88025_shost[0] & TR_RII) &&
- (rif_len > 2)) {
- trld->trld_rcf = th->rcf;
- trld->trld_rcf ^= htons(TR_RCF_DIR);
- memcpy(trld->trld_route, th->rd, rif_len - 2);
- trld->trld_rcf &= ~htons(TR_RCF_BCST_MASK);
- /*
- * Set up source routing information for
- * reply packet (XXX)
- */
- m->m_data -= rif_len;
- m->m_len += rif_len;
- m->m_pkthdr.len += rif_len;
- } else {
- th->iso88025_shost[0] &= ~TR_RII;
- trld->trld_rcf = 0;
- }
- m->m_data -= 8;
- m->m_len += 8;
- m->m_pkthdr.len += 8;
- th->rcf = trld->trld_rcf;
- }
- if (rt->rt_expire)
- rt->rt_expire = time_second + arpt_keep;
- rt->rt_flags &= ~RTF_REJECT;
- la->la_asked = 0;
- la->la_preempt = arp_maxtries;
- if (la->la_hold != NULL) {
- m_adj(la->la_hold, sizeof(struct ether_header));
- lwkt_serialize_enter(ifp->if_serializer);
- (*ifp->if_output)(ifp, la->la_hold, rt_key(rt), rt);
- lwkt_serialize_exit(ifp->if_serializer);
- la->la_hold = NULL;
- }
- }
+#ifdef SMP
+ lwkt_initmsg(&msg.lmsg, &curthread->td_msgport, 0,
+ lwkt_cmd_func(arp_update_msghandler), lwkt_cmd_op_none);
+ msg.m = m;
+ msg.saddr = isaddr.s_addr;
+ msg.create = (itaddr.s_addr == myaddr.s_addr);
+ lwkt_domsg(rtable_portfn(0), &msg.lmsg);
+#endif
+ arp_update_oncpu(m, isaddr.s_addr, (itaddr.s_addr == myaddr.s_addr),
+ TRUE);
reply:
if (op != ARPOP_REQUEST) {
m_freem(m);
memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln);
} else {
+ struct llinfo_arp *la;
+
la = arplookup(itaddr.s_addr, FALSE, SIN_PROXY);
if (la == NULL) {
struct sockaddr_in sin;
printf("arp: proxying for %s\n", inet_ntoa(itaddr));
#endif
} else {
+ struct sockaddr_dl *sdl;
+
rt = la->la_rt;
memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
sdl = SDL(rt->rt_gateway);
lwkt_serialize_exit(ifp->if_serializer);
return;
}
+
+#ifdef SMP
+
+static
+int
+arp_update_msghandler(struct lwkt_msg *lmsg)
+{
+ struct netmsg_arp_update *msg = (struct netmsg_arp_update *)lmsg;
+ int nextcpu;
+
+ arp_update_oncpu(msg->m, msg->saddr, msg->create, FALSE);
+
+ nextcpu = mycpuid + 1;
+ if (nextcpu < ncpus) {
+ lwkt_forwardmsg(rtable_portfn(nextcpu), &msg->lmsg);
+ } else {
+ lwkt_replymsg(&msg->lmsg, 0);
+ }
+ return (0);
+}
+
+#endif
+
#endif
/*
static void
arp_init(void)
{
- LIST_INIT(&llinfo_arp);
+ int cpu;
+
+ for (cpu = 0; cpu < ncpus2; cpu++)
+ LIST_INIT(&llinfo_arp_list[cpu]);
netisr_register(NETISR_ARP, cpu0_portfn, arpintr);
}
*
* @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
* $FreeBSD: src/sys/netinet/in_pcb.c,v 1.59.2.27 2004/01/02 04:06:42 ambrisko Exp $
- * $DragonFly: src/sys/netinet/in_pcb.c,v 1.37 2006/01/14 11:33:50 swildner Exp $
+ * $DragonFly: src/sys/netinet/in_pcb.c,v 1.38 2006/01/31 19:05:40 dillon Exp $
*/
#include "opt_ipsec.h"
rtinfo.rti_flags = rt->rt_flags;
rt_missmsg(RTM_LOSING, &rtinfo, rt->rt_flags, 0);
if (rt->rt_flags & RTF_DYNAMIC)
- rtrequest1(RTM_DELETE, &rtinfo, NULL);
+ rtrequest1_global(RTM_DELETE, &rtinfo, NULL, NULL);
inp->inp_route.ro_rt = NULL;
rtfree(rt);
/*
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/netinet/in_rmx.c,v 1.37.2.3 2002/08/09 14:49:23 ru Exp $
- * $DragonFly: src/sys/netinet/in_rmx.c,v 1.12 2005/06/02 23:52:42 dillon Exp $
+ * $DragonFly: src/sys/netinet/in_rmx.c,v 1.13 2006/01/31 19:05:40 dillon Exp $
*/
/*
#include <sys/socket.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>
+#include <sys/globaldata.h>
#include <sys/thread2.h>
#include <net/if.h>
#define RTPRF_EXPIRING RTF_PROTO3 /* set on routes we manage */
-static struct callout in_rtqtimo_ch;
+static struct callout in_rtqtimo_ch[MAXCPU];
/*
* Do what we need to do when inserting a route.
* and there is a cached route, free it. Otherwise, we may end
* up using the wrong route.
*/
- if (ret != NULL && ipforwarding && ipforward_rt.ro_rt != NULL) {
- RTFREE(ipforward_rt.ro_rt);
- ipforward_rt.ro_rt = NULL;
+ if (ret != NULL && ipforwarding &&
+ ipforward_rt[mycpuid].ro_rt != NULL) {
+ RTFREE(ipforward_rt[mycpuid].ro_rt);
+ ipforward_rt[mycpuid].ro_rt = NULL;
}
return ret;
atv.tv_usec = 0;
atv.tv_sec = arg.nextstop - time_second;
- callout_reset(&in_rtqtimo_ch, tvtohz_high(&atv), in_rtqtimo, rock);
+ callout_reset(&in_rtqtimo_ch[mycpuid], tvtohz_high(&atv), in_rtqtimo,
+ rock);
}
void
in_rtqdrain(void)
{
- struct radix_node_head *rnh = rt_tables[AF_INET];
+ struct radix_node_head *rnh = rt_tables[mycpuid][AF_INET];
struct rtqk_arg arg;
arg.found = arg.killed = 0;
if (!rn_inithead(head, off))
return 0;
- if (head != (void **)&rt_tables[AF_INET]) /* BOGUS! */
+ if (head != (void **)&rt_tables[mycpuid][AF_INET]) /* BOGUS! */
return 1; /* only do this for the real routing table */
rnh = *head;
rnh->rnh_addaddr = in_addroute;
rnh->rnh_matchaddr = in_matchroute;
rnh->rnh_close = in_closeroute;
- callout_init(&in_rtqtimo_ch);
+ callout_init(&in_rtqtimo_ch[mycpuid]);
in_rtqtimo(rnh); /* kick off timeout first time */
return 1;
}
if (ifa->ifa_addr->sa_family != AF_INET)
return 1;
- arg.rnh = rnh = rt_tables[AF_INET];
+ arg.rnh = rnh = rt_tables[mycpuid][AF_INET];
arg.ifa = ifa;
arg.del = delete;
rnh->rnh_walktree(rnh, in_ifadownkill, &arg);
*
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
* $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.52 2003/03/07 07:01:28 silby Exp $
- * $DragonFly: src/sys/netinet/ip_input.c,v 1.60 2005/10/28 15:56:47 liamfoy Exp $
+ * $DragonFly: src/sys/netinet/ip_input.c,v 1.61 2006/01/31 19:05:40 dillon Exp $
*/
#define _IP_VHL
* the most recently used route ? it is cleared in in_addroute()
* when a new route is successfully created.
*/
-struct route ipforward_rt;
+struct route ipforward_rt[MAXCPU];
/* Do transport protocol processing. */
static void
== NULL)
ia = (INA)ifa_ifwithnet((SA)&ipaddr);
} else
- ia = ip_rtaddr(ipaddr.sin_addr, &ipforward_rt);
+ ia = ip_rtaddr(ipaddr.sin_addr,
+ &ipforward_rt[mycpuid]);
if (ia == NULL) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_SRCFAIL;
* use the incoming interface (should be same).
*/
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == NULL &&
- (ia = ip_rtaddr(ipaddr.sin_addr, &ipforward_rt))
+ (ia = ip_rtaddr(ipaddr.sin_addr,
+ &ipforward_rt[mycpuid]))
== NULL) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_HOST;
n_long dest;
struct in_addr pkt_dst;
struct m_hdr tag;
+ struct route *cache_rt = &ipforward_rt[mycpuid];
dest = INADDR_ANY;
/*
return;
}
- ipforward_rtaddr = (struct sockaddr_in *) &ipforward_rt.ro_dst;
- if (ipforward_rt.ro_rt == NULL ||
+ ipforward_rtaddr = (struct sockaddr_in *) &cache_rt->ro_dst;
+ if (cache_rt->ro_rt == NULL ||
ipforward_rtaddr->sin_addr.s_addr != pkt_dst.s_addr) {
- if (ipforward_rt.ro_rt != NULL) {
- RTFREE(ipforward_rt.ro_rt);
- ipforward_rt.ro_rt = NULL;
+ if (cache_rt->ro_rt != NULL) {
+ RTFREE(cache_rt->ro_rt);
+ cache_rt->ro_rt = NULL;
}
ipforward_rtaddr->sin_family = AF_INET;
ipforward_rtaddr->sin_len = sizeof(struct sockaddr_in);
ipforward_rtaddr->sin_addr = pkt_dst;
- rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
- if (ipforward_rt.ro_rt == NULL) {
+ rtalloc_ign(cache_rt, RTF_PRCLONING);
+ if (cache_rt->ro_rt == NULL) {
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
return;
}
}
- rt = ipforward_rt.ro_rt;
+ rt = cache_rt->ro_rt;
/*
* Save the IP header and at most 8 bytes of the payload,
m = (struct mbuf *)&tag;
}
- error = ip_output(m, NULL, &ipforward_rt, IP_FORWARDING, NULL, NULL);
+ error = ip_output(m, NULL, cache_rt, IP_FORWARDING, NULL,
+ NULL);
if (error == 0) {
ipstat.ips_forward++;
if (type == 0) {
if (mcopy) {
- ipflow_create(&ipforward_rt, mcopy);
+ ipflow_create(cache_rt, mcopy);
m_freem(mcopy);
}
return; /* most common case */
* tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
* XXX quickhack!!!
*/
- if (ipforward_rt.ro_rt != NULL) {
+ if (cache_rt->ro_rt != NULL) {
struct secpolicy *sp = NULL;
int ipsecerror;
int ipsechdr;
&ipsecerror);
if (sp == NULL)
- destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
+ destmtu = cache_rt->ro_rt->rt_ifp->if_mtu;
else {
/* count IPsec header size */
ipsechdr = ipsec4_hdrsiz(mcopy,
* tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
* XXX quickhack!!!
*/
- if (ipforward_rt.ro_rt != NULL) {
+ if (cache_rt->ro_rt != NULL) {
struct secpolicy *sp = NULL;
int ipsecerror;
int ipsechdr;
&ipsecerror);
if (sp == NULL)
- destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
+ destmtu = cache_rt->ro_rt->rt_ifp->if_mtu;
else {
/* count IPsec header size */
ipsechdr = ipsec4_hdrsiz(mcopy,
}
}
#else /* !IPSEC && !FAST_IPSEC */
- if (ipforward_rt.ro_rt != NULL)
- destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
+ if (cache_rt->ro_rt != NULL)
+ destmtu = cache_rt->ro_rt->rt_ifp->if_mtu;
#endif /*IPSEC*/
ipstat.ips_cantfrag++;
break;
*
* @(#)ip_var.h 8.2 (Berkeley) 1/9/95
* $FreeBSD: src/sys/netinet/ip_var.h,v 1.50.2.13 2003/08/24 08:24:38 hsu Exp $
- * $DragonFly: src/sys/netinet/ip_var.h,v 1.17 2005/08/15 16:46:21 dillon Exp $
+ * $DragonFly: src/sys/netinet/ip_var.h,v 1.18 2006/01/31 19:05:40 dillon Exp $
*/
#ifndef _NETINET_IP_VAR_H_
extern u_short ip_id; /* ip packet ctr, for ids */
extern int ip_defttl; /* default IP ttl */
extern int ipforwarding; /* ip forwarding */
-extern struct route ipforward_rt; /* ip forwarding cached route */
+extern struct route ipforward_rt[]; /* ip forwarding cached route */
extern u_char ip_protox[];
-extern struct socket *ip_rsvpd; /* reservation protocol daemon */
-extern struct socket *ip_mrouter; /* multicast routing daemon */
+extern struct socket *ip_rsvpd; /* reservation protocol daemon */
+extern struct socket *ip_mrouter; /* multicast routing daemon */
extern int (*legal_vif_num)(int);
extern u_long (*ip_mcast_src)(int);
extern int rsvp_on;
/* $FreeBSD: src/sys/netinet6/in6.c,v 1.7.2.9 2002/04/28 05:40:26 suz Exp $ */
-/* $DragonFly: src/sys/netinet6/in6.c,v 1.17 2006/01/14 11:44:25 swildner Exp $ */
+/* $DragonFly: src/sys/netinet6/in6.c,v 1.18 2006/01/31 19:05:42 dillon Exp $ */
/* $KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $ */
/*
static int in6_ifinit (struct ifnet *, struct in6_ifaddr *,
struct sockaddr_in6 *, int);
static void in6_unlink_ifa (struct in6_ifaddr *, struct ifnet *);
+static void in6_ifloop_request_callback(int, int, struct rt_addrinfo *, struct rtentry *, void *);
struct in6_multihead in6_multihead; /* XXX BSS initialization */
in6_ifloop_request(int cmd, struct ifaddr *ifa)
{
struct sockaddr_in6 all1_sa;
- struct rtentry *nrt = NULL;
- int e;
+ struct rt_addrinfo rtinfo;
+ int error;
bzero(&all1_sa, sizeof(all1_sa));
all1_sa.sin6_family = AF_INET6;
all1_sa.sin6_len = sizeof(struct sockaddr_in6);
all1_sa.sin6_addr = in6mask128;
-
+
/*
* We specify the address itself as the gateway, and set the
* RTF_LLINFO flag, so that the corresponding host route would have
* (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
* which changes the outgoing interface to the loopback interface.
*/
- e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
- (struct sockaddr *)&all1_sa,
- RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
- if (e != 0) {
+ bzero(&rtinfo, sizeof(struct rt_addrinfo));
+ rtinfo.rti_info[RTAX_DST] = ifa->ifa_addr;
+ rtinfo.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ rtinfo.rti_info[RTAX_NETMASK] = (struct sockaddr *)&all1_sa;
+ rtinfo.rti_flags = RTF_UP|RTF_HOST|RTF_LLINFO;
+
+ error = rtrequest1_global(cmd, &rtinfo,
+ in6_ifloop_request_callback, ifa);
+ if (error != 0) {
log(LOG_ERR, "in6_ifloop_request: "
"%s operation failed for %s (errno=%d)\n",
cmd == RTM_ADD ? "ADD" : "DELETE",
ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
- e);
+ error);
}
+}
+
+static void
+in6_ifloop_request_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
+ struct rtentry *rt, void *arg)
+{
+ struct ifaddr *ifa = arg;
+
+ if (error)
+ goto done;
/*
* Make sure rt_ifa be equal to IFA, the second argument of the
* ip6_input, we assume that the rt_ifa points to the address instead
* of the loopback address.
*/
- if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
- IFAFREE(nrt->rt_ifa);
+ if (cmd == RTM_ADD && rt && ifa != rt->rt_ifa) {
+ ++rt->rt_refcnt;
+ IFAFREE(rt->rt_ifa);
IFAREF(ifa);
- nrt->rt_ifa = ifa;
+ rt->rt_ifa = ifa;
+ --rt->rt_refcnt;
}
/*
* we end up reporting twice in such a case. Should we rather
* omit the second report?
*/
- if (nrt) {
- rt_newaddrmsg(cmd, ifa, e, nrt);
+ if (rt) {
+ if (mycpuid == 0)
+ rt_newaddrmsg(cmd, ifa, error, rt);
if (cmd == RTM_DELETE) {
- if (nrt->rt_refcnt <= 0) {
- /* XXX: we should free the entry ourselves. */
- nrt->rt_refcnt++;
- rtfree(nrt);
+ if (rt->rt_refcnt == 0) {
+ ++rt->rt_refcnt;
+ rtfree(rt);
}
- } else {
- /* the cmd must be RTM_ADD here */
- nrt->rt_refcnt--;
}
}
+done:
+ /* no way to return any new error */
+ ;
}
/*
IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
if (in6m == NULL) {
- rtrequest(RTM_ADD,
+ rtrequest_global(RTM_ADD,
(struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&mltmask,
- RTF_UP|RTF_CLONING, /* xxx */
- (struct rtentry **)0);
+ RTF_UP|RTF_CLONING); /* xxx */
in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
if (error != 0) {
log(LOG_WARNING,
IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
if (in6m == NULL && ia_loop != NULL) {
- rtrequest(RTM_ADD,
+ rtrequest_global(RTM_ADD,
(struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia_loop->ia_addr,
(struct sockaddr *)&mltmask,
- RTF_UP,
- (struct rtentry **)0);
+ RTF_UP);
in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
if (error != 0) {
log(LOG_WARNING, "in6_update_ifa: "
/* $FreeBSD: src/sys/netinet6/in6_pcb.c,v 1.10.2.9 2003/01/24 05:11:35 sam Exp $ */
-/* $DragonFly: src/sys/netinet6/in6_pcb.c,v 1.27 2005/06/03 19:56:08 eirikn Exp $ */
+/* $DragonFly: src/sys/netinet6/in6_pcb.c,v 1.28 2006/01/31 19:05:42 dillon Exp $ */
/* $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $ */
/*
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
if (rt->rt_flags & RTF_DYNAMIC)
- rtrequest1(RTM_DELETE, &info, NULL);
+ rtrequest1_global(RTM_DELETE, &info, NULL, NULL);
in6p->in6p_route.ro_rt = NULL;
rtfree(rt);
/*
/* $FreeBSD: src/sys/netinet6/in6_rmx.c,v 1.1.2.4 2004/10/06 02:35:17 suz Exp $ */
-/* $DragonFly: src/sys/netinet6/in6_rmx.c,v 1.13 2005/06/03 19:56:08 eirikn Exp $ */
+/* $DragonFly: src/sys/netinet6/in6_rmx.c,v 1.14 2006/01/31 19:05:42 dillon Exp $ */
/* $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $ */
/*
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>
+#include <sys/globaldata.h>
#include <sys/thread2.h>
#include <net/if.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
-static struct callout in6_rtqtimo_ch;
-static struct callout in6_mtutimo_ch;
+static struct callout in6_rtqtimo_ch[MAXCPU];
+static struct callout in6_mtutimo_ch[MAXCPU];
extern int in6_inithead (void **head, int off);
atv.tv_usec = 0;
atv.tv_sec = arg.nextstop;
- callout_reset(&in6_rtqtimo_ch, tvtohz_high(&atv), in6_rtqtimo, rock);
+ callout_reset(&in6_rtqtimo_ch[mycpuid], tvtohz_high(&atv), in6_rtqtimo,
+ rock);
}
/*
printf("invalid mtu expiration time on routing table\n");
arg.nextstop = time_second + 30; /* last resort */
}
- callout_reset(&in6_mtutimo_ch, tvtohz_high(&atv), in6_mtutimo, rock);
+ callout_reset(&in6_mtutimo_ch[mycpuid], tvtohz_high(&atv), in6_mtutimo,
+ rock);
}
#if 0
void
in6_rtqdrain(void)
{
- struct radix_node_head *rnh = rt_tables[AF_INET6];
+ struct radix_node_head *rnh = rt_tables[mycpuid][AF_INET6];
struct rtqk_arg arg;
arg.found = arg.killed = 0;
if (!rn_inithead(head, off))
return 0;
- if (head != (void **)&rt_tables[AF_INET6]) /* BOGUS! */
+ if (head != (void **)&rt_tables[mycpuid][AF_INET6]) /* BOGUS! */
return 1; /* only do this for the real routing table */
rnh = *head;
rnh->rnh_addaddr = in6_addroute;
rnh->rnh_matchaddr = in6_matchroute;
rnh->rnh_close = in6_clsroute;
- callout_init(&in6_mtutimo_ch);
- callout_init(&in6_rtqtimo_ch);
+ callout_init(&in6_mtutimo_ch[mycpuid]);
+ callout_init(&in6_rtqtimo_ch[mycpuid]);
in6_rtqtimo(rnh); /* kick off timeout first time */
in6_mtutimo(rnh); /* kick off timeout first time */
return 1;
/* $FreeBSD: src/sys/netinet6/nd6_rtr.c,v 1.2.2.5 2003/04/05 10:28:53 ume Exp $ */
-/* $DragonFly: src/sys/netinet6/nd6_rtr.c,v 1.11 2006/01/14 11:44:25 swildner Exp $ */
+/* $DragonFly: src/sys/netinet6/nd6_rtr.c,v 1.12 2006/01/31 19:05:42 dillon Exp $ */
/* $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $ */
/*
#include <sys/errno.h>
#include <sys/syslog.h>
#include <sys/queue.h>
+#include <sys/globaldata.h>
#include <sys/thread2.h>
#include <net/if.h>
void
rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
{
- struct radix_node_head *rnh = rt_tables[AF_INET6];
+ struct radix_node_head *rnh = rt_tables[mycpuid][AF_INET6];
crit_enter();
*
* Machine independant code should not directly include this file.
*
- * $DragonFly: src/sys/platform/pc32/include/thread.h,v 1.13 2005/06/16 21:12:46 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/include/thread.h,v 1.14 2006/01/31 19:05:30 dillon Exp $
*/
#ifndef _MACHINE_THREAD_H_
}
#define mycpu _get_mycpu()
-#define mycpuid _get_mycpu()->gd_cpuid
+
+#ifdef SMP
+#define mycpuid (_get_mycpu()->gd_cpuid)
+#else
+#define mycpuid 0
+#endif
/*
* note: curthread is never NULL, but curproc can be. Also note that
* Types which must already be defined when this header is included by
* userland: struct md_thread
*
- * $DragonFly: src/sys/sys/thread.h,v 1.76 2005/12/02 22:02:20 dillon Exp $
+ * $DragonFly: src/sys/sys/thread.h,v 1.77 2006/01/31 19:05:44 dillon Exp $
*/
#ifndef _SYS_THREAD_H_
extern void lwkt_setpri_self(int pri);
extern int lwkt_checkpri_self(void);
extern void lwkt_setcpu_self(struct globaldata *rgd);
+extern void lwkt_migratecpu(int cpuid);
#ifdef SMP
* nfs/krpc_subr.c
* $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
* $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.9 2003/04/24 16:51:08 ambrisko Exp $
- * $DragonFly: src/sys/vfs/nfs/bootp_subr.c,v 1.12 2005/10/27 14:03:56 sephe Exp $
+ * $DragonFly: src/sys/vfs/nfs/bootp_subr.c,v 1.13 2006/01/31 19:05:45 dillon Exp $
*/
#include "opt_bootp.h"
if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
clear_sinaddr(&defdst);
clear_sinaddr(&defmask);
- error = rtrequest(RTM_ADD,
- (struct sockaddr *) &defdst,
- (struct sockaddr *) gw,
- (struct sockaddr *) &defmask,
- (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
+ error = rtrequest_global(RTM_ADD, (struct sockaddr *) &defdst,
+ (struct sockaddr *) gw,
+ (struct sockaddr *) &defmask,
+ (RTF_UP | RTF_GATEWAY | RTF_STATIC));
if (error != 0) {
printf("bootpc_adjust_interface: "
"add net route, error=%d\n", error);
*
* @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
* $FreeBSD: src/sys/nfs/nfs_vfsops.c,v 1.91.2.7 2003/01/27 20:04:08 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.33 2005/09/17 07:43:12 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.34 2006/01/31 19:05:45 dillon Exp $
*/
#include "opt_bootp.h"
sin.sin_len = sizeof(sin);
printf("nfs_mountroot: gateway %s\n",
inet_ntoa(nd->mygateway.sin_addr));
- error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
- (struct sockaddr *)&nd->mygateway,
- (struct sockaddr *)&mask,
- RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
+ error = rtrequest_global(RTM_ADD, (struct sockaddr *)&sin,
+ (struct sockaddr *)&nd->mygateway,
+ (struct sockaddr *)&mask,
+ RTF_UP | RTF_GATEWAY);
if (error)
printf("nfs_mountroot: unable to set gateway, error %d, continuing anyway\n", error);
}