route: Routes should only be accessed from the first netisr_ncpus netisrs.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 8 Aug 2017 09:18:29 +0000 (17:18 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 11 Aug 2017 09:44:16 +0000 (17:44 +0800)
Replicate routes to the first netisr_ncpus CPUs, instead of all CPUs.

17 files changed:
sys/kern/uipc_msg.c
sys/net/if.c
sys/net/netisr2.h
sys/net/radix.c
sys/net/route.c
sys/net/route.h
sys/net/rtsock.c
sys/netinet/if_ether.c
sys/netinet/in_rmx.c
sys/netinet/ip_demux.c
sys/netinet/ip_icmp.c
sys/netinet/ip_input.c
sys/netinet/tcp_subr.c
sys/netinet/udp_usrreq.c
sys/netinet6/in6_rmx.c
sys/sys/param.h
usr.bin/netstat/main.c

index 713206d..a05e681 100644 (file)
@@ -603,7 +603,7 @@ so_pr_ctlinput_direct(struct protosw *pr, int cmd, struct sockaddr *arg,
        port = so_pr_ctlport(pr, cmd, arg, extra, &cpuid);
        if (port == NULL)
                return;
-       if (cpuid != ncpus && cpuid != mycpuid)
+       if (cpuid != netisr_ncpus && cpuid != mycpuid)
                return;
 
        func = pr->pr_ctlinput;
index a4e767a..bf4908c 100644 (file)
@@ -526,11 +526,8 @@ if_attach(struct ifnet *ifp, lwkt_serialize_t serializer)
        }
 
        /*
-        * XXX -
-        * The old code would work if the interface passed a pre-existing
-        * chain of ifaddrs to this code.  We don't trust our callers to
-        * properly initialize the tailq, however, so we no longer allow
-        * this unlikely case.
+        * Make if_addrhead available on all CPUs, since they
+        * could be accessed by any threads.
         */
        ifp->if_addrheads = kmalloc(ncpus * sizeof(struct ifaddrhead),
                                    M_IFADDR, M_WAITOK | M_ZERO);
@@ -568,6 +565,11 @@ if_attach(struct ifnet *ifp, lwkt_serialize_t serializer)
                sdl->sdl_data[--namelen] = 0xff;
        ifa_iflink(ifa, ifp, 0 /* Insert head */);
 
+       /*
+        * Make if_data available on all CPUs, since they could
+        * be updated by hardware interrupt routing, which could
+        * be bound to any CPU.
+        */
        ifp->if_data_pcpu = kmalloc_cachealign(
            ncpus * sizeof(struct ifdata_pcpu), M_DEVBUF, M_WAITOK | M_ZERO);
 
@@ -610,12 +612,22 @@ if_attach(struct ifnet *ifp, lwkt_serialize_t serializer)
                if (ifp->if_serializer != NULL)
                        ifsq_set_hw_serialize(ifsq, ifp->if_serializer);
 
+               /* XXX: netisr_ncpus */
                ifsq->ifsq_stage =
                    kmalloc_cachealign(ncpus * sizeof(struct ifsubq_stage),
                    M_DEVBUF, M_WAITOK | M_ZERO);
                for (i = 0; i < ncpus; ++i)
                        ifsq->ifsq_stage[i].stg_subq = ifsq;
 
+               /*
+                * Allocate one if_start message for each CPU, since
+                * the hardware TX ring could be assigned to any CPU.
+                *
+                * NOTE:
+                * If the hardware TX ring polling CPU and the hardware
+                * TX ring interrupt CPU are same, one if_start message
+                * should be enough.
+                */
                ifsq->ifsq_ifstart_nmsg =
                    kmalloc(ncpus * sizeof(struct netmsg_base),
                    M_LWKTMSG, M_WAITOK);
@@ -870,6 +882,7 @@ ifq_stage_detach(struct ifaltq *ifq)
            ifq_stage_detach_handler);
        base.lmsg.u.ms_resultp = ifq;
 
+       /* XXX netisr_ncpus */
        for (cpu = 0; cpu < ncpus; ++cpu)
                lwkt_domsg(netisr_cpuport(cpu), &base.lmsg, 0);
 }
@@ -883,9 +896,11 @@ static void
 if_rtdel_dispatch(netmsg_t msg)
 {
        struct netmsg_if_rtdel *rmsg = (void *)msg;
-       int i, nextcpu, cpu;
+       int i, cpu;
 
        cpu = mycpuid;
+       ASSERT_NETISR_NCPUS(cpu);
+
        for (i = 1; i <= AF_MAX; i++) {
                struct radix_node_head  *rnh;
 
@@ -893,12 +908,7 @@ if_rtdel_dispatch(netmsg_t msg)
                        continue;
                rnh->rnh_walktree(rnh, if_rtdel, rmsg->ifp);
        }
-
-       nextcpu = cpu + 1;
-       if (nextcpu < ncpus)
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &rmsg->base.lmsg);
-       else
-               lwkt_replymsg(&rmsg->base.lmsg, 0);
+       netisr_forwardmsg(&msg->base, cpu + 1);
 }
 
 /*
@@ -1021,7 +1031,7 @@ if_detach(struct ifnet *ifp)
        netmsg_init(&msg.base, NULL, &curthread->td_msgport, MSGF_PRIORITY,
            if_rtdel_dispatch);
        msg.ifp = ifp;
-       rt_domsg_global(&msg.base);
+       netisr_domsg_global(&msg.base);
 
        SLIST_FOREACH(dp, &domains, dom_next)
                if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
@@ -1553,6 +1563,8 @@ if_unroute_dispatch(netmsg_t nmsg)
        int flag = msg->flag, fam = msg->fam;
        struct ifaddr_container *ifac;
 
+       ASSERT_NETISR0;
+
        ifp->if_flags &= ~flag;
        getmicrotime(&ifp->if_lastchange);
        /*
@@ -1601,6 +1613,8 @@ if_route_dispatch(netmsg_t nmsg)
        int flag = msg->flag, fam = msg->fam;
        struct ifaddr_container *ifac;
 
+       ASSERT_NETISR0;
+
        ifq_purge_all(&ifp->if_snd);
        ifp->if_flags |= flag;
        getmicrotime(&ifp->if_lastchange);
@@ -3105,6 +3119,11 @@ ifa_create(int size)
        KASSERT(size >= sizeof(*ifa), ("ifaddr size too small"));
 
        ifa = kmalloc(size, M_IFADDR, M_INTWAIT | M_ZERO);
+
+       /*
+        * Make ifa_container availabel on all CPUs, since they
+        * could be accessed by any threads.
+        */
        ifa->ifa_containers =
            kmalloc_cachealign(ncpus * sizeof(struct ifaddr_container),
                M_IFADDR, M_INTWAIT | M_ZERO);
@@ -3296,6 +3315,7 @@ ifnetinit(void *dummy __unused)
 {
        int i;
 
+       /* XXX netisr_ncpus */
        for (i = 0; i < ncpus; ++i)
                TAILQ_INIT(&ifsubq_stage_heads[i].stg_head);
        netisr_register_rollup(if_start_rollup, NETISR_ROLLUP_PRIO_IFSTART);
index c2ca7db..2763f47 100644 (file)
@@ -161,6 +161,14 @@ netisr_domsg(struct netmsg_base *nm, int cpu)
        return (netisr_domsg_port(nm, netisr_cpuport(cpu)));
 }
 
+static __inline int
+netisr_domsg_global(struct netmsg_base *nm)
+{
+
+       /* Start from netisr0. */
+       return (netisr_domsg(nm, 0));
+}
+
 static __inline void
 netisr_sendmsg(struct netmsg_base *nm, int cpu)
 {
@@ -200,14 +208,25 @@ netisr_forwardmsg_all(struct netmsg_base *nm, int next_cpu)
  * To netisr_ncpus.
  */
 static __inline void
-netisr_forwardmsg(struct netmsg_base *nm, int next_cpu)
+netisr_forwardmsg_error(struct netmsg_base *nm, int next_cpu,
+    int error)
 {
 
        KKASSERT(next_cpu > mycpuid && next_cpu <= netisr_ncpus);
        if (next_cpu < netisr_ncpus)
                lwkt_forwardmsg(netisr_cpuport(next_cpu), &nm->lmsg);
        else
-               netisr_replymsg(nm, 0);
+               netisr_replymsg(nm, error);
+}
+
+/*
+ * To netisr_ncpus.
+ */
+static __inline void
+netisr_forwardmsg(struct netmsg_base *nm, int next_cpu)
+{
+
+       netisr_forwardmsg_error(nm, next_cpu, 0);
 }
 
 #endif /* _NET_NETISR2_H_ */
index e72338a..5236d9e 100644 (file)
 #include <stdlib.h>
 #endif
 #include <sys/syslog.h>
+
 #include <net/radix.h>
+#include <net/netmsg2.h>
+#include <net/netisr2.h>
 
 /*
  * The arguments to the radix functions are really counted byte arrays with
@@ -1074,10 +1077,22 @@ rn_inithead(void **head, struct radix_node_head *maskhead, int off)
        return (1);
 }
 
+static void
+rn_init_handler(netmsg_t msg)
+{
+       int cpu = mycpuid;
+
+       ASSERT_NETISR_NCPUS(cpu);
+       if (rn_inithead((void **)&mask_rnheads[cpu], NULL, 0) == 0)
+               panic("rn_init 2");
+
+       netisr_forwardmsg(&msg->base, cpu + 1);
+}
+
 void
 rn_init(void)
 {
-       int cpu;
+       struct netmsg_base msg;
 #ifdef _KERNEL
        struct domain *dom;
 
@@ -1088,15 +1103,15 @@ rn_init(void)
                }
        }
 #endif
-       for (cpu = 0; cpu < ncpus; ++cpu) {
-               if (rn_inithead((void **)&mask_rnheads[cpu], NULL, 0) == 0)
-                       panic("rn_init 2");
-       }
+       netmsg_init(&msg, NULL, &curthread->td_msgport, 0, rn_init_handler);
+       netisr_domsg_global(&msg);
 }
 
 struct radix_node_head *
 rn_cpumaskhead(int cpu)
 {
+
+       ASSERT_NETISR_NCPUS(cpu);
        KKASSERT(mask_rnheads[cpu] != NULL);
        return mask_rnheads[cpu];
 }
index 56e35a1..ce9a5bc 100644 (file)
@@ -118,10 +118,6 @@ SYSCTL_INT(_net_route, OID_AUTO, route_debug, CTLFLAG_RW,
            &route_debug, 0, "");
 #endif
 
-int route_assert_owner_access = 1;
-SYSCTL_INT(_net_route, OID_AUTO, assert_owner_access, CTLFLAG_RW,
-           &route_assert_owner_access, 0, "");
-
 u_long route_kmalloc_limit = 0;
 TUNABLE_ULONG("net.route.kmalloc_limit", &route_kmalloc_limit);
 
@@ -135,32 +131,31 @@ route_init(void)
 {
        int cpu;
 
-       for (cpu = 0; cpu < ncpus; ++cpu)
+       if (route_kmalloc_limit)
+               kmalloc_raise_limit(M_RTABLE, route_kmalloc_limit);
+
+       for (cpu = 0; cpu < netisr_ncpus; ++cpu)
                bzero(&rtstatistics_percpu[cpu], sizeof(struct rtstatistics));
        rn_init();      /* initialize all zeroes, all ones, mask table */
        rtable_init();  /* call dom_rtattach() on each cpu */
-
-       if (route_kmalloc_limit)
-               kmalloc_raise_limit(M_RTABLE, route_kmalloc_limit);
 }
 
 static void
 rtable_init_oncpu(netmsg_t msg)
 {
        struct domain *dom;
-       int nextcpu = mycpuid + 1;
+       int cpu = mycpuid;
+
+       ASSERT_NETISR_NCPUS(cpu);
 
        SLIST_FOREACH(dom, &domains, dom_next) {
                if (dom->dom_rtattach) {
                        dom->dom_rtattach(
-                               (void **)&rt_tables[mycpuid][dom->dom_family],
+                               (void **)&rt_tables[cpu][dom->dom_family],
                                dom->dom_rtoffset);
                }
        }
-       if (nextcpu < ncpus)
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &msg->lmsg);
-       else
-               lwkt_replymsg(&msg->lmsg, 0);
+       netisr_forwardmsg(&msg->base, cpu + 1);
 }
 
 static void
@@ -169,7 +164,7 @@ rtable_init(void)
        struct netmsg_base msg;
 
        netmsg_init(&msg, NULL, &curthread->td_msgport, 0, rtable_init_oncpu);
-       rt_domsg_global(&msg);
+       netisr_domsg_global(&msg);
 }
 
 /*
@@ -180,7 +175,7 @@ sysctl_rtstatistics(SYSCTL_HANDLER_ARGS)
 {
        int cpu, error = 0;
 
-       for (cpu = 0; cpu < ncpus; ++cpu) {
+       for (cpu = 0; cpu < netisr_ncpus; ++cpu) {
                if ((error = SYSCTL_OUT(req, &rtstatistics_percpu[cpu],
                                        sizeof(struct rtstatistics))))
                                break;
@@ -242,6 +237,8 @@ _rtlookup(struct sockaddr *dst, boolean_t generate_report, u_long ignore)
        struct radix_node_head *rnh = rt_tables[mycpuid][dst->sa_family];
        struct rtentry *rt;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        if (rnh == NULL)
                goto unreach;
 
@@ -294,16 +291,8 @@ unreach:
 void
 rtfree(struct rtentry *rt)
 {
-       if (rt->rt_cpuid == mycpuid)
-               rtfree_oncpu(rt);
-       else
-               rtfree_remote(rt);
-}
 
-void
-rtfree_oncpu(struct rtentry *rt)
-{
-       KKASSERT(rt->rt_cpuid == mycpuid);
+       ASSERT_NETISR_NCPUS(rt->rt_cpuid);
        KASSERT(rt->rt_refcnt > 0, ("rtfree: rt_refcnt %ld", rt->rt_refcnt));
 
        --rt->rt_refcnt;
@@ -330,7 +319,7 @@ rtfree_async_dispatch(netmsg_t msg)
 {
        struct rtentry *rt = msg->lmsg.u.ms_resultp;
 
-       rtfree_oncpu(rt);
+       rtfree(rt);
        netisr_replymsg(&msg->base, 0);
 }
 
@@ -339,8 +328,8 @@ rtfree_async(struct rtentry *rt)
 {
        struct netmsg_base *msg;
 
-       if (IN_NETISR(rt->rt_cpuid)) {
-               rtfree_oncpu(rt);
+       if (IN_NETISR_NCPUS(rt->rt_cpuid)) {
+               rtfree(rt);
                return;
        }
 
@@ -354,23 +343,6 @@ rtfree_async(struct rtentry *rt)
        netisr_sendmsg(msg, rt->rt_cpuid);
 }
 
-void
-rtfree_remote(struct rtentry *rt)
-{
-
-       KKASSERT(rt->rt_cpuid != mycpuid);
-
-       if (route_assert_owner_access) {
-               panic("rt remote free rt_cpuid %d, mycpuid %d",
-                     rt->rt_cpuid, mycpuid);
-       } else {
-               kprintf("rt remote free rt_cpuid %d, mycpuid %d\n",
-                       rt->rt_cpuid, mycpuid);
-               print_backtrace(-1);
-       }
-       rtfree_async(rt);
-}
-
 int
 rtredirect_oncpu(struct sockaddr *dst, struct sockaddr *gateway,
                 struct sockaddr *netmask, int flags, struct sockaddr *src)
@@ -381,6 +353,8 @@ rtredirect_oncpu(struct sockaddr *dst, struct sockaddr *gateway,
        u_long *stat = NULL;
        int error;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /* verify the gateway is directly reachable */
        if ((ifa = ifa_ifwithnet(gateway)) == NULL) {
                error = ENETUNREACH;
@@ -486,8 +460,6 @@ struct netmsg_rtredirect {
  * 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,
@@ -504,7 +476,8 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway,
        msg.netmask = netmask;
        msg.flags = flags;
        msg.src = src;
-       error = rt_domsg_global(&msg.base);
+       error = netisr_domsg_global(&msg.base);
+
        bzero(&rtinfo, sizeof(struct rt_addrinfo));
        rtinfo.rti_info[RTAX_DST] = dst;
        rtinfo.rti_info[RTAX_GATEWAY] = gateway;
@@ -517,15 +490,10 @@ static void
 rtredirect_msghandler(netmsg_t msg)
 {
        struct netmsg_rtredirect *rmsg = (void *)msg;
-       int nextcpu;
 
        rtredirect_oncpu(rmsg->dst, rmsg->gateway, rmsg->netmask,
                         rmsg->flags, rmsg->src);
-       nextcpu = mycpuid + 1;
-       if (nextcpu < ncpus)
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &msg->lmsg);
-       else
-               lwkt_replymsg(&msg->lmsg, 0);
+       netisr_forwardmsg(&msg->base, mycpuid + 1);
 }
 
 /*
@@ -702,8 +670,8 @@ int
 rtrequest1_global(int req, struct rt_addrinfo *rtinfo,
     rtrequest1_callback_func_t callback, void *arg, boolean_t req_prio)
 {
-       int error, flags = 0;
        struct netmsg_rtq msg;
+       int flags = 0;
 
        if (req_prio)
                flags = MSGF_PRIORITY;
@@ -714,8 +682,7 @@ rtrequest1_global(int req, struct rt_addrinfo *rtinfo,
        msg.rtinfo = rtinfo;
        msg.callback = callback;
        msg.arg = arg;
-       error = rt_domsg_global(&msg.base);
-       return (error);
+       return (netisr_domsg_global(&msg.base));
 }
 
 /*
@@ -729,7 +696,6 @@ rtrequest1_msghandler(netmsg_t msg)
        struct netmsg_rtq *rmsg = (void *)msg;
        struct rt_addrinfo rtinfo;
        struct rtentry *rt = NULL;
-       int nextcpu;
        int error;
 
        /*
@@ -755,18 +721,16 @@ rtrequest1_msghandler(netmsg_t msg)
        if (rmsg->base.lmsg.ms_error < 0 || error == 0)
                rmsg->base.lmsg.ms_error = error;
 
-       nextcpu = mycpuid + 1;
        if (error && rmsg->req != RTM_DELETE) {
                if (mycpuid != 0) {
                        panic("rtrequest1_msghandler: rtrequest table req %d, "
                            "failed on cpu%d, error %d\n",
                            rmsg->req, mycpuid, error);
                }
-               lwkt_replymsg(&rmsg->base.lmsg, error);
-       } else if (nextcpu < ncpus) {
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &rmsg->base.lmsg);
+               netisr_replymsg(&rmsg->base, error);
        } else {
-               lwkt_replymsg(&rmsg->base.lmsg, rmsg->base.lmsg.ms_error);
+               netisr_forwardmsg_error(&rmsg->base, mycpuid + 1,
+                   rmsg->base.lmsg.ms_error);
        }
 }
 
@@ -782,6 +746,8 @@ rtrequest1(int req, struct rt_addrinfo *rtinfo, struct rtentry **ret_nrt)
        boolean_t reportmsg;
        int error = 0;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
 #define gotoerr(x) { error = x ; goto bad; }
 
 #ifdef ROUTE_DEBUG
@@ -1181,6 +1147,8 @@ rt_setgate(struct rtentry *rt0, struct sockaddr *dst, struct sockaddr *gate,
        struct rtentry *rt = rt0;
        struct radix_node_head *rnh = rt_tables[mycpuid][dst->sa_family];
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /*
         * A host route with the destination equal to the gateway
         * will interfere with keeping LLINFO in the routing
@@ -1307,6 +1275,8 @@ rt_llroute(struct sockaddr *dst, struct rtentry *rt0, struct rtentry **drt)
 {
        struct rtentry *up_rt, *rt;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        if (!(rt0->rt_flags & RTF_UP)) {
                up_rt = rtlookup(dst);
                if (up_rt == NULL)
@@ -1515,6 +1485,8 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
        struct rt_addrinfo rtinfo;
        int error;
 
+       ASSERT_NETISR0;
+
        if (flags & RTF_HOST) {
                dst = ifa->ifa_dstaddr;
                netmask = NULL;
@@ -1633,7 +1605,7 @@ rtsearch_global(int req, struct rt_addrinfo *rtinfo,
        msg.arg = arg;
        msg.exact_match = exact_match;
        msg.found_cnt = 0;
-       return rt_domsg_global(&msg.base);
+       return (netisr_domsg_global(&msg.base));
 }
 
 static void
@@ -1643,7 +1615,9 @@ rtsearch_msghandler(netmsg_t msg)
        struct rt_addrinfo rtinfo;
        struct radix_node_head *rnh;
        struct rtentry *rt;
-       int nextcpu, error;
+       int error;
+
+       ASSERT_NETISR_NCPUS(mycpuid);
 
        /*
         * Copy the rtinfo.  We need to make sure that the original
@@ -1659,7 +1633,7 @@ rtsearch_msghandler(netmsg_t msg)
        if ((rnh = rt_tables[mycpuid][rtinfo.rti_dst->sa_family]) == NULL) {
                if (mycpuid != 0)
                        panic("partially initialized routing tables");
-               lwkt_replymsg(&rmsg->base.lmsg, EAFNOSUPPORT);
+               netisr_replymsg(&rmsg->base, EAFNOSUPPORT);
                return;
        }
 
@@ -1701,12 +1675,11 @@ rtsearch_msghandler(netmsg_t msg)
                rt->rt_refcnt--;
 
                if (error == EJUSTRETURN) {
-                       lwkt_replymsg(&rmsg->base.lmsg, 0);
+                       netisr_replymsg(&rmsg->base, 0);
                        return;
                }
        }
 
-       nextcpu = mycpuid + 1;
        if (error) {
                KKASSERT(rmsg->found_cnt > 0);
 
@@ -1721,15 +1694,13 @@ rtsearch_msghandler(netmsg_t msg)
                        panic("rtsearch_msghandler: unrecoverable error "
                              "cpu %d", mycpuid);
                }
-               lwkt_replymsg(&rmsg->base.lmsg, error);
-       } else if (nextcpu < ncpus) {
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &rmsg->base.lmsg);
+               netisr_replymsg(&rmsg->base, error);
        } else {
                if (rmsg->found_cnt == 0) {
-                       /* The requested route was never seen ... */
+                       /* The requested route has not been seen ... */
                        error = ESRCH;
                }
-               lwkt_replymsg(&rmsg->base.lmsg, error);
+               netisr_forwardmsg_error(&rmsg->base, mycpuid + 1, error);
        }
 }
 
@@ -1745,7 +1716,7 @@ rtmask_add_global(struct sockaddr *mask, boolean_t req_prio)
            rtmask_add_msghandler);
        msg.lmsg.u.ms_resultp = mask;
 
-       return rt_domsg_global(&msg);
+       return (netisr_domsg_global(&msg));
 }
 
 struct sockaddr *
@@ -1769,18 +1740,15 @@ _rtmask_lookup(struct sockaddr *mask, boolean_t search)
 static void
 rtmask_add_msghandler(netmsg_t msg)
 {
-       struct lwkt_msg *lmsg = &msg->lmsg;
-       struct sockaddr *mask = lmsg->u.ms_resultp;
-       int error = 0, nextcpu;
-
-       if (rtmask_lookup(mask) == NULL)
-               error = ENOBUFS;
-
-       nextcpu = mycpuid + 1;
-       if (!error && nextcpu < ncpus)
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), lmsg);
-       else
-               lwkt_replymsg(lmsg, error);
+       struct sockaddr *mask = msg->lmsg.u.ms_resultp;
+
+       ASSERT_NETISR_NCPUS(mycpuid);
+
+       if (rtmask_lookup(mask) == NULL) {
+               netisr_replymsg(&msg->base, ENOBUFS);
+               return;
+       }
+       netisr_forwardmsg(&msg->base, mycpuid + 1);
 }
 
 /* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
@@ -1843,9 +1811,10 @@ rtchange_dispatch(netmsg_t msg)
        struct netmsg_rtchange *rmsg = (void *)msg;
        struct radix_node_head *rnh;
        struct rtchange_arg arg;
-       int nextcpu, cpu;
+       int cpu;
 
        cpu = mycpuid;
+       ASSERT_NETISR_NCPUS(cpu);
 
        memset(&arg, 0, sizeof(arg));
        arg.old_ifa = rmsg->old_ifa;
@@ -1870,11 +1839,7 @@ rtchange_dispatch(netmsg_t msg)
        if (arg.changed)
                rmsg->changed = 1;
 
-       nextcpu = cpu + 1;
-       if (nextcpu < ncpus)
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &rmsg->base.lmsg);
-       else
-               lwkt_replymsg(&rmsg->base.lmsg, 0);
+       netisr_forwardmsg(&rmsg->base, cpu + 1);
 }
 
 int
@@ -1894,7 +1859,7 @@ rtchange(struct ifaddr *old_ifa, struct ifaddr *new_ifa)
        msg.old_ifa = old_ifa;
        msg.new_ifa = new_ifa;
        msg.changed = 0;
-       rt_domsg_global(&msg.base);
+       netisr_domsg_global(&msg.base);
 
        if (msg.changed) {
                old_ifa->ifa_flags &= ~IFA_ROUTE;
@@ -1904,10 +1869,3 @@ rtchange(struct ifaddr *old_ifa, struct ifaddr *new_ifa)
                return ENOENT;
        }
 }
-
-int
-rt_domsg_global(struct netmsg_base *nmsg)
-{
-
-       return (netisr_domsg(nmsg, 0));
-}
index db45102..be8759c 100644 (file)
@@ -387,6 +387,7 @@ typedef int (*rtsearch_callback_func_t)(int, struct rt_addrinfo *,
                                        struct rtentry *, void *, int);
 
 void    rtfree (struct rtentry *);
+void    rtfree_async (struct rtentry *);
 int     rtinit (struct ifaddr *, int, int);
 int     rtchange (struct ifaddr *, struct ifaddr *);
 int     rtioctl (u_long, caddr_t, struct ucred *);
@@ -427,31 +428,26 @@ rtmask_purelookup(struct sockaddr *_mask)
        return _rtmask_lookup(_mask, TRUE);
 }
 
-void   rtfree_oncpu(struct rtentry *);
-void   rtfree_async(struct rtentry *);
-void   rtfree_remote(struct rtentry *);
 void   rt_print(struct rt_addrinfo *, struct rtentry *);
 void   rt_addrinfo_print(int cmd, struct rt_addrinfo *);
 void   sockaddr_print(struct sockaddr *);
 
-struct netmsg_base;
-int    rt_domsg_global(struct netmsg_base *);
-
 #ifndef _SYS_GLOBALDATA_H_
 #include <sys/globaldata.h>
 #endif
+#ifndef _NET_NETISR2_H_
+#include <net/netisr2.h>
+#endif
 
 static __inline void
 RTFREE(struct rtentry *rt)
 {
-       if (rt->rt_cpuid == mycpuid) {
-               if (rt->rt_refcnt <= 1)
-                       rtfree_oncpu(rt);
-               else
-                       --rt->rt_refcnt;
-       } else {
-               rtfree_remote(rt);
-       }
+
+       ASSERT_NETISR_NCPUS(rt->rt_cpuid);
+       if (rt->rt_refcnt <= 1)
+               rtfree(rt);
+       else
+               --rt->rt_refcnt;
 }
 
 int    in_inithead(void **, int);
index 1aa5b9f..f958569 100644 (file)
@@ -1633,7 +1633,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
         * debugging the route table.
         */
        if (namelen == 4) {
-               if (name[3] < 0 || name[3] >= ncpus)
+               if (name[3] < 0 || name[3] >= netisr_ncpus)
                        return (EINVAL);
                cpu = name[3];
        } else {
index fadcca0..53f4eba 100644 (file)
@@ -185,6 +185,8 @@ arptimer_dispatch(netmsg_t nmsg)
        struct llinfo_arp *la, *nla;
        struct arp_pcpu_data *ad = &arp_data[mycpuid];
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /* Reply ASAP */
        crit_enter();
        lwkt_replymsg(&nmsg->lmsg, 0);
@@ -254,7 +256,7 @@ arp_rtrequest(int req, struct rtentry *rt)
                 * once on cpu0.
                 */
                if ((rt->rt_flags & RTF_ANNOUNCE) && mycpuid == 0) {
-                       arprequest_async(rt->rt_ifp,
+                       arprequest(rt->rt_ifp,
                            &SIN(rt_key(rt))->sin_addr,
                            &SIN(rt_key(rt))->sin_addr,
                            LLADDR(SDL(gate)));
@@ -392,6 +394,8 @@ arpreq_send(struct ifnet *ifp, struct mbuf *m)
        struct sockaddr sa;
        struct ether_header *eh;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        switch (ifp->if_type) {
        case IFT_ETHER:
                /*
@@ -435,6 +439,8 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
 {
        struct mbuf *m;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        if (enaddr == NULL) {
                if (ifp->if_bridge) {
                        enaddr = IF_LLADDR(ether_bridge_interface(ifp));
@@ -460,6 +466,7 @@ arprequest_async(struct ifnet *ifp, const struct in_addr *sip,
 {
        struct mbuf *m;
        struct netmsg_packet *pmsg;
+       int cpu;
 
        if (enaddr == NULL) {
                if (ifp->if_bridge) {
@@ -478,7 +485,11 @@ arprequest_async(struct ifnet *ifp, const struct in_addr *sip,
        pmsg->nm_packet = m;
        pmsg->base.lmsg.u.ms_resultp = ifp;
 
-       lwkt_sendmsg_oncpu(netisr_cpuport(mycpuid), &pmsg->base.lmsg);
+       if (mycpuid < netisr_ncpus)
+               cpu = mycpuid;
+       else
+               cpu = 0;
+       lwkt_sendmsg(netisr_cpuport(cpu), &pmsg->base.lmsg);
 }
 
 /*
@@ -1044,7 +1055,7 @@ match:
                                   itaddr.s_addr == myaddr.s_addr,
                                   RTL_REPORTMSG, TRUE);
 
-       if (ncpus > 1 && changed) {
+       if (netisr_ncpus > 1 && changed) {
                struct netmsg_inarp *msg = &m->m_hdr.mh_arpmsg;
 
                netmsg_init(&msg->base, NULL, &netisr_apanic_rport,
@@ -1083,6 +1094,8 @@ arp_update_msghandler(netmsg_t msg)
        struct netmsg_inarp *rmsg = (struct netmsg_inarp *)msg;
        int nextcpu;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /*
         * This message handler will be called on all of the APs;
         * no need to generate rtmsg on them.
@@ -1093,7 +1106,7 @@ arp_update_msghandler(netmsg_t msg)
                         RTL_DONTREPORT, FALSE);
 
        nextcpu = mycpuid + 1;
-       if (nextcpu < ncpus) {
+       if (nextcpu < netisr_ncpus) {
                lwkt_forwardmsg(netisr_cpuport(nextcpu), &rmsg->base.lmsg);
        } else {
                struct mbuf *m = rmsg->m;
@@ -1125,6 +1138,8 @@ in_arpreply(struct mbuf *m, in_addr_t taddr, in_addr_t myaddr)
        struct sockaddr sa;
        struct ether_header *eh;
 
+       ASSERT_NETISR0;
+
        ah = mtod(m, struct arphdr *);
        if (ntohs(ah->ar_op) != ARPOP_REQUEST) {
                m_freem(m);
@@ -1301,8 +1316,13 @@ void
 arp_gratuitous(struct ifnet *ifp, struct ifaddr *ifa)
 {
        if (IA_SIN(ifa)->sin_addr.s_addr != INADDR_ANY) {
-               arprequest_async(ifp, &IA_SIN(ifa)->sin_addr,
-                                &IA_SIN(ifa)->sin_addr, NULL);
+               if (IN_NETISR_NCPUS(mycpuid)) {
+                       arprequest(ifp, &IA_SIN(ifa)->sin_addr,
+                           &IA_SIN(ifa)->sin_addr, NULL);
+               } else {
+                       arprequest_async(ifp, &IA_SIN(ifa)->sin_addr,
+                           &IA_SIN(ifa)->sin_addr, NULL);
+               }
        }
 }
 
@@ -1335,7 +1355,7 @@ arp_init(void)
 {
        int cpu;
 
-       for (cpu = 0; cpu < ncpus; cpu++) {
+       for (cpu = 0; cpu < netisr_ncpus; cpu++) {
                struct arp_pcpu_data *ad = &arp_data[cpu];
 
                LIST_INIT(&ad->llinfo_list);
index c9b4a62..5b8e0b6 100644 (file)
@@ -327,6 +327,8 @@ in_rtqtimo_dispatch(netmsg_t nmsg)
        struct in_rtq_pcpu *pcpu = &in_rtq_pcpu[mycpuid];
        struct radix_node_head *rnh = pcpu->rnh;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /* Reply ASAP */
        crit_enter();
        lwkt_replymsg(&nmsg->lmsg, 0);
@@ -395,6 +397,8 @@ in_rtqdrain_oncpu(struct in_rtq_pcpu *pcpu)
        struct radix_node_head *rnh = rt_tables[mycpuid][AF_INET];
        struct rtqk_arg arg;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        arg.found = arg.killed = 0;
        arg.rnh = rnh;
        arg.nextstop = 0;
@@ -437,15 +441,16 @@ in_rtqdrain(void)
        cpumask_t mask;
        int cpu;
 
-       CPUMASK_ASSBMASK(mask, ncpus);
+       CPUMASK_ASSBMASK(mask, netisr_ncpus);
        CPUMASK_ANDMASK(mask, smp_active_mask);
 
-       if (IN_NETISR(mycpuid)) {
-               in_rtqdrain_oncpu(&in_rtq_pcpu[mycpuid]);
-               CPUMASK_NANDBIT(mask, mycpuid);
+       cpu = mycpuid;
+       if (IN_NETISR_NCPUS(cpu)) {
+               in_rtqdrain_oncpu(&in_rtq_pcpu[cpu]);
+               CPUMASK_NANDBIT(mask, cpu);
        }
 
-       for (cpu = 0; cpu < ncpus; ++cpu) {
+       for (cpu = 0; cpu < netisr_ncpus; ++cpu) {
                struct in_rtq_pcpu *pcpu = &in_rtq_pcpu[cpu];
 
                if (!CPUMASK_TESTBIT(mask, cpu))
@@ -553,9 +558,10 @@ in_ifadown_dispatch(netmsg_t msg)
        struct radix_node_head *rnh;
        struct ifaddr *ifa = rmsg->ifa;
        struct in_ifadown_arg arg;
-       int nextcpu, cpu;
+       int cpu;
 
        cpu = mycpuid;
+       ASSERT_NETISR_NCPUS(cpu);
 
        arg.rnh = rnh = rt_tables[cpu][AF_INET];
        arg.ifa = ifa;
@@ -563,11 +569,7 @@ in_ifadown_dispatch(netmsg_t msg)
        rnh->rnh_walktree(rnh, in_ifadownkill, &arg);
        ifa->ifa_flags &= ~IFA_ROUTE;
 
-       nextcpu = cpu + 1;
-       if (nextcpu < ncpus)
-               lwkt_forwardmsg(netisr_cpuport(nextcpu), &rmsg->base.lmsg);
-       else
-               lwkt_replymsg(&rmsg->base.lmsg, 0);
+       netisr_forwardmsg(&msg->base, cpu + 1);
 }
 
 int
@@ -589,7 +591,7 @@ in_ifadown_force(struct ifaddr *ifa, int delete)
            in_ifadown_dispatch);
        msg.ifa = ifa;
        msg.del = delete;
-       rt_domsg_global(&msg.base);
+       netisr_domsg_global(&msg.base);
 
        return 0;
 }
index a8864a1..27ced20 100644 (file)
@@ -379,9 +379,9 @@ tcp_ctlport(int cmd, struct sockaddr *sa, void *vip, int *cpuid)
        if (notify == NULL)
                return NULL;
 
-       if (*cpuid == ncpus) {
+       if (*cpuid == netisr_ncpus) {
                /*
-                * Go through all CPUs.
+                * Go through all effective netisr CPUs.
                 *
                 * A new message will be allocated later to save necessary
                 * information and will be forwarded to all network protocol
@@ -441,9 +441,9 @@ udp_ctlport(int cmd, struct sockaddr *sa, void *vip, int *cpuid)
        if (notify == NULL)
                return NULL;
 
-       if (*cpuid == ncpus) {
+       if (*cpuid == netisr_ncpus) {
                /*
-                * Go through all CPUs.
+                * Go through all effective netisr CPUs.
                 *
                 * See the comment in tcp_ctlport.
                 */
index 58d3508..539b87e 100644 (file)
@@ -335,10 +335,12 @@ icmp_mtudisc_handler(netmsg_t nmsg)
        struct netmsg_ctlinput *msg = (struct netmsg_ctlinput *)nmsg;
        int nextcpu;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        icmp_mtudisc(msg->m, msg->hlen);
 
        nextcpu = mycpuid + 1;
-       if (nextcpu < ncpus)
+       if (nextcpu < netisr_ncpus)
                lwkt_forwardmsg(netisr_cpuport(nextcpu), &msg->base.lmsg);
        else
                icmp_ctlinput_done(msg->m);
@@ -353,7 +355,7 @@ icmp_mtudisc_start(struct mbuf *m, int hlen, int proto)
 
        icmp_mtudisc(m, hlen);
 
-       if (ncpus == 1) {
+       if (netisr_ncpus == 1) {
                /* There is only one netisr; done */
                return FALSE;
        }
@@ -394,6 +396,8 @@ icmp_ctlinput_handler(netmsg_t nmsg)
 {
        struct netmsg_ctlinput *msg = (struct netmsg_ctlinput *)nmsg;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        icmp_ctlinput(msg->m, msg->cmd, msg->hlen);
        icmp_ctlinput_done(msg->m);
 }
@@ -424,10 +428,12 @@ icmp_ctlinput_global_handler(netmsg_t nmsg)
        struct netmsg_ctlinput *msg = (struct netmsg_ctlinput *)nmsg;
        int nextcpu;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        icmp_ctlinput(msg->m, msg->cmd, msg->hlen);
 
        nextcpu = mycpuid + 1;
-       if (nextcpu < ncpus)
+       if (nextcpu < netisr_ncpus)
                lwkt_forwardmsg(netisr_cpuport(nextcpu), &msg->base.lmsg);
        else
                icmp_ctlinput_done(msg->m);
@@ -439,7 +445,7 @@ icmp_ctlinput_global_start(struct mbuf *m, int cmd, int hlen, int proto)
        struct netmsg_ctlinput *msg;
 
        ASSERT_NETISR0;
-       KASSERT(ncpus > 1, ("there is only 1 cpu"));
+       KASSERT(netisr_ncpus > 1, ("there is only 1 netisr cpu"));
 
        icmp_ctlinput(m, cmd, hlen);
 
@@ -551,10 +557,12 @@ icmp_redirect_handler(netmsg_t nmsg)
        struct netmsg_ctlinput *msg = (struct netmsg_ctlinput *)nmsg;
        int nextcpu;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        icmp_redirect(msg->m, msg->hlen, FALSE);
 
        nextcpu = mycpuid + 1;
-       if (nextcpu < ncpus)
+       if (nextcpu < netisr_ncpus)
                lwkt_forwardmsg(netisr_cpuport(nextcpu), &msg->base.lmsg);
        else
                icmp_redirect_done(msg->m, msg->hlen, TRUE);
@@ -569,7 +577,7 @@ icmp_redirect_start(struct mbuf *m, int hlen, int proto)
 
        icmp_redirect(m, hlen, TRUE);
 
-       if (ncpus == 1) {
+       if (netisr_ncpus == 1) {
                /* There is only one netisr; done */
                icmp_redirect_done(m, hlen, FALSE);
                return FALSE;
@@ -761,8 +769,8 @@ deliver:
                        port = so_pr_ctlport(pr, code,
                            (struct sockaddr *)&icmpsrc, &icp->icmp_ip, &cpu);
                        if (port != NULL) {
-                               if (cpu == ncpus) {
-                                       if (ncpus > 1) {
+                               if (cpu == netisr_ncpus) {
+                                       if (netisr_ncpus > 1) {
                                                /*
                                                 * Run pr_ctlinput in all
                                                 * netisrs
index fdd9765..1da4b3a 100644 (file)
@@ -347,8 +347,8 @@ ip_init(void)
            IFQ_MAXLEN, IPFRAG_MPIPE_MAX, 0, NULL, NULL, NULL);
 
        /*
-        * Addresses could be accessed from any CPUs in non-netisr threads,
-        * so populate all CPUs.
+        * Make in_ifaddrhead and in_ifaddrhashtbl available on all CPUs,
+        * since they could be accessed by any threads.
         */
        for (cpu = 0; cpu < ncpus; ++cpu) {
                TAILQ_INIT(&in_ifaddrheads[cpu]);
index 5f43758..43786f5 100644 (file)
@@ -1167,7 +1167,7 @@ tcp_drain(void)
 
        cpu = mycpuid;
        if (IN_NETISR_NCPUS(cpu)) {
-               tcp_drain_oncpu(&tcbinfo[mycpuid]);
+               tcp_drain_oncpu(&tcbinfo[cpu]);
                CPUMASK_NANDBIT(mask, cpu);
        }
 
@@ -1414,6 +1414,8 @@ tcp_notifyall_oncpu(netmsg_t msg)
        struct netmsg_tcp_notify *nm = (struct netmsg_tcp_notify *)msg;
        int nextcpu;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        in_pcbnotifyall(&tcbinfo[mycpuid], nm->nm_faddr,
                        nm->nm_arg, nm->nm_notify);
 
@@ -1462,8 +1464,8 @@ tcp_get_inpnotify(int cmd, const struct sockaddr *sa,
 
        if (cpuid != NULL) {
                if (ip == NULL) {
-                       /* Go through all CPUs */
-                       *cpuid = ncpus;
+                       /* Go through all effective netisr CPUs. */
+                       *cpuid = netisr_ncpus;
                } else {
                        const struct tcphdr *th;
 
@@ -1488,6 +1490,8 @@ tcp_ctlinput(netmsg_t msg)
        inp_notify_t notify;
        int arg, cpuid;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        notify = tcp_get_inpnotify(cmd, sa, &arg, &ip, &cpuid);
        if (notify == NULL)
                goto done;
@@ -1524,9 +1528,7 @@ tcp_ctlinput(netmsg_t msg)
                        syncache_unreach(&inc, th);
                }
        } else if (msg->ctlinput.nm_direct) {
-               if (cpuid != ncpus && cpuid != mycpuid)
-                       goto done;
-               if (mycpuid >= netisr_ncpus)
+               if (cpuid != netisr_ncpus && cpuid != mycpuid)
                        goto done;
 
                in_pcbnotifyall(&tcbinfo[mycpuid], faddr, arg, notify);
index 9031230..c791ca8 100644 (file)
@@ -747,6 +747,8 @@ udp_notifyall_oncpu(netmsg_t msg)
        struct netmsg_udp_notify *nm = (struct netmsg_udp_notify *)msg;
        int nextcpu, cpu = mycpuid;
 
+       ASSERT_NETISR_NCPUS(cpu);
+
        in_pcbnotifyall(&udbinfo[cpu], nm->nm_faddr, nm->nm_arg, nm->nm_notify);
 
        nextcpu = cpu + 1;
@@ -779,8 +781,8 @@ udp_get_inpnotify(int cmd, const struct sockaddr *sa,
 
        if (cpuid != NULL) {
                if (ip == NULL) {
-                       /* Go through all CPUs */
-                       *cpuid = ncpus;
+                       /* Go through all effective netisr CPUs. */
+                       *cpuid = netisr_ncpus;
                } else {
                        const struct udphdr *uh;
 
@@ -804,6 +806,8 @@ udp_ctlinput(netmsg_t msg)
        inp_notify_t notify;
        struct in_addr faddr;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        notify = udp_get_inpnotify(cmd, sa, &ip, &cpuid);
        if (notify == NULL)
                goto done;
@@ -822,9 +826,7 @@ udp_ctlinput(netmsg_t msg)
                if (inp != NULL && inp->inp_socket != NULL)
                        notify(inp, inetctlerrmap[cmd]);
        } else if (msg->ctlinput.nm_direct) {
-               if (cpuid != ncpus && cpuid != mycpuid)
-                       goto done;
-               if (mycpuid >= netisr_ncpus)
+               if (cpuid != netisr_ncpus && cpuid != mycpuid)
                        goto done;
 
                in_pcbnotifyall(&udbinfo[mycpuid], faddr, inetctlerrmap[cmd],
index 0eb4350..d266386 100644 (file)
@@ -365,6 +365,8 @@ in6_rtqtimo_dispatch(netmsg_t nmsg)
        struct timeval atv;
        static time_t last_adjusted_timeout = 0;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /* Reply ASAP */
        crit_enter();
        lwkt_replymsg(&nmsg->lmsg, 0);
@@ -467,6 +469,8 @@ in6_mtutimo_dispatch(netmsg_t nmsg)
        struct mtuex_arg arg;
        struct timeval atv;
 
+       ASSERT_NETISR_NCPUS(mycpuid);
+
        /* Reply ASAP */
        crit_enter();
        lwkt_replymsg(&nmsg->lmsg, 0);
index c1e895a..0fc1041 100644 (file)
  * 400907 - pthread_getthreadid_np()
  * 400908 - {clock,pthread}_getcpuclockid()
  * 400909 - deleted ortentry, SIOC{ADD,DEL}RT, RTM_OLD{ADD,DEL}
+ * 400910 - routing table is only available on netisr_ncpus
  */
 #undef __DragonFly_version
-#define __DragonFly_version 400909     /* propagated to newvers */
+#define __DragonFly_version 400910     /* propagated to newvers */
 
 #include <sys/_null.h>
 
index 5fd9358..0d33e85 100644 (file)
@@ -35,6 +35,7 @@
 #include <sys/file.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/sysctl.h>
 
 #include <netinet/in.h>
 
@@ -271,6 +272,7 @@ main(int argc, char **argv)
        struct protox *tp = NULL;  /* for printing cblocks & stats */
        int ch;
        int n;
+       size_t nsz;
 
        af = AF_UNSPEC;
 
@@ -286,11 +288,13 @@ main(int argc, char **argv)
                        bflag = 1;
                        break;
                case 'c':
-                       kread(0, 0, 0);
-                       kread(nl[N_NCPUS].n_value, (char *)&n, sizeof(n));
+                       nsz = sizeof(n);
+                       sysctlbyname("net.netisr.ncpus", &n, &nsz, NULL, 0);
                        cpuflag = strtol(optarg, NULL, 0);
-                       if (cpuflag < 0 || cpuflag >= n)
-                           errx(1, "cpu %d does not exist", cpuflag);
+                       if (cpuflag < 0 || cpuflag >= n) {
+                               errx(1, "cpu%d does not have network data",
+                                   cpuflag);
+                       }
                        break;
                case 'd':
                        dflag = 1;