Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 10 Sep 2010 09:28:37 +0000 (02:28 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 10 Sep 2010 09:28:37 +0000 (02:28 -0700)
125 files changed:
sys/bus/usb/usb_ethersubr.c
sys/conf/options
sys/config/LINT
sys/ddb/db_output.c
sys/dev/acpica5/acpi_cpu_pstate.c
sys/dev/netif/emx/if_emx.c
sys/dev/netif/ic/if_ic.c
sys/dev/netif/jme/if_jme.c
sys/kern/kern_poll.c
sys/kern/sys_generic.c
sys/kern/sys_socket.c
sys/kern/uipc_mbuf.c
sys/kern/uipc_msg.c
sys/kern/uipc_socket.c
sys/kern/uipc_socket2.c
sys/kern/uipc_syscalls.c
sys/kern/uipc_usrreq.c
sys/net/bpf.c
sys/net/bridge/if_bridge.c
sys/net/ef/if_ef.c
sys/net/faith/if_faith.c
sys/net/gif/if_gif.c
sys/net/if.c
sys/net/if_atmsubr.c
sys/net/if_ethersubr.c
sys/net/if_poll.c
sys/net/if_var.h
sys/net/ip_mroute/ip_mroute.c
sys/net/ipfw/ip_fw2.c
sys/net/netisr.c
sys/net/netisr.h
sys/net/netmsg.h
sys/net/netmsg2.h
sys/net/ppp/if_ppp.c
sys/net/raw_cb.c
sys/net/raw_usrreq.c
sys/net/rtsock.c
sys/net/sppp/if_spppsubr.c
sys/net/stf/if_stf.c
sys/net/toeplitz.c
sys/net/toeplitz2.h
sys/net/tun/if_tun.c
sys/netbt/bt_input.c
sys/netbt/bt_proto.c
sys/netbt/hci_socket.c
sys/netbt/l2cap_socket.c
sys/netbt/rfcomm_socket.c
sys/netbt/sco_socket.c
sys/netgraph/iface/ng_iface.c
sys/netgraph/ksocket/ng_ksocket.c
sys/netgraph/netgraph/ng_base.c
sys/netgraph/socket/ng_socket.c
sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c
sys/netgraph7/ng_base.c
sys/netgraph7/ng_iface.c
sys/netgraph7/ng_ip_input.c
sys/netgraph7/ng_ksocket.c
sys/netgraph7/ng_socket.c
sys/netinet/if_ether.c
sys/netinet/in_pcb.c
sys/netinet/in_proto.c
sys/netinet/ip_demux.c
sys/netinet/ip_divert.c
sys/netinet/ip_flow.c
sys/netinet/ip_gre.c
sys/netinet/ip_input.c
sys/netinet/ip_var.h
sys/netinet/raw_ip.c
sys/netinet/sctp_indata.c
sys/netinet/sctp_input.c
sys/netinet/sctp_pcb.c
sys/netinet/sctp_peeloff.c
sys/netinet/sctp_usrreq.c
sys/netinet/sctputil.c
sys/netinet/tcp_input.c
sys/netinet/tcp_subr.c
sys/netinet/tcp_syncache.c
sys/netinet/tcp_usrreq.c
sys/netinet/tcp_var.h
sys/netinet/udp_usrreq.c
sys/netinet6/ah_input.c
sys/netinet6/esp_input.c
sys/netinet6/frag6.c
sys/netinet6/in6_pcb.c
sys/netinet6/in6_proto.c
sys/netinet6/ip6_input.c
sys/netinet6/ip6_var.h
sys/netinet6/ipsec.c
sys/netinet6/raw_ip6.c
sys/netinet6/sctp6_usrreq.c
sys/netinet6/udp6_usrreq.c
sys/netproto/atalk/aarp.c
sys/netproto/atalk/ddp_input.c
sys/netproto/atalk/ddp_usrreq.c
sys/netproto/atm/atm_aal5.c
sys/netproto/atm/atm_socket.c
sys/netproto/atm/atm_subr.c
sys/netproto/atm/ipatm/ipatm_input.c
sys/netproto/ipsec/keysock.c
sys/netproto/ipx/ipx_input.c
sys/netproto/ipx/ipx_ip.c
sys/netproto/ipx/ipx_pcb.c
sys/netproto/ipx/ipx_usrreq.c
sys/netproto/ipx/spx_usrreq.c
sys/netproto/key/key.c
sys/netproto/key/key.h
sys/netproto/key/keydb.c
sys/netproto/key/keysock.c
sys/netproto/mpls/mpls_demux.c
sys/netproto/mpls/mpls_input.c
sys/netproto/mpls/mpls_var.h
sys/netproto/natm/natm.c
sys/netproto/ncp/ncp_sock.c
sys/netproto/ns/idp_usrreq.c
sys/netproto/ns/ns_input.c
sys/netproto/ns/ns_ip.c
sys/netproto/ns/ns_pcb.c
sys/netproto/ns/spp_usrreq.c
sys/netproto/smb/smb_trantcp.c
sys/sys/mbuf.h
sys/sys/socketvar.h
sys/sys/socketvar2.h
sys/sys/thread.h
sys/vfs/fifofs/fifo_vnops.c
sys/vfs/nfs/nfs_socket.c

index 0cda6b4..c284b98 100644 (file)
@@ -59,6 +59,7 @@
 
 #include <sys/thread2.h>
 #include <sys/msgport2.h>
+#include <sys/mplock2.h>
 
 #include <net/if.h>
 #include <net/ifq_var.h>
@@ -79,9 +80,12 @@ usbintr(struct netmsg *msg)
        struct mbuf *m = ((struct netmsg_packet *)msg)->nm_packet;
        struct ifnet *ifp;
 
+       /* not MPSAFE */
+       get_mplock();
        ifp = m->m_pkthdr.rcvif;
        (*ifp->if_input)(ifp, m);
        /* the msg is embedded in the mbuf, do not reply it */
+       rel_mplock();
 }
 
 void
@@ -89,8 +93,7 @@ usb_register_netisr(void)
 {
        if (netisr_inited == 0) {
                netisr_inited = 1;
-               netisr_register(NETISR_USB, cpu0_portfn, pktinfo_portfn_notsupp,
-                               usbintr, NETISR_FLAG_NOTMPSAFE);
+               netisr_register(NETISR_USB, usbintr, NULL);
        }
 }
 
index 3424890..a214a05 100644 (file)
@@ -658,8 +658,7 @@ SYSLINK                     opt_syslink.h
 # DSCHED stuff
 DSCHED_FQ              opt_dsched.h
 
-# Receive Side Scaling
-RSS                    opt_rss.h
+# Receive Side Scaling (now basecode)
 RSS_DEBUG              opt_rss.h
 
 # Enable watchdogs
index fe244b7..0664204 100644 (file)
@@ -2913,10 +2913,6 @@ options          SCTP_MAP_LOGGING
 # DSCHED stuff
 options                DSCHED_FQ
 
-# Receive Side Scaling
-options                RSS
-options                RSS_DEBUG
-
 # WATCHDOG
 options                WATCHDOG_ENABLE         # Enable watchdog support framework
 options                WDOG_DISABLE_ON_PANIC   # Automatically disable watchdogs on panic
index cf674a0..7347b3b 100644 (file)
@@ -181,12 +181,14 @@ db_printf(const char *fmt, ...)
        __va_start(listp, fmt);
        kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
        __va_end(listp);
+/*     DELAY(100000);*/
 }
 
 void
 db_vprintf(const char *fmt, __va_list va)
 {
        kvcprintf (fmt, db_putchar, NULL, db_radix, va);
+/*     DELAY(100000);*/
 }
 
 int db_indent;
index 1e59491..97f2ccb 100644 (file)
@@ -940,8 +940,7 @@ acpi_pst_check_csr(struct acpi_pst_softc *sc)
                return 0;
 
        netmsg_init(&msg.nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE | MSGF_PRIORITY,
-                   acpi_pst_check_csr_handler);
+                   MSGF_PRIORITY, acpi_pst_check_csr_handler);
        msg.ctrl = &sc->pst_creg;
        msg.status = &sc->pst_sreg;
 
@@ -966,8 +965,7 @@ acpi_pst_check_pstates(struct acpi_pst_softc *sc)
                return 0;
 
        netmsg_init(&nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE | MSGF_PRIORITY,
-                   acpi_pst_check_pstates_handler);
+                   MSGF_PRIORITY, acpi_pst_check_pstates_handler);
 
        return lwkt_domsg(cpu_portfn(sc->pst_cpuid), &nmsg.nm_lmsg, 0);
 }
@@ -991,7 +989,7 @@ acpi_pst_init(struct acpi_pst_softc *sc)
                return 0;
 
        netmsg_init(&msg.nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE | MSGF_PRIORITY, acpi_pst_init_handler);
+                   MSGF_PRIORITY, acpi_pst_init_handler);
        msg.ctrl = &sc->pst_creg;
        msg.status = &sc->pst_sreg;
 
@@ -1017,8 +1015,7 @@ acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
        KKASSERT(acpi_pst_md != NULL);
 
        netmsg_init(&msg.nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE | MSGF_PRIORITY,
-                   acpi_pst_set_pstate_handler);
+                   MSGF_PRIORITY, acpi_pst_set_pstate_handler);
        msg.nmsg.nm_lmsg.u.ms_resultp = __DECONST(void *, pstate);
        msg.ctrl = &sc->pst_creg;
        msg.status = &sc->pst_sreg;
@@ -1047,8 +1044,7 @@ acpi_pst_get_pstate(struct acpi_pst_softc *sc)
                return 0;
 
        netmsg_init(&msg.nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE | MSGF_PRIORITY,
-                   acpi_pst_get_pstate_handler);
+                   MSGF_PRIORITY, acpi_pst_get_pstate_handler);
        msg.status = &sc->pst_sreg;
 
        lwkt_domsg(cpu_portfn(sc->pst_cpuid), &msg.nmsg.nm_lmsg, 0);
index 51fc3f3..cfba53f 100644 (file)
@@ -514,12 +514,10 @@ emx_attach(device_t dev)
        /* This controls when hardware reports transmit completion status. */
        sc->hw.mac.report_tx_early = 1;
 
-#ifdef RSS
        /* Calculate # of RX rings */
        if (ncpus > 1)
                sc->rx_ring_cnt = EMX_NRX_RING;
        else
-#endif
                sc->rx_ring_cnt = 1;
        sc->rx_ring_inuse = sc->rx_ring_cnt;
 
index 1be8d0f..72620dc 100644 (file)
@@ -296,7 +296,7 @@ icintr (device_t dev, int event, char *ptr)
          top = m_devget(sc->ic_ifbuf + ICHDRLEN, len, 0, &sc->ic_if, 0);
 
          if (top)
-           netisr_dispatch(NETISR_IP, top);
+           netisr_queue(NETISR_IP, top);
          break;
 
        err:
index b6a90b6..7cc5d2a 100644 (file)
@@ -620,7 +620,9 @@ jme_attach(device_t dev)
        if (sc->jme_tx_desc_cnt > JME_NDESC_MAX)
                sc->jme_tx_desc_cnt = JME_NDESC_MAX;
 
-#ifdef RSS
+       /*
+        * Calculate rx rings based on ncpus2
+        */
        sc->jme_rx_ring_cnt = jme_rx_ring_count;
        if (sc->jme_rx_ring_cnt <= 0)
                sc->jme_rx_ring_cnt = JME_NRXRING_1;
@@ -631,9 +633,6 @@ jme_attach(device_t dev)
                sc->jme_rx_ring_cnt = JME_NRXRING_4;
        else if (sc->jme_rx_ring_cnt >= JME_NRXRING_2)
                sc->jme_rx_ring_cnt = JME_NRXRING_2;
-#else
-       sc->jme_rx_ring_cnt = JME_NRXRING_MIN;
-#endif
        sc->jme_rx_ring_inuse = sc->jme_rx_ring_cnt;
 
        sc->jme_dev = dev;
index 1504b37..97a983e 100644 (file)
@@ -258,13 +258,13 @@ init_device_poll_pcpu(int cpuid)
        poll_reset_state(pctx);
 
        netmsg_init(&pctx->poll_netmsg, NULL, &netisr_adone_rport,
-                   MSGF_MPSAFE, netisr_poll);
+                   0, netisr_poll);
 #ifdef INVARIANTS
        pctx->poll_netmsg.nm_lmsg.u.ms_resultp = pctx;
 #endif
 
        netmsg_init(&pctx->poll_more_netmsg, NULL, &netisr_adone_rport,
-                   MSGF_MPSAFE, netisr_pollmore);
+                   0, netisr_pollmore);
 #ifdef INVARIANTS
        pctx->poll_more_netmsg.nm_lmsg.u.ms_resultp = pctx;
 #endif
@@ -342,7 +342,7 @@ sysctl_pollhz(SYSCTL_HANDLER_ARGS)
                phz = DEVICE_POLLING_FREQ_MAX;
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_sysctl_pollhz);
+                   0, poll_sysctl_pollhz);
        msg.nm_lmsg.u.ms_result = phz;
 
        port = cpu_portfn(pctx->poll_cpuid);
@@ -367,7 +367,7 @@ sysctl_polling(SYSCTL_HANDLER_ARGS)
                return error;
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_sysctl_polling);
+                   0, poll_sysctl_polling);
        msg.nm_lmsg.u.ms_result = enabled;
 
        port = cpu_portfn(pctx->poll_cpuid);
@@ -390,7 +390,7 @@ sysctl_regfrac(SYSCTL_HANDLER_ARGS)
                return error;
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_sysctl_regfrac);
+                   0, poll_sysctl_regfrac);
        msg.nm_lmsg.u.ms_result = reg_frac;
 
        port = cpu_portfn(pctx->poll_cpuid);
@@ -417,7 +417,7 @@ sysctl_burstmax(SYSCTL_HANDLER_ARGS)
                burst_max = MAX_POLL_BURST_MAX;
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_sysctl_burstmax);
+                   0, poll_sysctl_burstmax);
        msg.nm_lmsg.u.ms_result = burst_max;
 
        port = cpu_portfn(pctx->poll_cpuid);
@@ -440,7 +440,7 @@ sysctl_eachburst(SYSCTL_HANDLER_ARGS)
                return error;
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_sysctl_eachburst);
+                   0, poll_sysctl_eachburst);
        msg.nm_lmsg.u.ms_result = each_burst;
 
        port = cpu_portfn(pctx->poll_cpuid);
@@ -767,7 +767,7 @@ ether_pollcpu_register(struct ifnet *ifp, int cpuid)
        ifnet_deserialize_all(ifp);
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_register);
+                   0, poll_register);
        msg.nm_lmsg.u.ms_resultp = ifp;
 
        port = cpu_portfn(cpuid);
@@ -861,7 +861,7 @@ ether_poll_deregister(struct ifnet *ifp)
        ifnet_deserialize_all(ifp);
 
        netmsg_init(&msg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, poll_deregister);
+                   0, poll_deregister);
        msg.nm_lmsg.u.ms_resultp = ifp;
 
        port = cpu_portfn(cpuid);
index 18b6f6a..8f70272 100644 (file)
@@ -1499,6 +1499,11 @@ socket_wait_copyout(void *arg, struct kevent *kevp, int count, int *res)
 }
 
 extern struct fileops socketops;
+
+/*
+ * NOTE: Callers of socket_wait() must already have a reference on the
+ *      socket.
+ */
 int
 socket_wait(struct socket *so, struct timespec *ts, int *res)
 {
index 0b0eeb0..92527aa 100644 (file)
@@ -52,6 +52,7 @@
 #include <sys/ucred.h>
 
 #include <sys/mplock2.h>
+#include <sys/socketvar2.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -136,11 +137,11 @@ soo_ioctl(struct file *fp, u_long cmd, caddr_t data,
        switch (cmd) {
        case FIOASYNC:
                if (*(int *)data) {
-                       so->so_state |= SS_ASYNC;
+                       sosetstate(so, SS_ASYNC);
                        atomic_set_int(&so->so_rcv.ssb_flags,  SSB_ASYNC);
                        atomic_set_int(&so->so_snd.ssb_flags, SSB_ASYNC);
                } else {
-                       so->so_state &= ~SS_ASYNC;
+                       soclrstate(so, SS_ASYNC);
                        atomic_clear_int(&so->so_rcv.ssb_flags, SSB_ASYNC);
                        atomic_clear_int(&so->so_snd.ssb_flags, SSB_ASYNC);
                }
index 18f9b56..e0c8030 100644 (file)
@@ -167,9 +167,9 @@ mbufuntrack(struct mbuf *m)
                panic("mbufuntrack: mbuf %p was not tracked\n", m);
        } else {
                mbuf_rb_tree_RB_REMOVE(&mbuf_track_root, mbt);
+               spin_unlock(&mbuf_track_spin);
                kfree(mbt, M_MTRACK);
        }
-       spin_unlock(&mbuf_track_spin);
 }
 
 void
index 02a895f..1c9e786 100644 (file)
 
 /*
  * Abort a socket and free it.  Called from soabort() only.
- *
- * The SS_ABORTING flag must already be set.
  */
 void
 so_pru_abort(struct socket *so)
 {
        struct netmsg_pru_abort msg;
 
-       KKASSERT(so->so_state & SS_ABORTING);
        netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
                    0, netmsg_pru_abort);
        msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
@@ -70,15 +67,12 @@ so_pru_abort(struct socket *so)
 /*
  * Abort a socket and free it, asynchronously.  Called from
  * soaborta() only.
- *
- * The SS_ABORTING flag must already be set.
  */
 void
 so_pru_aborta(struct socket *so)
 {
        struct netmsg_pru_abort *msg;
 
-       KKASSERT(so->so_state & SS_ABORTING);
        msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO);
        netmsg_init(&msg->nm_netmsg, so, &netisr_afree_rport,
                    0, netmsg_pru_abort);
@@ -89,8 +83,6 @@ so_pru_aborta(struct socket *so)
 /*
  * Abort a socket and free it.  Called from soabort_oncpu() only.
  * Caller must make sure that the current CPU is inpcb's owner CPU.
- *
- * The SS_ABORTING flag must already be set.
  */
 void
 so_pru_abort_oncpu(struct socket *so)
@@ -418,6 +410,9 @@ so_pru_ctlinput(struct protosw *pr, int cmd, struct sockaddr *arg, void *extra)
 
 /*
  * Abort and destroy a socket.
+ *
+ * The originator referenced the socket so we must dereference it when
+ * done.
  */
 void
 netmsg_pru_abort(netmsg_t msg)
@@ -426,11 +421,8 @@ netmsg_pru_abort(netmsg_t msg)
        struct socket *so = msg->nm_so;
        int error;
 
-       KKASSERT(so->so_state & SS_ABORTING);
-       so->so_state &= ~SS_ABORTING;
        error = nm->nm_prufn(so);
-       if (error)
-               sofree(so);
+       sofree(so);     /* from soabort*() */
        lwkt_replymsg(&msg->nm_lmsg, error);
 }
 
index 96e4261..66160a6 100644 (file)
@@ -154,6 +154,10 @@ soalloc(int waitok)
                TAILQ_INIT(&so->so_aiojobq);
                TAILQ_INIT(&so->so_rcv.ssb_kq.ki_mlist);
                TAILQ_INIT(&so->so_snd.ssb_kq.ki_mlist);
+               lwkt_token_init(&so->so_rcv.ssb_token, 1, "rcvtok");
+               lwkt_token_init(&so->so_snd.ssb_token, 1, "rcvtok");
+               so->so_state = SS_NOFDREF;
+               so->so_refs = 1;
        }
        return so;
 }
@@ -187,9 +191,16 @@ socreate(int dom, struct socket **aso, int type,
        if (prp->pr_type != type)
                return (EPROTOTYPE);
        so = soalloc(p != 0);
-       if (so == 0)
+       if (so == NULL)
                return (ENOBUFS);
 
+       /*
+        * Callers of socreate() presumably will connect up a descriptor
+        * and call soclose() if they cannot.  This represents our so_refs
+        * (which should be 1) from soalloc().
+        */
+       soclrstate(so, SS_NOFDREF);
+
        /*
         * Set a default port for protocol processing.  No action will occur
         * on the socket on this port until an inpcb is attached to it and
@@ -213,11 +224,14 @@ socreate(int dom, struct socket **aso, int type,
         */
        error = so_pru_attach(so, proto, &ai);
        if (error) {
-               so->so_state |= SS_NOFDREF;
-               sofree(so);
-               return (error);
+               sosetstate(so, SS_NOFDREF);
+               sofree(so);     /* from soalloc */
+               return error;
        }
 
+       /*
+        * NOTE: Returns referenced socket.
+        */
        *aso = so;
        return (0);
 }
@@ -227,13 +241,11 @@ sobind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
        int error;
 
-       crit_enter();
        error = so_pru_bind(so, nam, td);
-       crit_exit();
        return (error);
 }
 
-void
+static void
 sodealloc(struct socket *so)
 {
        if (so->so_rcv.ssb_hiwat)
@@ -259,19 +271,18 @@ solisten(struct socket *so, int backlog, struct thread *td)
        short oldopt, oldqlimit;
 #endif /* SCTP */
 
-       crit_enter();
-       if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING)) {
-               crit_exit();
+       if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING))
                return (EINVAL);
-       }
 
 #ifdef SCTP
        oldopt = so->so_options;
        oldqlimit = so->so_qlimit;
 #endif /* SCTP */
 
+       lwkt_gettoken(&so->so_rcv.ssb_token);
        if (TAILQ_EMPTY(&so->so_comp))
                so->so_options |= SO_ACCEPTCONN;
+       lwkt_reltoken(&so->so_rcv.ssb_token);
        if (backlog < 0 || backlog > somaxconn)
                backlog = somaxconn;
        so->so_qlimit = backlog;
@@ -286,10 +297,8 @@ solisten(struct socket *so, int backlog, struct thread *td)
                so->so_options = oldopt;
                so->so_qlimit = oldqlimit;
 #endif /* SCTP */
-               crit_exit();
                return (error);
        }
-       crit_exit();
        return (0);
 }
 
@@ -299,18 +308,26 @@ solisten(struct socket *so, int backlog, struct thread *td)
  *
  *     so_pcb -        The protocol stack still has a reference
  *     SS_NOFDREF -    There is no longer a file pointer reference
- *     SS_ABORTING -   An abort netmsg is in-flight
  */
 void
 sofree(struct socket *so)
 {
        struct socket *head = so->so_head;
 
-       if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
-               return;
-       if (so->so_state & SS_ABORTING)
+       /*
+        * Arbitrage the last free.
+        */
+       KKASSERT(so->so_refs > 0);
+       if (atomic_fetchadd_int(&so->so_refs, -1) != 1)
                return;
+
+       KKASSERT(so->so_pcb == NULL && (so->so_state & SS_NOFDREF));
+
+       /*
+        * We're done, clean up
+        */
        if (head != NULL) {
+               lwkt_gettoken(&head->so_rcv.ssb_token);
                if (so->so_state & SS_INCOMP) {
                        TAILQ_REMOVE(&head->so_incomp, so, so_list);
                        head->so_incqlen--;
@@ -321,12 +338,14 @@ sofree(struct socket *so)
                         * accept(2) may hang after select(2) indicated
                         * that the listening socket was ready.
                         */
+                       lwkt_reltoken(&head->so_rcv.ssb_token);
                        return;
                } else {
                        panic("sofree: not queued");
                }
-               so->so_state &= ~SS_INCOMP;
+               soclrstate(so, SS_INCOMP);
                so->so_head = NULL;
+               lwkt_reltoken(&head->so_rcv.ssb_token);
        }
        ssb_release(&so->so_snd, so);
        sorflush(so);
@@ -343,7 +362,6 @@ soclose(struct socket *so, int fflag)
 {
        int error = 0;
 
-       crit_enter();
        funsetown(so->so_sigio);
        if (so->so_pcb == NULL)
                goto discard;
@@ -358,8 +376,8 @@ soclose(struct socket *so, int fflag)
                            (fflag & FNONBLOCK))
                                goto drop;
                        while (so->so_state & SS_ISCONNECTED) {
-                               error = tsleep((caddr_t)&so->so_timeo,
-                                   PCATCH, "soclos", so->so_linger * hz);
+                               error = tsleep(&so->so_timeo, PCATCH,
+                                              "soclos", so->so_linger * hz);
                                if (error)
                                        break;
                        }
@@ -374,29 +392,30 @@ drop:
                        error = error2;
        }
 discard:
+       lwkt_gettoken(&so->so_rcv.ssb_token);
        if (so->so_options & SO_ACCEPTCONN) {
                struct socket *sp;
 
                while ((sp = TAILQ_FIRST(&so->so_incomp)) != NULL) {
                        TAILQ_REMOVE(&so->so_incomp, sp, so_list);
-                       sp->so_state &= ~SS_INCOMP;
+                       soclrstate(sp, SS_INCOMP);
                        sp->so_head = NULL;
                        so->so_incqlen--;
                        soaborta(sp);
                }
                while ((sp = TAILQ_FIRST(&so->so_comp)) != NULL) {
                        TAILQ_REMOVE(&so->so_comp, sp, so_list);
-                       sp->so_state &= ~SS_COMP;
+                       soclrstate(sp, SS_COMP);
                        sp->so_head = NULL;
                        so->so_qlen--;
                        soaborta(sp);
                }
        }
+       lwkt_reltoken(&so->so_rcv.ssb_token);
        if (so->so_state & SS_NOFDREF)
                panic("soclose: NOFDREF");
-       so->so_state |= SS_NOFDREF;
-       sofree(so);
-       crit_exit();
+       sosetstate(so, SS_NOFDREF);     /* take ref */
+       sofree(so);                     /* dispose of ref */
        return (error);
 }
 
@@ -407,28 +426,22 @@ discard:
 void
 soabort(struct socket *so)
 {
-       if ((so->so_state & SS_ABORTING) == 0) {
-               so->so_state |= SS_ABORTING;
-               so_pru_abort(so);
-       }
+       soreference(so);
+       so_pru_abort(so);
 }
 
 void
 soaborta(struct socket *so)
 {
-       if ((so->so_state & SS_ABORTING) == 0) {
-               so->so_state |= SS_ABORTING;
-               so_pru_aborta(so);
-       }
+       soreference(so);
+       so_pru_aborta(so);
 }
 
 void
 soabort_oncpu(struct socket *so)
 {
-       if ((so->so_state & SS_ABORTING) == 0) {
-               so->so_state |= SS_ABORTING;
-               so_pru_abort_oncpu(so);
-       }
+       soreference(so);
+       so_pru_abort_oncpu(so);
 }
 
 int
@@ -436,12 +449,11 @@ soaccept(struct socket *so, struct sockaddr **nam)
 {
        int error;
 
-       crit_enter();
        if ((so->so_state & SS_NOFDREF) == 0)
                panic("soaccept: !NOFDREF");
-       so->so_state &= ~SS_NOFDREF;
+       soreference(so);                /* create ref */
+       soclrstate(so, SS_NOFDREF);     /* owned by lack of SS_NOFDREF */
        error = so_pru_accept(so, nam);
-       crit_exit();
        return (error);
 }
 
@@ -452,7 +464,6 @@ soconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
 
        if (so->so_options & SO_ACCEPTCONN)
                return (EOPNOTSUPP);
-       crit_enter();
        /*
         * If protocol is connection-based, can only connect once.
         * Otherwise, if connected, try to disconnect first.
@@ -471,7 +482,6 @@ soconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
                so->so_error = 0;
                error = so_pru_connect(so, nam, td);
        }
-       crit_exit();
        return (error);
 }
 
@@ -480,9 +490,7 @@ soconnect2(struct socket *so1, struct socket *so2)
 {
        int error;
 
-       crit_enter();
        error = so_pru_connect2(so1, so2);
-       crit_exit();
        return (error);
 }
 
@@ -491,7 +499,6 @@ sodisconnect(struct socket *so)
 {
        int error;
 
-       crit_enter();
        if ((so->so_state & SS_ISCONNECTED) == 0) {
                error = ENOTCONN;
                goto bad;
@@ -502,7 +509,6 @@ sodisconnect(struct socket *so)
        }
        error = so_pru_disconnect(so);
 bad:
-       crit_exit();
        return (error);
 }
 
@@ -568,7 +574,7 @@ sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
                td->td_lwp->lwp_ru.ru_msgsnd++;
        if (control)
                clen = control->m_len;
-#define        gotoerr(errcode)        { error = errcode; crit_exit(); goto release; }
+#define        gotoerr(errcode)        { error = errcode; goto release; }
 
 restart:
        error = ssb_lock(&so->so_snd, SBLOCKWAIT(flags));
@@ -576,13 +582,11 @@ restart:
                goto out;
 
        do {
-               crit_enter();
                if (so->so_state & SS_CANTSENDMORE)
                        gotoerr(EPIPE);
                if (so->so_error) {
                        error = so->so_error;
                        so->so_error = 0;
-                       crit_exit();
                        goto release;
                }
                if ((so->so_state & SS_ISCONNECTED) == 0) {
@@ -614,12 +618,10 @@ restart:
                                gotoerr(EWOULDBLOCK);
                        ssb_unlock(&so->so_snd);
                        error = ssb_wait(&so->so_snd);
-                       crit_exit();
                        if (error)
                                goto out;
                        goto restart;
                }
-               crit_exit();
                mp = &top;
                space -= clen;
                do {
@@ -682,7 +684,6 @@ restart:
                    } else {
                            pru_flags = 0;
                    }
-                   crit_enter();
                    /*
                     * XXX all the SS_CANTSENDMORE checks previously
                     * done could be out of date.  We could have recieved
@@ -693,7 +694,6 @@ restart:
                     * also happens.  We must rethink this.
                     */
                    error = so_pru_send(so, pru_flags, top, addr, control, td);
-                   crit_exit();
                    if (dontroute)
                            so->so_options &= ~SO_DONTROUTE;
                    clen = 0;
@@ -749,13 +749,11 @@ restart:
        if (error)
                goto out;
 
-       crit_enter();
        if (so->so_state & SS_CANTSENDMORE)
                gotoerr(EPIPE);
        if (so->so_error) {
                error = so->so_error;
                so->so_error = 0;
-               crit_exit();
                goto release;
        }
        if (!(so->so_state & SS_ISCONNECTED) && addr == NULL)
@@ -768,12 +766,10 @@ restart:
                        gotoerr(EWOULDBLOCK);
                ssb_unlock(&so->so_snd);
                error = ssb_wait(&so->so_snd);
-               crit_exit();
                if (error)
                        goto out;
                goto restart;
        }
-       crit_exit();
 
        if (uio) {
                top = m_uiomove(uio);
@@ -801,15 +797,16 @@ out:
 
 /*
  * Implement receive operations on a socket.
+ *
  * We depend on the way that records are added to the signalsockbuf
  * by sbappend*.  In particular, each record (mbufs linked through m_next)
  * must begin with an address if the protocol so specifies,
  * followed by an optional mbuf or mbufs containing ancillary data,
  * and then zero or more mbufs of data.
- * In order to avoid blocking network interrupts for the entire time here,
- * we exit the critical section while doing the actual copy to user space.
- * Although the signalsockbuf is locked, new data may still be appended,
- * and thus we must maintain consistency of the signalsockbuf during that time.
+ *
+ * Although the signalsockbuf is locked, new data may still be appended.
+ * A token inside the ssb_lock deals with MP issues and still allows
+ * the network to access the socket if we block in a uio.
  *
  * The caller may receive the data as a single mbuf chain by supplying
  * an mbuf **mp0 for use in returning the chain.  The uio is then used
@@ -872,7 +869,6 @@ bad:
                so_pru_rcvd(so, 0);
 
 restart:
-       crit_enter();
        error = ssb_lock(&so->so_rcv, SBLOCKWAIT(flags));
        if (error)
                goto done;
@@ -930,7 +926,6 @@ restart:
                error = ssb_wait(&so->so_rcv);
                if (error)
                        goto done;
-               crit_exit();
                goto restart;
        }
 dontblock:
@@ -1025,7 +1020,7 @@ dontblock:
                else
                    KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
                        ("receive 3"));
-               so->so_state &= ~SS_RCVATMARK;
+               soclrstate(so, SS_RCVATMARK);
                len = (resid > INT_MAX) ? INT_MAX : resid;
                if (so->so_oobmark && len > so->so_oobmark - offset)
                        len = so->so_oobmark - offset;
@@ -1038,11 +1033,9 @@ dontblock:
                 * with the resid here either way.
                 */
                if (uio) {
-                       crit_exit();
                        uio->uio_resid = resid;
                        error = uiomove(mtod(m, caddr_t) + moff, len, uio);
                        resid = uio->uio_resid;
-                       crit_enter();
                        if (error)
                                goto release;
                } else {
@@ -1089,7 +1082,7 @@ dontblock:
                        if ((flags & MSG_PEEK) == 0) {
                                so->so_oobmark -= len;
                                if (so->so_oobmark == 0) {
-                                       so->so_state |= SS_RCVATMARK;
+                                       sosetstate(so, SS_RCVATMARK);
                                        break;
                                }
                        } else {
@@ -1150,7 +1143,6 @@ dontblock:
        if (orig_resid == resid && orig_resid &&
            (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
                ssb_unlock(&so->so_rcv);
-               crit_exit();
                goto restart;
        }
 
@@ -1159,7 +1151,6 @@ dontblock:
 release:
        ssb_unlock(&so->so_rcv);
 done:
-       crit_exit();
        if (free_chain)
                m_freem(free_chain);
        return (error);
@@ -1786,7 +1777,7 @@ filt_soread(struct knote *kn, long hint)
        if (kn->kn_sfflags & NOTE_LOWAT)
                return (kn->kn_data >= kn->kn_sdata);
        return ((kn->kn_data >= so->so_rcv.ssb_lowat) ||
-           !TAILQ_EMPTY(&so->so_comp));
+               !TAILQ_EMPTY(&so->so_comp));
 }
 
 static void
index 4ad52b7..4369da5 100644 (file)
@@ -57,6 +57,7 @@
 
 #include <sys/thread2.h>
 #include <sys/msgport2.h>
+#include <sys/socketvar2.h>
 
 int    maxsockets;
 
@@ -152,6 +153,7 @@ _ssb_lock(struct signalsockbuf *ssb)
                } else {
                        if (atomic_cmpset_int(&ssb->ssb_flags, flags,
                                              flags | SSB_LOCK)) {
+                               lwkt_gettoken(&ssb->ssb_token);
                                error = 0;
                                break;
                        }
@@ -212,8 +214,8 @@ ssbtoxsockbuf(struct signalsockbuf *ssb, struct xsockbuf *xsb)
 void
 soisconnecting(struct socket *so)
 {
-       so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
-       so->so_state |= SS_ISCONNECTING;
+       soclrstate(so, SS_ISCONNECTED | SS_ISDISCONNECTING);
+       sosetstate(so, SS_ISCONNECTING);
 }
 
 void
@@ -221,8 +223,8 @@ soisconnected(struct socket *so)
 {
        struct socket *head = so->so_head;
 
-       so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
-       so->so_state |= SS_ISCONNECTED;
+       soclrstate(so, SS_ISCONNECTING | SS_ISDISCONNECTING | SS_ISCONFIRMING);
+       sosetstate(so, SS_ISCONNECTED);
        if (head && (so->so_state & SS_INCOMP)) {
                if ((so->so_options & SO_ACCEPTFILTER) != 0) {
                        so->so_upcall = head->so_accf->so_accept_filter->accf_callback;
@@ -232,12 +234,19 @@ soisconnected(struct socket *so)
                        so->so_upcall(so, so->so_upcallarg, 0);
                        return;
                }
+
+               /*
+                * Listen socket are not per-cpu.
+                */
+               lwkt_gettoken(&head->so_rcv.ssb_token);
                TAILQ_REMOVE(&head->so_incomp, so, so_list);
                head->so_incqlen--;
-               so->so_state &= ~SS_INCOMP;
+               soclrstate(so, SS_INCOMP);
                TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
                head->so_qlen++;
-               so->so_state |= SS_COMP;
+               sosetstate(so, SS_COMP);
+               lwkt_reltoken(&head->so_rcv.ssb_token);
+
                sorwakeup(head);
                wakeup_one(&head->so_timeo);
        } else {
@@ -250,8 +259,8 @@ soisconnected(struct socket *so)
 void
 soisdisconnecting(struct socket *so)
 {
-       so->so_state &= ~SS_ISCONNECTING;
-       so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
+       soclrstate(so, SS_ISCONNECTING);
+       sosetstate(so, SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE);
        wakeup((caddr_t)&so->so_timeo);
        sowwakeup(so);
        sorwakeup(so);
@@ -260,8 +269,8 @@ soisdisconnecting(struct socket *so)
 void
 soisdisconnected(struct socket *so)
 {
-       so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
-       so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
+       soclrstate(so, SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
+       sosetstate(so, SS_CANTRCVMORE | SS_CANTSENDMORE | SS_ISDISCONNECTED);
        wakeup((caddr_t)&so->so_timeo);
        sbdrop(&so->so_snd.sb, so->so_snd.ssb_cc);
        sowwakeup(so);
@@ -271,15 +280,15 @@ soisdisconnected(struct socket *so)
 void
 soisreconnecting(struct socket *so)
 {
-        so->so_state &= ~(SS_ISDISCONNECTING|SS_ISDISCONNECTED|SS_CANTRCVMORE|
-                       SS_CANTSENDMORE);
-       so->so_state |= SS_ISCONNECTING;
+        soclrstate(so, SS_ISDISCONNECTING | SS_ISDISCONNECTED |
+                      SS_CANTRCVMORE | SS_CANTSENDMORE);
+       sosetstate(so, SS_ISCONNECTING);
 }
 
 void
 soisreconnected(struct socket *so)
 {
-       so->so_state &= ~(SS_ISDISCONNECTED|SS_CANTRCVMORE|SS_CANTSENDMORE);
+       soclrstate(so, SS_ISDISCONNECTED | SS_CANTRCVMORE | SS_CANTSENDMORE);
        soisconnected(so);
 }
 
@@ -301,6 +310,9 @@ sosetport(struct socket *so, lwkt_port_t port)
  * then we allocate a new structure, propoerly linked into the
  * data structure of the original socket, and return this.
  * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
+ *
+ * The new socket is returned with one ref and so_pcb assigned.
+ * The reference is implied by so_pcb.
  */
 struct socket *
 sonewconn(struct socket *head, int connstatus)
@@ -320,18 +332,31 @@ sonewconn(struct socket *head, int connstatus)
        so->so_type = head->so_type;
        so->so_options = head->so_options &~ SO_ACCEPTCONN;
        so->so_linger = head->so_linger;
+
+       /*
+        * NOTE: Clearing NOFDREF implies referencing the so with
+        *       soreference().
+        */
        so->so_state = head->so_state | SS_NOFDREF;
        so->so_proto = head->so_proto;
        so->so_cred = crhold(head->so_cred);
        ai.sb_rlimit = NULL;
        ai.p_ucred = NULL;
        ai.fd_rdir = NULL;              /* jail code cruft XXX JH */
-       if (soreserve(so, head->so_snd.ssb_hiwat, head->so_rcv.ssb_hiwat, NULL) ||
-           /* Directly call function since we're already at protocol level. */
+
+       /*
+        * Reserve space and call pru_attach.  We can directl call the
+        * function since we're already in the protocol thread.
+        */
+       if (soreserve(so, head->so_snd.ssb_hiwat,
+                     head->so_rcv.ssb_hiwat, NULL) ||
            (*so->so_proto->pr_usrreqs->pru_attach)(so, 0, &ai)) {
-               sodealloc(so);
+               so->so_head = NULL;
+               sofree(so);             /* remove implied pcb ref */
                return (NULL);
        }
+       KKASSERT(so->so_refs == 2);     /* attach + our base ref */
+       sofree(so);
        KKASSERT(so->so_port != NULL);
        so->so_rcv.ssb_lowat = head->so_rcv.ssb_lowat;
        so->so_snd.ssb_lowat = head->so_snd.ssb_lowat;
@@ -341,27 +366,29 @@ sonewconn(struct socket *head, int connstatus)
                                (SSB_AUTOSIZE | SSB_AUTOLOWAT);
        so->so_snd.ssb_flags |= head->so_snd.ssb_flags &
                                (SSB_AUTOSIZE | SSB_AUTOLOWAT);
+       lwkt_gettoken(&head->so_rcv.ssb_token);
        if (connstatus) {
                TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
-               so->so_state |= SS_COMP;
+               sosetstate(so, SS_COMP);
                head->so_qlen++;
        } else {
                if (head->so_incqlen > head->so_qlimit) {
                        sp = TAILQ_FIRST(&head->so_incomp);
                        TAILQ_REMOVE(&head->so_incomp, sp, so_list);
                        head->so_incqlen--;
-                       sp->so_state &= ~SS_INCOMP;
+                       soclrstate(sp, SS_INCOMP);
                        sp->so_head = NULL;
                        soaborta(sp);
                }
                TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
-               so->so_state |= SS_INCOMP;
+               sosetstate(so, SS_INCOMP);
                head->so_incqlen++;
        }
+       lwkt_reltoken(&head->so_rcv.ssb_token);
        if (connstatus) {
                sorwakeup(head);
                wakeup((caddr_t)&head->so_timeo);
-               so->so_state |= connstatus;
+               sosetstate(so, connstatus);
        }
        return (so);
 }
@@ -378,14 +405,14 @@ sonewconn(struct socket *head, int connstatus)
 void
 socantsendmore(struct socket *so)
 {
-       so->so_state |= SS_CANTSENDMORE;
+       sosetstate(so, SS_CANTSENDMORE);
        sowwakeup(so);
 }
 
 void
 socantrcvmore(struct socket *so)
 {
-       so->so_state |= SS_CANTRCVMORE;
+       sosetstate(so, SS_CANTRCVMORE);
        sorwakeup(so);
 }
 
index e378300..192c5cc 100644 (file)
@@ -225,6 +225,7 @@ soaccept_predicate(struct netmsg *msg0)
                msg->nm_netmsg.nm_lmsg.ms_error = head->so_error;
                return (TRUE);
        }
+       lwkt_gettoken(&head->so_rcv.ssb_token);
        if (!TAILQ_EMPTY(&head->so_comp)) {
                /* Abuse nm_so field as copy in/copy out parameter. XXX JH */
                msg->nm_so = TAILQ_FIRST(&head->so_comp);
@@ -232,8 +233,10 @@ soaccept_predicate(struct netmsg *msg0)
                head->so_qlen--;
 
                msg->nm_netmsg.nm_lmsg.ms_error = 0;
+               lwkt_reltoken(&head->so_rcv.ssb_token);
                return (TRUE);
        }
+       lwkt_reltoken(&head->so_rcv.ssb_token);
        if (head->so_state & SS_CANTRCVMORE) {
                msg->nm_netmsg.nm_lmsg.ms_error = ECONNABORTED;
                return (TRUE);
@@ -313,7 +316,7 @@ kern_accept(int s, int fflags, struct sockaddr **name, int *namelen, int *res)
        /* connection has been removed from the listen queue */
        KNOTE(&head->so_rcv.ssb_kq.ki_note, 0);
 
-       so->so_state &= ~SS_COMP;
+       soclrstate(so, SS_COMP);
        so->so_head = NULL;
        if (head->so_sigio != NULL)
                fsetown(fgetown(head->so_sigio), &so->so_sigio);
@@ -517,7 +520,7 @@ kern_connect(int s, int fflags, struct sockaddr *sa)
        }
 bad:
        if (!interrupted)
-               so->so_state &= ~SS_ISCONNECTING;
+               soclrstate(so, SS_ISCONNECTING);
        if (error == ERESTART)
                error = EINTR;
 done:
@@ -1880,8 +1883,8 @@ sys_sctp_peeloff(struct sctp_peeloff_args *uap)
                 */
                goto noconnection;
        }
-       so->so_state &= ~SS_COMP;
-       so->so_state &= ~SS_NOFDREF;
+       soreference(so);                        /* reference needed */
+       soclrstate(so, SS_NOFDREF | SS_COMP);   /* when clearing NOFDREF */
        so->so_head = NULL;
        if (head->so_sigio != NULL)
                fsetown(fgetown(head->so_sigio), &so->so_sigio);
index 5ec5ea5..17e7719 100644 (file)
 #include <sys/un.h>
 #include <sys/unpcb.h>
 #include <sys/vnode.h>
+
 #include <sys/file2.h>
 #include <sys/spinlock2.h>
-
+#include <sys/socketvar2.h>
 
 static MALLOC_DEFINE(M_UNPCB, "unpcb", "unpcb struct");
 static unp_gen_t unp_gencnt;
@@ -66,6 +67,8 @@ static        u_int unp_count;
 
 static struct unp_head unp_shead, unp_dhead;
 
+static struct lwkt_token unp_token = LWKT_TOKEN_MP_INITIALIZER(unp_token);
+
 /*
  * Unix communications domain.
  *
@@ -100,26 +103,41 @@ static int     unp_internalize (struct mbuf *, struct thread *);
 static int     unp_listen (struct unpcb *, struct thread *);
 static void    unp_fp_externalize(struct lwp *lp, struct file *fp, int fd);
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 uipc_abort(struct socket *so)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       unp_drop(unp, ECONNABORTED);
-       unp_detach(unp);
-       sofree(so);
-       return 0;
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp) {
+               unp_drop(unp, ECONNABORTED);
+               unp_detach(unp);
+               error = 0;
+       } else {
+               error = EINVAL;
+       }
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_accept(struct socket *so, struct sockaddr **nam)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
 
-       if (unp == NULL)
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp == NULL) {
+               lwkt_reltoken(&unp_token);
                return EINVAL;
+       }
 
        /*
         * Pass back name of connected socket,
@@ -131,48 +149,76 @@ uipc_accept(struct socket *so, struct sockaddr **nam)
        } else {
                *nam = dup_sockaddr((struct sockaddr *)&sun_noname);
        }
+       lwkt_reltoken(&unp_token);
        return 0;
 }
 
 static int
 uipc_attach(struct socket *so, int proto, struct pru_attach_info *ai)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
+
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp)
+               error = EISCONN;
+       else
+               error = unp_attach(so, ai);
+       lwkt_reltoken(&unp_token);
 
-       if (unp != NULL)
-               return EISCONN;
-       return unp_attach(so, ai);
+       return error;
 }
 
 static int
 uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       return unp_bind(unp, nam, td);
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp)
+               error = unp_bind(unp, nam, td);
+       else
+               error = EINVAL;
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       return unp_connect(so, nam, td);
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp)
+               error = unp_connect(so, nam, td);
+       else
+               error = EINVAL;
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_connect2(struct socket *so1, struct socket *so2)
 {
-       struct unpcb *unp = so1->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
+       lwkt_gettoken(&unp_token);
+       unp = so1->so_pcb;
+       if (unp)
+               error = unp_connect2(so1, so2);
+       else
+               error = EINVAL;
+       lwkt_reltoken(&unp_token);
 
-       return unp_connect2(so1, so2);
+       return error;
 }
 
 /* control is EOPNOTSUPP */
@@ -180,69 +226,102 @@ uipc_connect2(struct socket *so1, struct socket *so2)
 static int
 uipc_detach(struct socket *so)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp) {
+               unp_detach(unp);
+               error = 0;
+       } else {
+               error = EINVAL;
+       }
+       lwkt_reltoken(&unp_token);
 
-       unp_detach(unp);
-       return 0;
+       return error;
 }
 
 static int
 uipc_disconnect(struct socket *so)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       unp_disconnect(unp);
-       return 0;
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp) {
+               unp_disconnect(unp);
+               error = 0;
+       } else {
+               error = EINVAL;
+       }
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_listen(struct socket *so, struct thread *td)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
        if (unp == NULL || unp->unp_vnode == NULL)
-               return EINVAL;
-       return unp_listen(unp, td);
+               error = EINVAL;
+       else
+               error = unp_listen(unp, td);
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_peeraddr(struct socket *so, struct sockaddr **nam)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       if (unp->unp_conn && unp->unp_conn->unp_addr)
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp == NULL) {
+               error = EINVAL;
+       } else if (unp->unp_conn && unp->unp_conn->unp_addr) {
                *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr);
-       else {
+               error = 0;
+       } else {
                /*
                 * XXX: It seems that this test always fails even when
                 * connection is established.  So, this else clause is
                 * added as workaround to return PF_LOCAL sockaddr.
                 */
                *nam = dup_sockaddr((struct sockaddr *)&sun_noname);
+               error = 0;
        }
-       return 0;
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_rcvd(struct socket *so, int flags)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
        struct socket *so2;
 
-       if (unp == NULL)
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp == NULL) {
+               lwkt_reltoken(&unp_token);
                return EINVAL;
+       }
+
        switch (so->so_type) {
        case SOCK_DGRAM:
                panic("uipc_rcvd DGRAM?");
                /*NOTREACHED*/
-
        case SOCK_STREAM:
        case SOCK_SEQPACKET:
                if (unp->unp_conn == NULL)
@@ -260,10 +339,12 @@ uipc_rcvd(struct socket *so, int flags)
                        sowwakeup(so2);
                }
                break;
-
        default:
                panic("uipc_rcvd unknown socktype");
+               /*NOTREACHED*/
        }
+       lwkt_reltoken(&unp_token);
+
        return 0;
 }
 
@@ -273,10 +354,13 @@ static int
 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
          struct mbuf *control, struct thread *td)
 {
-       int error = 0;
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
        struct socket *so2;
+       int error = 0;
 
+       lwkt_gettoken(&unp_token);
+
+       unp = so->so_pcb;
        if (unp == NULL) {
                error = EINVAL;
                goto release;
@@ -397,6 +481,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
                unp_dispose(control);
 
 release:
+       lwkt_reltoken(&unp_token);
+
        if (control)
                m_freem(control);
        if (m)
@@ -410,10 +496,14 @@ release:
 static int
 uipc_sense(struct socket *so, struct stat *sb)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
 
-       if (unp == NULL)
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp == NULL) {
+               lwkt_reltoken(&unp_token);
                return EINVAL;
+       }
        sb->st_blksize = so->so_snd.ssb_hiwat;
        sb->st_dev = NOUDEV;
        if (unp->unp_ino == 0) {        /* make up a non-zero inode number */
@@ -422,31 +512,49 @@ uipc_sense(struct socket *so, struct stat *sb)
                spin_unlock(&unp_ino_spin);
        }
        sb->st_ino = unp->unp_ino;
+       lwkt_reltoken(&unp_token);
+
        return (0);
 }
 
 static int
 uipc_shutdown(struct socket *so)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       socantsendmore(so);
-       unp_shutdown(unp);
-       return 0;
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp) {
+               socantsendmore(so);
+               unp_shutdown(unp);
+               error = 0;
+       } else {
+               error = EINVAL;
+       }
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 static int
 uipc_sockaddr(struct socket *so, struct sockaddr **nam)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
+       int error;
 
-       if (unp == NULL)
-               return EINVAL;
-       if (unp->unp_addr)
-               *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr);
-       return 0;
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (unp) {
+               if (unp->unp_addr)
+                       *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr);
+               error = 0;
+       } else {
+               error = EINVAL;
+       }
+       lwkt_reltoken(&unp_token);
+
+       return error;
 }
 
 struct pr_usrreqs uipc_usrreqs = {
@@ -474,9 +582,12 @@ struct pr_usrreqs uipc_usrreqs = {
 int
 uipc_ctloutput(struct socket *so, struct sockopt *sopt)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
        int error = 0;
 
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+
        switch (sopt->sopt_dir) {
        case SOPT_GET:
                switch (sopt->sopt_name) {
@@ -503,6 +614,8 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
                error = EOPNOTSUPP;
                break;
        }
+       lwkt_reltoken(&unp_token);
+
        return (error);
 }
        
@@ -551,6 +664,7 @@ unp_attach(struct socket *so, struct pru_attach_info *ai)
        struct unpcb *unp;
        int error;
 
+       lwkt_gettoken(&unp_token);
        if (so->so_snd.ssb_hiwat == 0 || so->so_rcv.ssb_hiwat == 0) {
                switch (so->so_type) {
 
@@ -569,11 +683,13 @@ unp_attach(struct socket *so, struct pru_attach_info *ai)
                        panic("unp_attach");
                }
                if (error)
-                       return (error);
+                       goto failed;
        }
        unp = kmalloc(sizeof(*unp), M_UNPCB, M_NOWAIT|M_ZERO);
-       if (unp == NULL)
-               return (ENOBUFS);
+       if (unp == NULL) {
+               error = ENOBUFS;
+               goto failed;
+       }
        unp->unp_gencnt = ++unp_gencnt;
        unp_count++;
        LIST_INIT(&unp->unp_refs);
@@ -582,13 +698,21 @@ unp_attach(struct socket *so, struct pru_attach_info *ai)
        LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
                         : &unp_shead, unp, unp_link);
        so->so_pcb = (caddr_t)unp;
+       soreference(so);
        so->so_port = sync_soport(so, NULL, NULL);
-       return (0);
+       error = 0;
+failed:
+       lwkt_reltoken(&unp_token);
+       return error;
 }
 
 static void
 unp_detach(struct unpcb *unp)
 {
+       struct socket *so;
+
+       lwkt_gettoken(&unp_token);
+
        LIST_REMOVE(unp, unp_link);
        unp->unp_gencnt = ++unp_gencnt;
        --unp_count;
@@ -602,7 +726,12 @@ unp_detach(struct unpcb *unp)
        while (!LIST_EMPTY(&unp->unp_refs))
                unp_drop(LIST_FIRST(&unp->unp_refs), ECONNRESET);
        soisdisconnected(unp->unp_socket);
-       unp->unp_socket->so_pcb = NULL;
+       so = unp->unp_socket;
+       soreference(so);        /* for delayed sorflush */
+       so->so_pcb = NULL;
+       unp->unp_socket = NULL;
+       sofree(so);             /* remove pcb ref */
+
        if (unp_rights) {
                /*
                 * Normally the receive buffer is flushed later,
@@ -611,9 +740,12 @@ unp_detach(struct unpcb *unp)
                 * of those descriptor references after the garbage collector
                 * gets them (resulting in a "panic: closef: count < 0").
                 */
-               sorflush(unp->unp_socket);
+               sorflush(so);
                unp_gc();
        }
+       sofree(so);
+       lwkt_reltoken(&unp_token);
+
        if (unp->unp_addr)
                kfree(unp->unp_addr, M_SONAME);
        kfree(unp, M_UNPCB);
@@ -630,11 +762,16 @@ unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
        struct nlookupdata nd;
        char buf[SOCK_MAXADDRLEN];
 
-       if (unp->unp_vnode != NULL)
-               return (EINVAL);
+       lwkt_gettoken(&unp_token);
+       if (unp->unp_vnode != NULL) {
+               error = EINVAL;
+               goto failed;
+       }
        namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
-       if (namelen <= 0)
-               return (EINVAL);
+       if (namelen <= 0) {
+               error = EINVAL;
+               goto failed;
+       }
        strncpy(buf, soun->sun_path, namelen);
        buf[namelen] = 0;       /* null-terminate the string */
        error = nlookup_init(&nd, buf, UIO_SYSSPACE,
@@ -658,6 +795,8 @@ unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
        }
 done:
        nlookup_done(&nd);
+failed:
+       lwkt_reltoken(&unp_token);
        return (error);
 }
 
@@ -673,11 +812,13 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
        struct nlookupdata nd;
        char buf[SOCK_MAXADDRLEN];
 
-       KKASSERT(p);
+       lwkt_gettoken(&unp_token);
 
        len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
-       if (len <= 0)
-               return EINVAL;
+       if (len <= 0) {
+               error = EINVAL;
+               goto failed;
+       }
        strncpy(buf, soun->sun_path, len);
        buf[len] = 0;
 
@@ -689,7 +830,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
                error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
        nlookup_done(&nd);
        if (error)
-               return (error);
+               goto failed;
 
        if (vp->v_type != VSOCK) {
                error = ENOTSOCK;
@@ -747,21 +888,27 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
        error = unp_connect2(so, so2);
 bad:
        vput(vp);
+failed:
+       lwkt_reltoken(&unp_token);
        return (error);
 }
 
 int
 unp_connect2(struct socket *so, struct socket *so2)
 {
-       struct unpcb *unp = so->so_pcb;
+       struct unpcb *unp;
        struct unpcb *unp2;
 
-       if (so2->so_type != so->so_type)
+       lwkt_gettoken(&unp_token);
+       unp = so->so_pcb;
+       if (so2->so_type != so->so_type) {
+               lwkt_reltoken(&unp_token);
                return (EPROTOTYPE);
+       }
        unp2 = so2->so_pcb;
        unp->unp_conn = unp2;
-       switch (so->so_type) {
 
+       switch (so->so_type) {
        case SOCK_DGRAM:
                LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
                soisconnected(so);
@@ -777,23 +924,29 @@ unp_connect2(struct socket *so, struct socket *so2)
        default:
                panic("unp_connect2");
        }
+       lwkt_reltoken(&unp_token);
        return (0);
 }
 
 static void
 unp_disconnect(struct unpcb *unp)
 {
-       struct unpcb *unp2 = unp->unp_conn;
+       struct unpcb *unp2;
 
-       if (unp2 == NULL)
+       lwkt_gettoken(&unp_token);
+
+       unp2 = unp->unp_conn;
+       if (unp2 == NULL) {
+               lwkt_reltoken(&unp_token);
                return;
+       }
 
        unp->unp_conn = NULL;
 
        switch (unp->unp_socket->so_type) {
        case SOCK_DGRAM:
                LIST_REMOVE(unp, unp_reflink);
-               unp->unp_socket->so_state &= ~SS_ISCONNECTED;
+               soclrstate(unp->unp_socket, SS_ISCONNECTED);
                break;
        case SOCK_STREAM:
        case SOCK_SEQPACKET:
@@ -802,14 +955,16 @@ unp_disconnect(struct unpcb *unp)
                soisdisconnected(unp2->unp_socket);
                break;
        }
+       lwkt_reltoken(&unp_token);
 }
 
 #ifdef notdef
 void
 unp_abort(struct unpcb *unp)
 {
-
+       lwkt_gettoken(&unp_token);
        unp_detach(unp);
+       lwkt_reltoken(&unp_token);
 }
 #endif
 
@@ -854,6 +1009,8 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
        if (req->newptr != NULL)
                return EPERM;
 
+       lwkt_gettoken(&unp_token);
+
        /*
         * OK, now we're committed to doing something.
         */
@@ -892,7 +1049,9 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
                        error = SYSCTL_OUT(req, &xu, sizeof xu);
                }
        }
+       lwkt_reltoken(&unp_token);
        kfree(unp_list, M_TEMP);
+
        return error;
 }
 
@@ -931,7 +1090,8 @@ unp_drop(struct unpcb *unp, int err)
 void
 unp_drain(void)
 {
-
+       lwkt_gettoken(&unp_token);
+       lwkt_reltoken(&unp_token);
 }
 #endif
 
@@ -950,6 +1110,8 @@ unp_externalize(struct mbuf *rights)
                / sizeof (struct file *);
        int f;
 
+       lwkt_gettoken(&unp_token);
+
        /*
         * if the new FD's will not fit, then we free them all
         */
@@ -964,6 +1126,7 @@ unp_externalize(struct mbuf *rights)
                        *rp++ = 0;
                        unp_discard(fp, NULL);
                }
+               lwkt_reltoken(&unp_token);
                return (EMSGSIZE);
        }
 
@@ -1006,6 +1169,8 @@ unp_externalize(struct mbuf *rights)
         */
        cm->cmsg_len = CMSG_LEN(newfds * sizeof(int));
        rights->m_len = cm->cmsg_len;
+
+       lwkt_reltoken(&unp_token);
        return (0);
 }
 
@@ -1015,6 +1180,8 @@ unp_fp_externalize(struct lwp *lp, struct file *fp, int fd)
        struct file *fx;
        int error;
 
+       lwkt_gettoken(&unp_token);
+
        if (lp) {
                KKASSERT(fd >= 0);
                if (fp->f_flag & FREVOKED) {
@@ -1035,6 +1202,8 @@ unp_fp_externalize(struct lwp *lp, struct file *fp, int fd)
        unp_rights--;
        spin_unlock(&unp_spin);
        fdrop(fp);
+
+       lwkt_reltoken(&unp_token);
 }
 
 
@@ -1058,13 +1227,17 @@ unp_internalize(struct mbuf *control, struct thread *td)
        struct cmsgcred *cmcred;
        int oldfds;
        u_int newlen;
+       int error;
 
        KKASSERT(p);
+       lwkt_gettoken(&unp_token);
+
        fdescp = p->p_fd;
        if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) ||
            cm->cmsg_level != SOL_SOCKET ||
            CMSG_ALIGN(cm->cmsg_len) != control->m_len) {
-               return (EINVAL);
+               error = EINVAL;
+               goto done;
        }
 
        /*
@@ -1080,15 +1253,18 @@ unp_internalize(struct mbuf *control, struct thread *td)
                                                        CMGROUP_MAX);
                for (i = 0; i < cmcred->cmcred_ngroups; i++)
                        cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i];
-               return(0);
+               error = 0;
+               goto done;
        }
 
        /*
         * cmsghdr may not be aligned, do not allow calculation(s) to
         * go negative.
         */
-       if (cm->cmsg_len < CMSG_LEN(0))
-               return(EINVAL);
+       if (cm->cmsg_len < CMSG_LEN(0)) {
+               error = EINVAL;
+               goto done;
+       }
 
        oldfds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof (int);
 
@@ -1100,10 +1276,14 @@ unp_internalize(struct mbuf *control, struct thread *td)
        for (i = 0; i < oldfds; i++) {
                fd = *fdp++;
                if ((unsigned)fd >= fdescp->fd_nfiles ||
-                   fdescp->fd_files[fd].fp == NULL)
-                       return (EBADF);
-               if (fdescp->fd_files[fd].fp->f_type == DTYPE_KQUEUE)
-                       return (EOPNOTSUPP);
+                   fdescp->fd_files[fd].fp == NULL) {
+                       error = EBADF;
+                       goto done;
+               }
+               if (fdescp->fd_files[fd].fp->f_type == DTYPE_KQUEUE) {
+                       error = EOPNOTSUPP;
+                       goto done;
+               }
        }
        /*
         * Now replace the integer FDs with pointers to
@@ -1112,14 +1292,20 @@ unp_internalize(struct mbuf *control, struct thread *td)
         * enough, return E2BIG.
         */
        newlen = CMSG_LEN(oldfds * sizeof(struct file *));
-       if (newlen > MCLBYTES)
-               return (E2BIG);
+       if (newlen > MCLBYTES) {
+               error = E2BIG;
+               goto done;
+       }
        if (newlen - control->m_len > M_TRAILINGSPACE(control)) {
-               if (control->m_flags & M_EXT)
-                       return (E2BIG);
+               if (control->m_flags & M_EXT) {
+                       error = E2BIG;
+                       goto done;
+               }
                MCLGET(control, MB_WAIT);
-               if (!(control->m_flags & M_EXT))
-                       return (ENOBUFS);
+               if (!(control->m_flags & M_EXT)) {
+                       error = ENOBUFS;
+                       goto done;
+               }
 
                /* copy the data to the cluster */
                memcpy(mtod(control, char *), cm, cm->cmsg_len);
@@ -1166,7 +1352,10 @@ unp_internalize(struct mbuf *control, struct thread *td)
                        spin_unlock(&unp_spin);
                }
        }
-       return (0);
+       error = 0;
+done:
+       lwkt_reltoken(&unp_token);
+       return error;
 }
 
 /*
@@ -1201,6 +1390,8 @@ unp_gc(void)
        unp_gcing = TRUE;
        spin_unlock(&unp_spin);
 
+       lwkt_gettoken(&unp_token);
+
        /* 
         * before going through all this, set all FDs to 
         * be NOT defered and NOT externally accessible
@@ -1271,6 +1462,9 @@ unp_gc(void)
                for (i = info.index, fpp = info.extra_ref; --i >= 0; ++fpp)
                        closef(*fpp, NULL);
        } while (info.index == info.maxindex);
+
+       lwkt_reltoken(&unp_token);
+
        kfree((caddr_t)info.extra_ref, M_FILE);
        unp_gcing = FALSE;
 }
@@ -1416,6 +1610,7 @@ unp_revoke_gc(struct file *fx)
        struct unp_revoke_gc_info info;
        int i;
 
+       lwkt_gettoken(&unp_token);
        info.fx = fx;
        do {
                info.fcount = 0;
@@ -1423,6 +1618,7 @@ unp_revoke_gc(struct file *fx)
                for (i = 0; i < info.fcount; ++i)
                        unp_fp_externalize(NULL, info.fary[i], -1);
        } while (info.fcount == REVOKE_GC_MAXFILES);
+       lwkt_reltoken(&unp_token);
 }
 
 /*
@@ -1505,8 +1701,10 @@ unp_revoke_gc_check(struct file *fps, void *vinfo)
 void
 unp_dispose(struct mbuf *m)
 {
+       lwkt_gettoken(&unp_token);
        if (m)
                unp_scan(m, unp_discard, NULL);
+       lwkt_reltoken(&unp_token);
 }
 
 static int
@@ -1515,8 +1713,10 @@ unp_listen(struct unpcb *unp, struct thread *td)
        struct proc *p = td->td_proc;
 
        KKASSERT(p);
+       lwkt_gettoken(&unp_token);
        cru2x(p->p_ucred, &unp->unp_peercred);
        unp->unp_flags |= UNP_HAVEPCCACHED;
+       lwkt_reltoken(&unp_token);
        return (0);
 }
 
index afc885e..d8bbda1 100644 (file)
@@ -587,7 +587,7 @@ bpfwrite(struct dev_write_args *ap)
                dst.sa_family = pseudo_AF_HDRCMPLT;
 
        netmsg_init(&bmsg.nm_netmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, bpf_output_dispatch);
+                   0, bpf_output_dispatch);
        bmsg.nm_mbuf = m;
        bmsg.nm_ifp = ifp;
        bmsg.nm_dst = &dst;
index a3e4e71..58ca156 100644 (file)
@@ -1830,7 +1830,7 @@ bridge_enqueue(struct ifnet *dst_ifp, struct mbuf *m)
        nmp->nm_packet = m;
        nmp->nm_netmsg.nm_lmsg.u.ms_resultp = dst_ifp;
 
-       lwkt_sendmsg(curnetport, &nmp->nm_netmsg.nm_lmsg);
+       lwkt_sendmsg(ifnet_portfn(mycpu->gd_cpuid), &nmp->nm_netmsg.nm_lmsg);
 }
 
 /*
index 3f6ead0..86f6170 100644 (file)
@@ -253,7 +253,7 @@ ef_inputEII(struct mbuf *m, struct llc* l, u_short ether_type)
        default:
                return (EPROTONOSUPPORT);
        }
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
@@ -272,7 +272,7 @@ ef_inputSNAP(struct mbuf *m, struct llc* l, u_short ether_type)
        default:
                return (EPROTONOSUPPORT);
        }
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
@@ -291,7 +291,7 @@ ef_input8022(struct mbuf *m, struct llc* l, u_short ether_type)
        default:
                return (EPROTONOSUPPORT);
        }
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
@@ -384,7 +384,7 @@ ef_input(struct ifnet *ifp, const struct ether_header *eh, struct mbuf *m)
                        ft, ether_type);
                return (EPROTONOSUPPORT);
        }
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
index 8663d17..d452c49 100644 (file)
@@ -245,9 +245,10 @@ faithoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
        /* XXX do we need more sanity checks? */
 
        m->m_pkthdr.rcvif = ifp;
+       m->m_flags &= ~M_HASH;
        ifp->if_ipackets++;
        ifp->if_ibytes += m->m_pkthdr.len;
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
index c21de80..2c7fb33 100644 (file)
@@ -427,7 +427,8 @@ gif_input(struct mbuf *m, int af, struct ifnet *ifp)
 
        ifp->if_ipackets++;
        ifp->if_ibytes += m->m_pkthdr.len;
-       netisr_dispatch(isr, m);
+       m->m_flags &= ~M_HASH;
+       netisr_queue(isr, m);
 
        return;
 }
index c1a3988..38002d0 100644 (file)
@@ -171,7 +171,6 @@ struct callout              if_slowtimo_timer;
 int                    if_index = 0;
 struct ifnet           **ifindex2ifnet = NULL;
 static struct thread   ifnet_threads[MAXCPU];
-static int             ifnet_mpsafe_thread = NETMSG_SERVICE_MPSAFE;
 
 #define IFQ_KTR_STRING         "ifq=%p"
 #define IFQ_KTR_ARG_SIZE       (sizeof(void *))
@@ -2689,6 +2688,21 @@ ifnet_sendmsg(struct lwkt_msg *lmsg, int cpu)
        lwkt_sendmsg(ifnet_portfn(cpu), lmsg);
 }
 
+/*
+ * Generic netmsg service loop.  Some protocols may roll their own but all
+ * must do the basic command dispatch function call done here.
+ */
+static void
+ifnet_service_loop(void *arg __unused)
+{
+       struct netmsg *msg;
+
+       while ((msg = lwkt_waitport(&curthread->td_msgport, 0))) {
+               KASSERT(msg->nm_dispatch, ("ifnet_service: badmsg"));
+               msg->nm_dispatch(msg);
+       }
+}
+
 static void
 ifnetinit(void *dummy __unused)
 {
@@ -2697,10 +2711,10 @@ ifnetinit(void *dummy __unused)
        for (i = 0; i < ncpus; ++i) {
                struct thread *thr = &ifnet_threads[i];
 
-               lwkt_create(netmsg_service_loop, &ifnet_mpsafe_thread, NULL,
-                           thr, TDF_NETWORK, i,
-                           "ifnet %d", i);
+               lwkt_create(ifnet_service_loop, NULL, NULL,
+                           thr, TDF_STOPREQ, i, "ifnet %d", i);
                netmsg_service_port_init(&thr->td_msgport);
+               lwkt_schedule(thr);
        }
 }
 
index ffe7c70..f1df178 100644 (file)
@@ -297,7 +297,8 @@ atm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m,
                }
        }
 
-       netisr_dispatch(isr, m);
+       m->m_flags &= ~M_HASH;
+       netisr_queue(isr, m);
 }
 
 /*
index 2b736bc..259af04 100644 (file)
@@ -358,7 +358,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
                 */
                if (bcmp(edst, &ns_thishost, ETHER_ADDR_LEN) == 0) {
                        m->m_pkthdr.rcvif = ifp;
-                       netisr_dispatch(NETISR_NS, m);
+                       netisr_queue(NETISR_NS, m);
                        return (error);
                }
                if (bcmp(edst, &ns_broadhost, ETHER_ADDR_LEN) == 0)
@@ -1035,19 +1035,13 @@ static void
 ether_input_ipifunc(void *arg)
 {
        struct mbuf *m, *next;
-       lwkt_port_t port;
+       lwkt_port_t port = cpu_portfn(mycpu->gd_cpuid);
 
        m = arg;
        do {
                next = m->m_nextpkt;
                m->m_nextpkt = NULL;
-
-               port = m->m_pkthdr.header;
-               m->m_pkthdr.header = NULL;
-
-               lwkt_sendmsg(port,
-               &m->m_hdr.mh_netmsg.nm_netmsg.nm_lmsg);
-
+               lwkt_sendmsg(port, &m->m_hdr.mh_netmsg.nm_netmsg.nm_lmsg);
                m = next;
        } while (m != NULL);
 }
@@ -1062,7 +1056,7 @@ ether_input_dispatch(struct mbuf_chain *chain)
        for (i = 0; i < ncpus; ++i) {
                if (chain[i].mc_head != NULL) {
                        lwkt_send_ipiq(globaldata_find(i),
-                       ether_input_ipifunc, chain[i].mc_head);
+                                      ether_input_ipifunc, chain[i].mc_head);
                }
        }
 #else
@@ -1222,7 +1216,7 @@ post_stats:
 #ifdef INET
        case ETHERTYPE_IP:
                if ((m->m_flags & M_LENCHECKED) == 0) {
-                       if (!ip_lengthcheck(&m))
+                       if (!ip_lengthcheck(&m, 0))
                                return;
                }
                if (ipflow_fastforward(m))
@@ -1361,17 +1355,14 @@ dropanyway:
                return;
        }
 
-       if (!redispatch)
-               netisr_run(isr, m);
-       else
-               netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
 }
 
 /*
  * First we perform any link layer operations, then continue to the
  * upper layers with ether_demux_oncpu().
  */
-void
+static void
 ether_input_oncpu(struct ifnet *ifp, struct mbuf *m)
 {
        if ((ifp->if_flags & (IFF_UP | IFF_MONITOR)) != IFF_UP) {
@@ -1532,48 +1523,24 @@ ether_input_handler(struct netmsg *nmsg)
        ether_input_oncpu(ifp, m);
 }
 
-static __inline void
-ether_init_netpacket(int num, struct mbuf *m)
+/*
+ * Send the packet to the target msgport or queue it into 'chain'.
+ */
+static void
+ether_dispatch(int isr, struct mbuf *m, struct mbuf_chain *chain)
 {
        struct netmsg_packet *pmsg;
 
+       KKASSERT(m->m_flags & M_HASH);
        pmsg = &m->m_hdr.mh_netmsg;
        netmsg_init(&pmsg->nm_netmsg, NULL, &netisr_apanic_rport,
-                   MSGF_MPSAFE, ether_input_handler);
+                   0, ether_input_handler);
        pmsg->nm_packet = m;
-       pmsg->nm_netmsg.nm_lmsg.u.ms_result = num;
-}
-
-static __inline struct lwkt_port *
-ether_mport(int num, struct mbuf **m)
-{
-       if (num == NETISR_MAX) {
-               /*
-                * All packets whose target msgports can't be
-                * determined here are dispatched to netisr0,
-                * where further dispatching may happen.
-                */
-               return cpu_portfn(0);
-       }
-       return netisr_find_port(num, m);
-}
-
-/*
- * Send the packet to the target msgport or
- * queue it into 'chain'.
- */
-static void
-ether_dispatch(int isr, struct lwkt_port *port, struct mbuf *m,
-              struct mbuf_chain *chain)
-{
-       ether_init_netpacket(isr, m);
+       pmsg->nm_netmsg.nm_lmsg.u.ms_result = isr;
 
        if (chain != NULL) {
+               int cpuid = m->m_pkthdr.hash;
                struct mbuf_chain *c;
-               int cpuid;
-
-               m->m_pkthdr.header = port; /* XXX */
-               cpuid = port->mpu_td->td_gd->gd_cpuid;
 
                c = &chain[cpuid];
                if (c->mc_head == NULL) {
@@ -1584,7 +1551,8 @@ ether_dispatch(int isr, struct lwkt_port *port, struct mbuf *m,
                }
                m->m_nextpkt = NULL;
        } else {
-               lwkt_sendmsg(port, &m->m_hdr.mh_netmsg.nm_netmsg.nm_lmsg);
+               lwkt_sendmsg(cpu_portfn(m->m_pkthdr.hash),
+                            &pmsg->nm_netmsg.nm_lmsg);
        }
 }
 
@@ -1595,13 +1563,10 @@ ether_dispatch(int isr, struct lwkt_port *port, struct mbuf *m,
  * MUST MAKE SURE that there are at least sizeof(struct ether_header)
  * bytes in the first mbuf.
  *
- * We first try to find the target msgport for this ether frame, if
- * there is no target msgport for it, this ether frame is discarded,
- * else we do following processing according to whether 'chain' is
- * NULL or not:
  * - If 'chain' is NULL, this ether frame is sent to the target msgport
  *   immediately.  This situation happens when ether_input_chain is
  *   accessed through ifnet.if_input.
+ *
  * - If 'chain' is not NULL, this ether frame is queued to the 'chain'
  *   bucket indexed by the target msgport's cpuid and the target msgport
  *   is saved in mbuf's m_pkthdr.m_head.  Caller of ether_input_chain
@@ -1613,8 +1578,7 @@ void
 ether_input_chain(struct ifnet *ifp, struct mbuf *m, const struct pktinfo *pi,
                  struct mbuf_chain *chain)
 {
-       struct ether_header *eh, *save_eh, save_eh0;
-       struct lwkt_port *port;
+       struct ether_header *eh;
        uint16_t ether_type;
        int isr;
 
@@ -1654,27 +1618,21 @@ ether_input_chain(struct ifnet *ifp, struct mbuf *m, const struct pktinfo *pi,
                return;
        }
 
+       /*
+        * If the packet has been characterized (pi->pi_netisr / M_HASH)
+        * we can dispatch it immediately without further inspection.
+        */
        if (pi != NULL && (m->m_flags & M_HASH)) {
 #ifdef RSS_DEBUG
                ether_pktinfo_try++;
 #endif
-               /* Try finding the port using the packet info */
-               port = netisr_find_pktinfo_port(pi, m);
-               if (port != NULL) {
+               ether_dispatch(pi->pi_netisr, m, chain);
+
 #ifdef RSS_DEBUG
-                       ether_pktinfo_hit++;
+               ether_pktinfo_hit++;
 #endif
-                       ether_dispatch(pi->pi_netisr, port, m, chain);
-
-                       logether(chain_end, ifp);
-                       return;
-               }
-
-               /*
-                * The packet info does not contain enough
-                * information, we will have to check the
-                * packet content.
-                */
+               logether(chain_end, ifp);
+               return;
        }
 #ifdef RSS_DEBUG
        else if (ifp->if_capenable & IFCAP_RSS) {
@@ -1753,58 +1711,26 @@ ether_input_chain(struct ifnet *ifp, struct mbuf *m, const struct pktinfo *pi,
        default:
                /*
                 * NETISR_MAX is an invalid value; it is chosen to let
-                * ether_mport() know that we are not able to decide
-                * this packet's msgport here.
                 */
                isr = NETISR_MAX;
                break;
        }
 
        /*
-        * If the packet is in contiguous memory, following
-        * m_adj() could ensure that the hidden ether header
-        * will not be destroyed, else we will have to save
-        * the ether header for the later restoration.
-        */
-       if (m->m_pkthdr.len != m->m_len) {
-               save_eh0 = *eh;
-               save_eh = &save_eh0;
-       } else {
-               save_eh = NULL;
-       }
-
-       /*
-        * Temporarily remove ether header; ether_mport()
-        * expects a packet without ether header.
+        * Ask the isr to characterize the packet since we couldn't.
+        * This is an attempt to optimally get us onto the correct protocol
+        * thread.
         */
-       m_adj(m, sizeof(struct ether_header));
-
-       /*
-        * Find the packet's target msgport.
-        */
-       port = ether_mport(isr, &m);
-       if (port == NULL) {
-               KKASSERT(m == NULL);
+       netisr_characterize(isr, &m, sizeof(struct ether_header));
+       if (m == NULL) {
                logether(chain_end, ifp);
                return;
        }
 
        /*
-        * Restore ether header.
+        * Finally dispatch it
         */
-       if (save_eh != NULL) {
-               ether_restore_header(&m, eh, save_eh);
-               if (m == NULL) {
-                       logether(chain_end, ifp);
-                       return;
-               }
-       } else {
-               m->m_data -= ETHER_HDR_LEN;
-               m->m_len += ETHER_HDR_LEN;
-               m->m_pkthdr.len += ETHER_HDR_LEN;
-       }
-
-       ether_dispatch(isr, port, m, chain);
+       ether_dispatch(isr, m, chain);
 
        logether(chain_end, ifp);
 }
index 541aa17..3a11cb0 100644 (file)
@@ -375,7 +375,7 @@ ifpoll_register(struct ifnet *ifp)
        ifnet_deserialize_all(ifp);
 
        netmsg_init(&nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, ifpoll_register_handler);
+                   0, ifpoll_register_handler);
        nmsg.nm_lmsg.u.ms_resultp = &info;
 
        error = ifnet_domsg(&nmsg.nm_lmsg, 0);
@@ -408,7 +408,7 @@ ifpoll_deregister(struct ifnet *ifp)
        ifnet_deserialize_all(ifp);
 
        netmsg_init(&nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, ifpoll_deregister_handler);
+                   0, ifpoll_deregister_handler);
        nmsg.nm_lmsg.u.ms_resultp = ifp;
 
        error = ifnet_domsg(&nmsg.nm_lmsg, 0);
@@ -504,7 +504,7 @@ stpoll_init(void)
                        "Number of registered status poll handlers");
 
        netmsg_init(&st_ctx->poll_netmsg, NULL, &netisr_adone_rport,
-                   MSGF_MPSAFE, stpoll_handler);
+                   0, stpoll_handler);
 }
 
 /*
@@ -691,11 +691,11 @@ iopoll_ctx_create(int cpuid, int poll_type)
        iopoll_reset_state(io_ctx);
 
        netmsg_init(&io_ctx->poll_netmsg, NULL, &netisr_adone_rport,
-                   MSGF_MPSAFE, iopoll_handler);
+                   0, iopoll_handler);
        io_ctx->poll_netmsg.nm_lmsg.u.ms_resultp = io_ctx;
 
        netmsg_init(&io_ctx->poll_more_netmsg, NULL, &netisr_adone_rport,
-                   MSGF_MPSAFE, iopollmore_handler);
+                   0, iopollmore_handler);
        io_ctx->poll_more_netmsg.nm_lmsg.u.ms_resultp = io_ctx;
 
        /*
@@ -1006,7 +1006,7 @@ sysctl_burstmax(SYSCTL_HANDLER_ARGS)
 
        nmsg = &msg.nmsg;
        netmsg_init(nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, sysctl_burstmax_handler);
+                   0, sysctl_burstmax_handler);
        nmsg->nm_lmsg.u.ms_result = burst_max;
        msg.ctx = io_ctx;
 
@@ -1049,7 +1049,7 @@ sysctl_eachburst(SYSCTL_HANDLER_ARGS)
 
        nmsg = &msg.nmsg;
        netmsg_init(nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, sysctl_eachburst_handler);
+                   0, sysctl_eachburst_handler);
        nmsg->nm_lmsg.u.ms_result = each_burst;
        msg.ctx = io_ctx;
 
@@ -1270,7 +1270,7 @@ sysctl_pollhz(SYSCTL_HANDLER_ARGS)
                phz = IFPOLL_FREQ_MAX;
 
        netmsg_init(&nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, sysctl_pollhz_handler);
+                   0, sysctl_pollhz_handler);
        nmsg.nm_lmsg.u.ms_result = phz;
 
        return ifnet_domsg(&nmsg.nm_lmsg, comm->poll_cpuid);
@@ -1320,7 +1320,7 @@ sysctl_stfrac(SYSCTL_HANDLER_ARGS)
                return EINVAL;
 
        netmsg_init(&nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, sysctl_stfrac_handler);
+                   0, sysctl_stfrac_handler);
        nmsg.nm_lmsg.u.ms_result = stfrac;
 
        return ifnet_domsg(&nmsg.nm_lmsg, comm->poll_cpuid);
@@ -1358,7 +1358,7 @@ sysctl_txfrac(SYSCTL_HANDLER_ARGS)
                return EINVAL;
 
        netmsg_init(&nmsg, NULL, &curthread->td_msgport,
-                   MSGF_MPSAFE, sysctl_txfrac_handler);
+                   0, sysctl_txfrac_handler);
        nmsg.nm_lmsg.u.ms_result = txfrac;
 
        return ifnet_domsg(&nmsg.nm_lmsg, comm->poll_cpuid);
index 784cf5a..3334f05 100644 (file)
@@ -728,7 +728,6 @@ void        ether_ifattach_bpf(struct ifnet *, uint8_t *, u_int, u_int,
                        struct lwkt_serialize *);
 void   ether_ifdetach(struct ifnet *);
 void   ether_demux_oncpu(struct ifnet *, struct mbuf *);
-void   ether_input_oncpu(struct ifnet *, struct mbuf *);
 void   ether_reinput_oncpu(struct ifnet *, struct mbuf *, int);
 void   ether_input_chain(struct ifnet *, struct mbuf *,
                          const struct pktinfo *, struct mbuf_chain *);
index 96a91bd..c7ab539 100644 (file)
@@ -100,6 +100,9 @@ SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_RD,
 
 static u_char          nexpire[MFCTBLSIZ];
 
+struct lwkt_token mroute_token = LWKT_TOKEN_MP_INITIALIZER(mroute_token);
+
+
 static struct callout expire_upcalls_ch;
 static struct callout tbf_reprocess_q_ch;
 #define                EXPIRE_TIMEOUT  (hz / 4)        /* 4x / second          */
@@ -519,16 +522,17 @@ get_sg_cnt(struct sioc_sg_req *req)
 {
     struct mfc *rt;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     rt = mfc_find(req->src.s_addr, req->grp.s_addr);
-    crit_exit();
     if (rt == NULL) {
        req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
+       lwkt_reltoken(&mroute_token);
        return EADDRNOTAVAIL;
     }
     req->pktcnt = rt->mfc_pkt_cnt;
     req->bytecnt = rt->mfc_byte_cnt;
     req->wrong_if = rt->mfc_wrong_if;
+    lwkt_reltoken(&mroute_token);
     return 0;
 }
 
@@ -610,7 +614,7 @@ X_ip_mrouter_done(void)
     struct mfc *rt;
     struct rtdetq *rte;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     /*
      * For each phyint in use, disable promiscuous reception of all IP
@@ -677,7 +681,7 @@ X_ip_mrouter_done(void)
 
     ip_mrouter = NULL;
 
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 
     if (mrtdebug)
        log(LOG_DEBUG, "ip_mrouter_done\n");
@@ -816,14 +820,14 @@ add_vif(struct vifctl *vifcp)
            return EOPNOTSUPP;
 
        /* Enable promiscuous reception of all IP multicasts from the if */
-       crit_enter();
+       lwkt_gettoken(&mroute_token);
        error = if_allmulti(ifp, 1);
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        if (error)
            return error;
     }
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     /* define parameters for the tbf structure */
     vifp->v_tbf = v_tbf;
     GET_TIME(vifp->v_tbf->tbf_last_pkt_t);
@@ -846,11 +850,12 @@ add_vif(struct vifctl *vifcp)
     vifp->v_pkt_out   = 0;
     vifp->v_bytes_in  = 0;
     vifp->v_bytes_out = 0;
-    crit_exit();
 
     /* Adjust numvifs up if the vifi is higher than numvifs */
     if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
 
+    lwkt_reltoken(&mroute_token);
+
     if (mrtdebug)
        log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n",
            vifcp->vifc_vifi,
@@ -877,7 +882,7 @@ del_vif(vifi_t vifi)
     if (vifp->v_lcl_addr.s_addr == INADDR_ANY)
        return EADDRNOTAVAIL;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)))
        if_allmulti(vifp->v_ifp, 0);
@@ -914,7 +919,7 @@ del_vif(vifi_t vifi)
            break;
     numvifs = vifi;
 
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 
     return 0;
 }
@@ -980,16 +985,16 @@ add_mfc(struct mfcctl2 *mfccp)
                (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
                mfccp->mfcc_parent);
 
-       crit_enter();
+       lwkt_gettoken(&mroute_token);
        update_mfc_params(rt, mfccp);
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return 0;
     }
 
     /*
      * Find the entry for which the upcall was made and update
      */
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
     for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
 
@@ -1051,7 +1056,7 @@ add_mfc(struct mfcctl2 *mfccp)
        if (rt == NULL) {               /* no upcall, so make a new entry */
            rt = kmalloc(sizeof(*rt), M_MRTABLE, M_INTWAIT | M_NULLOK);
            if (rt == NULL) {
-                   crit_exit();
+                   lwkt_reltoken(&mroute_token);
                    return ENOBUFS;
            }
 
@@ -1065,7 +1070,7 @@ add_mfc(struct mfcctl2 *mfccp)
            mfctable[hash] = rt;
        }
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
     return 0;
 }
 
@@ -1089,7 +1094,7 @@ del_mfc(struct mfcctl2 *mfccp)
        log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
            (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
     for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next)
@@ -1098,7 +1103,7 @@ del_mfc(struct mfcctl2 *mfccp)
                rt->mfc_stall == NULL)
            break;
     if (rt == NULL) {
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return EADDRNOTAVAIL;
     }
 
@@ -1109,11 +1114,9 @@ del_mfc(struct mfcctl2 *mfccp)
      */
     list = rt->mfc_bw_meter;
     rt->mfc_bw_meter = NULL;
+    lwkt_reltoken(&mroute_token);
 
     kfree(rt, M_MRTABLE);
-
-    crit_exit();
-
     free_bw_list(list);
 
     return 0;
@@ -1212,14 +1215,15 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
     /*
      * Determine forwarding vifs from the forwarding cache table
      */
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     ++mrtstat.mrts_mfc_lookups;
     rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr);
 
     /* Entry exists, so forward if necessary */
     if (rt != NULL) {
-       crit_exit();
-       return ip_mdq(m, ifp, rt, -1);
+       int ipres = ip_mdq(m, ifp, rt, -1);
+       lwkt_reltoken(&mroute_token);
+       return ipres;
     } else {
        /*
         * If we don't have a route for packet's origin,
@@ -1246,7 +1250,7 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
         */
        rte = kmalloc((sizeof *rte), M_MRTABLE, M_INTWAIT | M_NULLOK);
        if (rte == NULL) {
-               crit_exit();
+               lwkt_reltoken(&mroute_token);
                return ENOBUFS;
        }
 
@@ -1255,7 +1259,7 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
            mb0 = m_pullup(mb0, hlen);
        if (mb0 == NULL) {
            kfree(rte, M_MRTABLE);
-           crit_exit();
+           lwkt_reltoken(&mroute_token);
            return ENOBUFS;
        }
 
@@ -1314,7 +1318,7 @@ fail1:
 fail:
                kfree(rte, M_MRTABLE);
                m_freem(mb0);
-               crit_exit();
+               lwkt_reltoken(&mroute_token);
                return ENOBUFS;
            }
 
@@ -1356,7 +1360,7 @@ fail:
 non_fatal:
                kfree(rte, M_MRTABLE);
                m_freem(mb0);
-               crit_exit();
+               lwkt_reltoken(&mroute_token);
                return 0;
            }
 
@@ -1368,7 +1372,7 @@ non_fatal:
        rte->ifp                = ifp;
        rte->next               = NULL;
 
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return 0;
     }
 }
@@ -1383,7 +1387,7 @@ expire_upcalls(void *unused)
     struct mfc *mfc, **nptr;
     int i;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     for (i = 0; i < MFCTBLSIZ; i++) {
        if (nexpire[i] == 0)
            continue;
@@ -1432,7 +1436,7 @@ expire_upcalls(void *unused)
        }
     }
     callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL);
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -1810,7 +1814,7 @@ tbf_queue(struct vif *vifp, struct mbuf *m)
 {
     struct tbf *t = vifp->v_tbf;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     if (t->tbf_t == NULL)      /* Queue was empty */
        t->tbf_q = m;
@@ -1828,7 +1832,7 @@ tbf_queue(struct vif *vifp, struct mbuf *m)
 
     t->tbf_q_len++;
 
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -1839,7 +1843,7 @@ tbf_process_q(struct vif *vifp)
 {
     struct tbf *t = vifp->v_tbf;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     /* loop through the queue at the interface and send as many packets
      * as possible
@@ -1861,7 +1865,7 @@ tbf_process_q(struct vif *vifp)
        m->m_nextpkt = NULL;
        tbf_send_packet(vifp, m);
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 static void
@@ -1889,7 +1893,7 @@ tbf_dq_sel(struct vif *vifp, struct ip *ip)
     struct mbuf **np;
     struct tbf *t = vifp->v_tbf;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     p = priority(vifp, ip);
 
@@ -1905,21 +1909,21 @@ tbf_dq_sel(struct vif *vifp, struct ip *ip)
            /* It's impossible for the queue to be empty, but check anyways. */
            if (--t->tbf_q_len == 0)
                t->tbf_t = NULL;
-           crit_exit();
            mrtstat.mrts_drop_sel++;
+           lwkt_reltoken(&mroute_token);
            return 1;
        }
        np = &m->m_nextpkt;
        last = m;
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
     return 0;
 }
 
 static void
 tbf_send_packet(struct vif *vifp, struct mbuf *m)
 {
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     if (vifp->v_flags & VIFF_TUNNEL)   /* If tunnel options */
        ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, NULL, NULL);
@@ -1945,7 +1949,7 @@ tbf_send_packet(struct vif *vifp, struct mbuf *m)
            log(LOG_DEBUG, "phyint_send on vif %d err %d\n",
                (int)(vifp - viftable), error);
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 /* determine the current time and then
@@ -1959,7 +1963,7 @@ tbf_update_tokens(struct vif *vifp)
     u_long tm;
     struct tbf *t = vifp->v_tbf;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     GET_TIME(tp);
 
@@ -1980,7 +1984,7 @@ tbf_update_tokens(struct vif *vifp)
     if (t->tbf_n_tok > MAX_BKT_SIZE)
        t->tbf_n_tok = MAX_BKT_SIZE;
 
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 static int
@@ -2032,17 +2036,17 @@ X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
     if (error)
        return error;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return EADDRNOTAVAIL;
     }
 
     if (sopt->sopt_name == IP_RSVP_VIF_ON) {
        /* Check if socket is available. */
        if (viftable[vifi].v_rsvpd != NULL) {
-           crit_exit();
+           lwkt_reltoken(&mroute_token);
            return EADDRINUSE;
        }
 
@@ -2070,7 +2074,7 @@ X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
            rsvp_on--;
        }
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
     return 0;
 }
 
@@ -2083,7 +2087,7 @@ X_ip_rsvp_force_done(struct socket *so)
     if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
        return;
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     /* The socket may be attached to more than one vif...this
      * is perfectly legal.
@@ -2101,7 +2105,7 @@ X_ip_rsvp_force_done(struct socket *so)
        }
     }
 
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 static void
@@ -2137,7 +2141,7 @@ X_rsvp_input(struct mbuf *m, ...)
        return;
     }
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
 
     if (rsvpdebug)
        kprintf("rsvp_input: check vifs\n");
@@ -2174,7 +2178,7 @@ X_rsvp_input(struct mbuf *m, ...)
                kprintf("rsvp_input: No socket defined for vif %d\n",vifi);
            m_freem(m);
        }
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return;
     }
     rsvp_src.sin_addr = ip->ip_src;
@@ -2212,7 +2216,7 @@ X_rsvp_input(struct mbuf *m, ...)
     }
 #endif /* !ALTQ */
 
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -2277,10 +2281,10 @@ add_bw_upcall(struct bw_upcall *req)
     /*
      * Find if we have already same bw_meter entry
      */
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
     if (mfc == NULL) {
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return EADDRNOTAVAIL;
     }
     for (x = mfc->mfc_bw_meter; x != NULL; x = x->bm_mfc_next) {
@@ -2289,11 +2293,11 @@ add_bw_upcall(struct bw_upcall *req)
            (x->bm_threshold.b_packets == req->bu_threshold.b_packets) &&
            (x->bm_threshold.b_bytes == req->bu_threshold.b_bytes) &&
            (x->bm_flags & BW_METER_USER_FLAGS) == flags)  {
-           crit_exit();
+           lwkt_reltoken(&mroute_token);
            return 0;           /* XXX Already installed */
        }
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
     
     /* Allocate the new bw_meter entry */
     x = kmalloc(sizeof(*x), M_BWMETER, M_INTWAIT);
@@ -2311,12 +2315,12 @@ add_bw_upcall(struct bw_upcall *req)
     x->bm_time_hash = BW_METER_BUCKETS;
     
     /* Add the new bw_meter entry to the front of entries for this MFC */
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     x->bm_mfc = mfc;
     x->bm_mfc_next = mfc->mfc_bw_meter;
     mfc->mfc_bw_meter = x;
     schedule_bw_meter(x, &now);
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
     
     return 0;
 }
@@ -2345,11 +2349,11 @@ del_bw_upcall(struct bw_upcall *req)
     if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
        return EOPNOTSUPP;
     
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     /* Find the corresponding MFC entry */
     mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
     if (mfc == NULL) {
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        return EADDRNOTAVAIL;
     } else if (req->bu_flags & BW_UPCALL_DELETE_ALL) {
        /*
@@ -2359,7 +2363,7 @@ del_bw_upcall(struct bw_upcall *req)
        
        list = mfc->mfc_bw_meter;
        mfc->mfc_bw_meter = NULL;
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        free_bw_list(list);
        return 0;
     } else {                   /* Delete a single bw_meter entry */
@@ -2383,14 +2387,13 @@ del_bw_upcall(struct bw_upcall *req)
                prev->bm_mfc_next = x->bm_mfc_next;     /* remove from middle*/
            else
                x->bm_mfc->mfc_bw_meter = x->bm_mfc_next;/* new head of list */
-           crit_exit();
-
            unschedule_bw_meter(x);
+           lwkt_reltoken(&mroute_token);
            /* Free the bw_meter entry */
            kfree(x, M_BWMETER);
            return 0;
        } else {
-           crit_exit();
+           lwkt_reltoken(&mroute_token);
            return EINVAL;
        }
     }
@@ -2405,7 +2408,7 @@ bw_meter_receive_packet(struct bw_meter *x, int plen, struct timeval *nowp)
 {
     struct timeval delta;
     
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     delta = *nowp;
     BW_TIMEVALDECR(&delta, &x->bm_start_time);
     
@@ -2486,7 +2489,7 @@ bw_meter_receive_packet(struct bw_meter *x, int plen, struct timeval *nowp)
            x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
        }
     }
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -2498,7 +2501,7 @@ bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
     struct timeval delta;
     struct bw_upcall *u;
     
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     
     /*
      * Compute the measured time interval 
@@ -2534,7 +2537,7 @@ bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
     if (x->bm_flags & BW_METER_LEQ)
        u->bu_flags |= BW_UPCALL_LEQ;
     
-    crit_exit();
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -2614,12 +2617,11 @@ schedule_bw_meter(struct bw_meter *x, struct timeval *nowp)
     /*
      * Reset the bw_meter entry
      */
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     x->bm_start_time = *nowp;
     x->bm_measured.b_packets = 0;
     x->bm_measured.b_bytes = 0;
     x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
-    crit_exit();
     
     /*
      * Compute the timeout hash value and insert the entry
@@ -2628,6 +2630,8 @@ schedule_bw_meter(struct bw_meter *x, struct timeval *nowp)
     x->bm_time_next = bw_meter_timers[time_hash];
     bw_meter_timers[time_hash] = x;
     x->bm_time_hash = time_hash;
+
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -2690,7 +2694,7 @@ bw_meter_process(void)
     if (last_tv_sec == now.tv_sec)
        return;         /* nothing to do */
 
-    crit_enter();
+    lwkt_gettoken(&mroute_token);
     loops = now.tv_sec - last_tv_sec;
     last_tv_sec = now.tv_sec;
     if (loops > BW_METER_BUCKETS)
@@ -2756,10 +2760,9 @@ bw_meter_process(void)
            schedule_bw_meter(x, &now);
        }
     }
-    crit_exit();
-    
     /* Send all upcalls that are pending delivery */
     bw_upcalls_send();
+    lwkt_reltoken(&mroute_token);
 }
 
 /*
@@ -3255,7 +3258,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
 {
     switch (type) {
     case MOD_LOAD:
-       crit_enter();
+       lwkt_gettoken(&mroute_token);
        /* XXX Protect against multiple loading */
        ip_mcast_src = X_ip_mcast_src;
        ip_mforward = X_ip_mforward;
@@ -3268,14 +3271,14 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
        legal_vif_num = X_legal_vif_num;
        mrt_ioctl = X_mrt_ioctl;
        rsvp_input_p = X_rsvp_input;
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        break;
 
     case MOD_UNLOAD:
        if (ip_mrouter)
            return EINVAL;
 
-       crit_enter();
+       lwkt_gettoken(&mroute_token);
        ip_mcast_src = NULL;
        ip_mforward = NULL;
        ip_mrouter_done = NULL;
@@ -3287,7 +3290,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
        legal_vif_num = NULL;
        mrt_ioctl = NULL;
        rsvp_input_p = NULL;
-       crit_exit();
+       lwkt_reltoken(&mroute_token);
        break;
     }
     return 0;
index 20bf240..f6d3090 100644 (file)
@@ -2484,7 +2484,7 @@ ipfw_dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
        pkt->pipe_nr = pipe_nr;
 
        pkt->cpuid = mycpuid;
-       pkt->msgport = curnetport;
+       pkt->msgport = cur_netport();
 
        id = &fwa->f_id;
        fid = &pkt->id;
@@ -4440,7 +4440,7 @@ ipfw_init_dispatch(struct netmsg *nmsg)
 
        callout_init_mp(&ipfw_timeout_h);
        netmsg_init(&ipfw_timeout_netmsg, NULL, &netisr_adone_rport,
-                   MSGF_MPSAFE | MSGF_DROPABLE | MSGF_PRIORITY,
+                   MSGF_DROPABLE | MSGF_PRIORITY,
                    ipfw_tick_dispatch);
        lockinit(&dyn_lock, "ipfw_dyn", 0, 0);
 
index f28626e..baf005e 100644 (file)
 #include <net/netmsg2.h>
 #include <sys/mplock2.h>
 
-#define NETISR_GET_MPLOCK(ni) \
-do { \
-    if (((ni)->ni_flags & NETISR_FLAG_MPSAFE) == 0) \
-       get_mplock(); \
-} while (0)
-
-#define NETISR_REL_MPLOCK(ni) \
-do { \
-    if (((ni)->ni_flags & NETISR_FLAG_MPSAFE) == 0) \
-       rel_mplock(); \
-} while (0)
-
 static void netmsg_sync_func(struct netmsg *msg);
+static void netmsg_service_loop(void *arg);
+static void cpu0_cpufn(struct mbuf **mp, int hoff);
 
 struct netmsg_port_registration {
-    TAILQ_ENTRY(netmsg_port_registration) npr_entry;
-    lwkt_port_t        npr_port;
+       TAILQ_ENTRY(netmsg_port_registration) npr_entry;
+       lwkt_port_t     npr_port;
+};
+
+struct netmsg_rollup {
+       TAILQ_ENTRY(netmsg_rollup) ru_entry;
+       netisr_ru_t     ru_func;
 };
 
 static struct netisr netisrs[NETISR_MAX];
 static TAILQ_HEAD(,netmsg_port_registration) netreglist;
+static TAILQ_HEAD(,netmsg_rollup) netrulist;
 
 /* Per-CPU thread to handle any protocol.  */
-struct thread netisr_cpu[MAXCPU];
+static struct thread netisr_cpu[MAXCPU];
 lwkt_port netisr_afree_rport;
 lwkt_port netisr_adone_rport;
 lwkt_port netisr_apanic_rport;
@@ -89,23 +85,7 @@ lwkt_port netisr_sync_port;
 
 static int (*netmsg_fwd_port_fn)(lwkt_port_t, lwkt_msg_t);
 
-static int netisr_mpsafe_thread = NETMSG_SERVICE_ADAPTIVE;
-TUNABLE_INT("net.netisr.mpsafe_thread", &netisr_mpsafe_thread);
-
 SYSCTL_NODE(_net, OID_AUTO, netisr, CTLFLAG_RW, 0, "netisr");
-SYSCTL_INT(_net_netisr, OID_AUTO, mpsafe_thread, CTLFLAG_RW,
-          &netisr_mpsafe_thread, 0,
-          "0:BGL, 1:Adaptive BGL, 2:No BGL(experimental)");
-
-static __inline int
-NETISR_TO_MSGF(const struct netisr *ni)
-{
-    int msg_flags = 0;
-    
-    if (ni->ni_flags & NETISR_FLAG_MPSAFE)
-       msg_flags |= MSGF_MPSAFE;
-    return msg_flags;
-}
 
 /*
  * netisr_afree_rport replymsg function, only used to handle async
@@ -114,7 +94,7 @@ NETISR_TO_MSGF(const struct netisr *ni)
 static void
 netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
 {
-    kfree(msg, M_LWKTMSG);
+       kfree(msg, M_LWKTMSG);
 }
 
 /*
@@ -131,16 +111,18 @@ netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
 static int
 netmsg_put_port(lwkt_port_t port, lwkt_msg_t lmsg)
 {
-    netmsg_t netmsg = (void *)lmsg;
-
-    if ((lmsg->ms_flags & MSGF_SYNC) && port == &curthread->td_msgport) {
-       netmsg->nm_dispatch(netmsg);
-       if ((lmsg->ms_flags & MSGF_DONE) == 0)
-           panic("netmsg_put_port: self-referential deadlock on netport");
-       return(EASYNC);
-    } else {
-       return(netmsg_fwd_port_fn(port, lmsg));
-    }
+       netmsg_t netmsg = (void *)lmsg;
+
+       if ((lmsg->ms_flags & MSGF_SYNC) && port == &curthread->td_msgport) {
+               netmsg->nm_dispatch(netmsg);
+               if ((lmsg->ms_flags & MSGF_DONE) == 0) {
+                       panic("netmsg_put_port: self-referential "
+                             "deadlock on netport");
+               }
+               return(EASYNC);
+       } else {
+               return(netmsg_fwd_port_fn(port, lmsg));
+       }
 }
 
 /*
@@ -156,47 +138,49 @@ netmsg_put_port(lwkt_port_t port, lwkt_msg_t lmsg)
 static int
 netmsg_sync_putport(lwkt_port_t port, lwkt_msg_t lmsg)
 {
-    netmsg_t netmsg = (void *)lmsg;
+       netmsg_t netmsg = (void *)lmsg;
 
-    KKASSERT((lmsg->ms_flags & MSGF_DONE) == 0);
+       KKASSERT((lmsg->ms_flags & MSGF_DONE) == 0);
 
-    lmsg->ms_target_port = port;       /* required for abort */
-    netmsg->nm_dispatch(netmsg);
-    return(EASYNC);
+       lmsg->ms_target_port = port;    /* required for abort */
+       netmsg->nm_dispatch(netmsg);
+       return(EASYNC);
 }
 
 static void
 netisr_init(void)
 {
-    int i;
-
-    TAILQ_INIT(&netreglist);
-
-    /*
-     * Create default per-cpu threads for generic protocol handling.
-     */
-    for (i = 0; i < ncpus; ++i) {
-       lwkt_create(netmsg_service_loop, &netisr_mpsafe_thread, NULL,
-                   &netisr_cpu[i], TDF_NETWORK, i,
-                   "netisr_cpu %d", i);
-       netmsg_service_port_init(&netisr_cpu[i].td_msgport);
-    }
-
-    /*
-     * The netisr_afree_rport is a special reply port which automatically
-     * frees the replied message.  The netisr_adone_rport simply marks
-     * the message as being done.  The netisr_apanic_rport panics if
-     * the message is replied to.
-     */
-    lwkt_initport_replyonly(&netisr_afree_rport, netisr_autofree_reply);
-    lwkt_initport_replyonly_null(&netisr_adone_rport);
-    lwkt_initport_panic(&netisr_apanic_rport);
-
-    /*
-     * The netisr_syncport is a special port which executes the message
-     * synchronously and waits for it if EASYNC is returned.
-     */
-    lwkt_initport_putonly(&netisr_sync_port, netmsg_sync_putport);
+       int i;
+
+       TAILQ_INIT(&netreglist);
+       TAILQ_INIT(&netrulist);
+
+       /*
+        * Create default per-cpu threads for generic protocol handling.
+        */
+       for (i = 0; i < ncpus; ++i) {
+               lwkt_create(netmsg_service_loop, NULL, NULL,
+                           &netisr_cpu[i], TDF_STOPREQ, i,
+                           "netisr_cpu %d", i);
+               netmsg_service_port_init(&netisr_cpu[i].td_msgport);
+               lwkt_schedule(&netisr_cpu[i]);
+       }
+
+       /*
+        * The netisr_afree_rport is a special reply port which automatically
+        * frees the replied message.  The netisr_adone_rport simply marks
+        * the message as being done.  The netisr_apanic_rport panics if
+        * the message is replied to.
+        */
+       lwkt_initport_replyonly(&netisr_afree_rport, netisr_autofree_reply);
+       lwkt_initport_replyonly_null(&netisr_adone_rport);
+       lwkt_initport_panic(&netisr_apanic_rport);
+
+       /*
+        * The netisr_syncport is a special port which executes the message
+        * synchronously and waits for it if EASYNC is returned.
+        */
+       lwkt_initport_putonly(&netisr_sync_port, netmsg_sync_putport);
 }
 
 SYSINIT(netisr, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, netisr_init, NULL);
@@ -209,25 +193,25 @@ SYSINIT(netisr, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, netisr_init, NULL);
 void
 netmsg_service_port_init(lwkt_port_t port)
 {
-    struct netmsg_port_registration *reg;
-
-    /*
-     * Override the putport function.  Our custom function checks for 
-     * self-references and executes such commands synchronously.
-     */
-    if (netmsg_fwd_port_fn == NULL)
-       netmsg_fwd_port_fn = port->mp_putport;
-    KKASSERT(netmsg_fwd_port_fn == port->mp_putport);
-    port->mp_putport = netmsg_put_port;
-
-    /*
-     * Keep track of ports using the netmsg API so we can synchronize
-     * certain operations (such as freeing an ifnet structure) across all
-     * consumers.
-     */
-    reg = kmalloc(sizeof(*reg), M_TEMP, M_WAITOK|M_ZERO);
-    reg->npr_port = port;
-    TAILQ_INSERT_TAIL(&netreglist, reg, npr_entry);
+       struct netmsg_port_registration *reg;
+
+       /*
+        * Override the putport function.  Our custom function checks for
+        * self-references and executes such commands synchronously.
+        */
+       if (netmsg_fwd_port_fn == NULL)
+               netmsg_fwd_port_fn = port->mp_putport;
+       KKASSERT(netmsg_fwd_port_fn == port->mp_putport);
+       port->mp_putport = netmsg_put_port;
+
+       /*
+        * Keep track of ports using the netmsg API so we can synchronize
+        * certain operations (such as freeing an ifnet structure) across all
+        * consumers.
+        */
+       reg = kmalloc(sizeof(*reg), M_TEMP, M_WAITOK|M_ZERO);
+       reg->npr_port = port;
+       TAILQ_INSERT_TAIL(&netreglist, reg, npr_entry);
 }
 
 /*
@@ -242,15 +226,14 @@ netmsg_service_port_init(lwkt_port_t port)
 void
 netmsg_service_sync(void)
 {
-    struct netmsg_port_registration *reg;
-    struct netmsg smsg;
+       struct netmsg_port_registration *reg;
+       struct netmsg smsg;
 
-    netmsg_init(&smsg, NULL, &curthread->td_msgport,
-               MSGF_MPSAFE, netmsg_sync_func);
+       netmsg_init(&smsg, NULL, &curthread->td_msgport, 0, netmsg_sync_func);
 
-    TAILQ_FOREACH(reg, &netreglist, npr_entry) {
-       lwkt_domsg(reg->npr_port, &smsg.nm_lmsg, 0);
-    }
+       TAILQ_FOREACH(reg, &netreglist, npr_entry) {
+               lwkt_domsg(reg->npr_port, &smsg.nm_lmsg, 0);
+       }
 }
 
 /*
@@ -260,233 +243,240 @@ netmsg_service_sync(void)
 static void
 netmsg_sync_func(struct netmsg *msg)
 {
-    lwkt_replymsg(&msg->nm_lmsg, 0);
-}
-
-/*
- * Service a netmsg request and modify the BGL lock state if appropriate.
- * The new BGL lock state is returned (1:locked, 0:unlocked).
- */
-int
-netmsg_service(struct netmsg *msg, int mpsafe_mode, int mplocked)
-{
-    /*
-     * If nm_so is non-NULL the message is related to a socket.  Sockets
-     * can migrate between protocol processing threads when they connect,
-     * due to an implied connect during a sendmsg(), or when a connection
-     * is accepted.
-     *
-     * If this occurs any messages already queued to the original thread
-     * or which race the change must be forwarded to the new protocol
-     * processing port.
-     *
-     * MPSAFE - socket changes are synchronous to the current protocol port
-     *                 so if the port can only change out from under us if it is
-     *         already different from the current port anyway so we forward
-     *         it.  It is possible to chase a changing port, which is fine.
-     */
-    if (msg->nm_so && msg->nm_so->so_port != &curthread->td_msgport) {
-       lwkt_forwardmsg(msg->nm_so->so_port, &msg->nm_lmsg);
-       return(mplocked);
-    }
-
-    /*
-     * Adjust the mplock dynamically.
-     */
-    switch (mpsafe_mode) {
-    case NETMSG_SERVICE_ADAPTIVE: /* Adaptive BGL */
-       if (msg->nm_lmsg.ms_flags & MSGF_MPSAFE) {
-           if (mplocked) {
-               rel_mplock();
-               mplocked = 0;
-           }
-           msg->nm_dispatch(msg);
-           /* Leave mpunlocked */
-       } else {
-           if (!mplocked) {
-               get_mplock();
-               /* mplocked = 1; not needed */
-           }
-           msg->nm_dispatch(msg);
-           rel_mplock();
-           mplocked = 0;
-           /* Leave mpunlocked, next msg might be mpsafe */
-       }
-       break;
-
-    case NETMSG_SERVICE_MPSAFE: /* No BGL */
-       if (mplocked) {
-           rel_mplock();
-           mplocked = 0;
-       }
-       msg->nm_dispatch(msg);
-       /* Leave mpunlocked */
-       break;
-
-    default: /* BGL */
-       if (!mplocked) {
-           get_mplock();
-           mplocked = 1;
-       }
-       msg->nm_dispatch(msg);
-       /* Leave mplocked */
-       break;
-    }
-    return mplocked;
+       lwkt_replymsg(&msg->nm_lmsg, 0);
 }
 
 /*
  * Generic netmsg service loop.  Some protocols may roll their own but all
  * must do the basic command dispatch function call done here.
  */
-void
+static void
 netmsg_service_loop(void *arg)
 {
-    struct netmsg *msg;
-    int mplocked, *mpsafe_mode = arg;
-
-    /*
-     * Threads always start mpsafe.
-     */
-    mplocked = 0;
-
-    /*
-     * Loop on netmsgs
-     */
-    while ((msg = lwkt_waitport(&curthread->td_msgport, 0))) {
-       mplocked = netmsg_service(msg, *mpsafe_mode, mplocked);
-    }
+       struct netmsg_rollup *ru;
+       struct netmsg *msg;
+       thread_t td = curthread;;
+       int limit;
+
+       while ((msg = lwkt_waitport(&td->td_msgport, 0))) {
+               /*
+                * Run up to 512 pending netmsgs.
+                */
+               limit = 512;
+               do {
+                       KASSERT(msg->nm_dispatch != NULL,
+                               ("netmsg_service isr %d badmsg\n",
+                               msg->nm_lmsg.u.ms_result));
+                       msg->nm_dispatch(msg);
+                       if (--limit == 0)
+                               break;
+               } while ((msg = lwkt_getport(&td->td_msgport)) != NULL);
+
+               /*
+                * Run all registered rollup functions for this cpu
+                * (e.g. tcp_willblock()).
+                */
+               TAILQ_FOREACH(ru, &netrulist, ru_entry)
+                       ru->ru_func();
+       }
 }
 
 /*
- * Call the netisr directly.
- * Queueing may be done in the msg port layer at its discretion.
+ * Forward a packet to a netisr service function.
+ *
+ * If the packet has not been assigned to a protocol thread we call
+ * the port characterization function to assign it.  The caller must
+ * clear M_HASH (or not have set it in the first place) if the caller
+ * wishes the packet to be recharacterized.
  */
-void
-netisr_dispatch(int num, struct mbuf *m)
+int
+netisr_queue(int num, struct mbuf *m)
 {
-    /* just queue it for now XXX JH */
-    netisr_queue(num, m);
+       struct netisr *ni;
+       struct netmsg_packet *pmsg;
+       lwkt_port_t port;
+
+       KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
+               ("Bad isr %d", num));
+
+       ni = &netisrs[num];
+       if (ni->ni_handler == NULL) {
+               kprintf("Unregistered isr %d\n", num);
+               m_freem(m);
+               return (EIO);
+       }
+
+       /*
+        * Figure out which protocol thread to send to.  This does not
+        * have to be perfect but performance will be really good if it
+        * is correct.  Major protocol inputs such as ip_input() will
+        * re-characterize the packet as necessary.
+        */
+       if ((m->m_flags & M_HASH) == 0) {
+               ni->ni_cpufn(&m, 0);
+               if (m == NULL) {
+                       m_freem(m);
+                       return (EIO);
+               }
+               if ((m->m_flags & M_HASH) == 0) {
+                       kprintf("netisr_queue(%d): packet hash failed\n", num);
+                       m_freem(m);
+                       return (EIO);
+               }
+       }
+
+       /*
+        * Get the protocol port based on the packet hash, initialize
+        * the netmsg, and send it off.
+        */
+       port = cpu_portfn(m->m_pkthdr.hash);
+       pmsg = &m->m_hdr.mh_netmsg;
+       netmsg_init(&pmsg->nm_netmsg, NULL, &netisr_apanic_rport,
+                   0, ni->ni_handler);
+       pmsg->nm_packet = m;
+       pmsg->nm_netmsg.nm_lmsg.u.ms_result = num;
+       lwkt_sendmsg(port, &pmsg->nm_netmsg.nm_lmsg);
+
+       return (0);
 }
 
 /*
- * Same as netisr_dispatch(), but always queue.
- * This is either used in places where we are not confident that
- * direct dispatch is possible, or where queueing is required.
+ * Pre-characterization of a deeper portion of the packet for the
+ * requested isr.
+ *
+ * The base of the ISR type (e.g. IP) that we want to characterize is
+ * at (hoff) relative to the beginning of the mbuf.  This allows
+ * e.g. ether_input_chain() to not have to adjust the m_data/m_len.
  */
-int
-netisr_queue(int num, struct mbuf *m)
+void
+netisr_characterize(int num, struct mbuf **mp, int hoff)
 {
-    struct netisr *ni;
-    struct netmsg_packet *pmsg;
-    lwkt_port_t port;
-
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-           ("%s: bad isr %d", __func__, num));
-
-    ni = &netisrs[num];
-    if (ni->ni_handler == NULL) {
-       kprintf("%s: unregistered isr %d\n", __func__, num);
-       m_freem(m);
-       return (EIO);
-    }
-
-    if ((port = ni->ni_mport(&m)) == NULL)
-       return (EIO);
-
-    pmsg = &m->m_hdr.mh_netmsg;
-
-    netmsg_init(&pmsg->nm_netmsg, NULL, &netisr_apanic_rport,
-               NETISR_TO_MSGF(ni), ni->ni_handler);
-    pmsg->nm_packet = m;
-    pmsg->nm_netmsg.nm_lmsg.u.ms_result = num;
-    lwkt_sendmsg(port, &pmsg->nm_netmsg.nm_lmsg);
-    return (0);
+       struct netisr *ni;
+       struct mbuf *m;
+
+       /*
+        * Validation
+        */
+       KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
+               ("Bad isr %d", num));
+       m = *mp;
+       KKASSERT(m != NULL);
+
+       /*
+        * Valid netisr?
+        */
+       ni = &netisrs[num];
+       if (ni->ni_handler == NULL) {
+               kprintf("Unregistered isr %d\n", num);
+               m_freem(m);
+               *mp = NULL;
+       }
+
+       /*
+        * Characterize the packet
+        */
+       if ((m->m_flags & M_HASH) == 0) {
+               ni->ni_cpufn(mp, hoff);
+               m = *mp;
+               if (m && (m->m_flags & M_HASH) == 0)
+                       kprintf("netisr_queue(%d): packet hash failed\n", num);
+       }
 }
 
 void
-netisr_register(int num, pkt_portfn_t mportfn,
-               pktinfo_portfn_t mportfn_pktinfo, netisr_fn_t handler,
-               uint32_t flags)
+netisr_register(int num, netisr_fn_t handler, netisr_cpufn_t cpufn)
 {
-    struct netisr *ni;
-
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-       ("netisr_register: bad isr %d", num));
-    ni = &netisrs[num];
-
-    ni->ni_mport = mportfn;
-    ni->ni_mport_pktinfo = mportfn_pktinfo;
-    ni->ni_handler = handler;
-    ni->ni_flags = flags;
-    netmsg_init(&ni->ni_netmsg, NULL, &netisr_adone_rport,
-               NETISR_TO_MSGF(ni), NULL);
-}
+       struct netisr *ni;
 
-int
-netisr_unregister(int num)
-{
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-       ("unregister_netisr: bad isr number: %d\n", num));
+       KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
+               ("netisr_register: bad isr %d", num));
+       KKASSERT(handler != NULL);
+
+       if (cpufn == NULL)
+               cpufn = cpu0_cpufn;
 
-    /* XXX JH */
-    return (0);
+       ni = &netisrs[num];
+
+       ni->ni_handler = handler;
+       ni->ni_cpufn = cpufn;
+       netmsg_init(&ni->ni_netmsg, NULL, &netisr_adone_rport, 0, NULL);
 }
 
-/*
- * Return message port for default handler thread on CPU 0.
- */
-lwkt_port_t
-cpu0_portfn(struct mbuf **mptr)
+void
+netisr_register_rollup(netisr_ru_t ru_func)
 {
-    struct mbuf *m = *mptr;
-    int cpu = 0;
+       struct netmsg_rollup *ru;
 
-    m->m_pkthdr.hash = cpu;
-    m->m_flags |= M_HASH;
-    return (&netisr_cpu[cpu].td_msgport);
+       ru = kmalloc(sizeof(*ru), M_TEMP, M_WAITOK|M_ZERO);
+       ru->ru_func = ru_func;
+       TAILQ_INSERT_TAIL(&netrulist, ru, ru_entry);
 }
 
+/*
+ * Return the message port for the general protocol message servicing
+ * thread for a particular cpu.
+ */
 lwkt_port_t
 cpu_portfn(int cpu)
 {
-    return (&netisr_cpu[cpu].td_msgport);
+       KKASSERT(cpu >= 0 && cpu < ncpus);
+       return (&netisr_cpu[cpu].td_msgport);
 }
 
 /*
- * If the current thread is a network protocol thread (TDF_NETWORK),
- * then return the current thread's message port.
- * XXX Else, return the current CPU's netisr message port.
+ * Return the current cpu's network protocol thread.
  */
 lwkt_port_t
 cur_netport(void)
 {
-    if (curthread->td_flags & TDF_NETWORK)
-       return &curthread->td_msgport;
-    else
-       return cpu_portfn(mycpuid);
+       return(cpu_portfn(mycpu->gd_cpuid));
 }
 
-/* ARGSUSED */
+/*
+ * Return a default protocol mbuf processing thread port
+ */
 lwkt_port_t
 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused,
            struct mbuf **dummy __unused)
 {
-    return (&netisr_cpu[0].td_msgport);
+       return (&netisr_cpu[0].td_msgport);
 }
 
+/*
+ * Return a default protocol control message processing thread port
+ */
 lwkt_port_t
 cpu0_ctlport(int cmd __unused, struct sockaddr *sa __unused,
             void *extra __unused)
 {
-    return (&netisr_cpu[0].td_msgport);
+       return (&netisr_cpu[0].td_msgport);
 }
 
+/*
+ * This is a dummy port that causes a message to be executed synchronously
+ * instead of being queued to a port.
+ */
 lwkt_port_t
 sync_soport(struct socket *so __unused, struct sockaddr *nam __unused,
            struct mbuf **dummy __unused)
 {
-    return (&netisr_sync_port);
+       return (&netisr_sync_port);
+}
+
+/*
+ * This is a default netisr packet characterization function which
+ * sets M_HASH.  If a netisr is registered with a NULL cpufn function
+ * this one is assigned.
+ *
+ * This function makes no attempt to validate the packet.
+ */
+static void
+cpu0_cpufn(struct mbuf **mp, int hoff __unused)
+{
+       struct mbuf *m = *mp;
+
+       m->m_flags |= M_HASH;
+       m->m_pkthdr.hash = 0;
 }
 
 /*
@@ -504,122 +494,37 @@ sync_soport(struct socket *so __unused, struct sockaddr *nam __unused,
 static void
 schednetisr_remote(void *data)
 {
-    int num = (int)(intptr_t)data;
-    struct netisr *ni = &netisrs[num];
-    lwkt_port_t port = &netisr_cpu[0].td_msgport;
-    struct netmsg *pmsg;
-
-    pmsg = &netisrs[num].ni_netmsg;
-    crit_enter();
-    if (pmsg->nm_lmsg.ms_flags & MSGF_DONE) {
-       netmsg_init(pmsg, NULL, &netisr_adone_rport,
-                   NETISR_TO_MSGF(ni), ni->ni_handler);
-       pmsg->nm_lmsg.u.ms_result = num;
-       lwkt_sendmsg(port, &pmsg->nm_lmsg);
-    }
-    crit_exit();
+       int num = (int)(intptr_t)data;
+       struct netisr *ni = &netisrs[num];
+       lwkt_port_t port = &netisr_cpu[0].td_msgport;
+       struct netmsg *pmsg;
+
+       pmsg = &netisrs[num].ni_netmsg;
+       if (pmsg->nm_lmsg.ms_flags & MSGF_DONE) {
+               netmsg_init(pmsg, NULL, &netisr_adone_rport, 0, ni->ni_handler);
+               pmsg->nm_lmsg.u.ms_result = num;
+               lwkt_sendmsg(port, &pmsg->nm_lmsg);
+       }
 }
 
 void
 schednetisr(int num)
 {
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-       ("schednetisr: bad isr %d", num));
+       KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
+               ("schednetisr: bad isr %d", num));
+       KKASSERT(netisrs[num].ni_handler != NULL);
 #ifdef SMP
-    if (mycpu->gd_cpuid != 0) {
-       lwkt_send_ipiq(globaldata_find(0),
-                      schednetisr_remote, (void *)(intptr_t)num);
-    } else {
-       schednetisr_remote((void *)(intptr_t)num);
-    }
+       if (mycpu->gd_cpuid != 0) {
+               lwkt_send_ipiq(globaldata_find(0),
+                              schednetisr_remote, (void *)(intptr_t)num);
+       } else {
+               crit_enter();
+               schednetisr_remote((void *)(intptr_t)num);
+               crit_exit();
+       }
 #else
-    schednetisr_remote((void *)(intptr_t)num);
+       crit_enter();
+       schednetisr_remote((void *)(intptr_t)num);
+       crit_exit();
 #endif
 }
-
-lwkt_port_t
-netisr_find_port(int num, struct mbuf **m0)
-{
-    struct netisr *ni;
-    lwkt_port_t port;
-    struct mbuf *m = *m0;
-
-    *m0 = NULL;
-
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-           ("%s: bad isr %d", __func__, num));
-
-    ni = &netisrs[num];
-    if (ni->ni_mport == NULL) {
-       kprintf("%s: unregistered isr %d\n", __func__, num);
-       m_freem(m);
-       return NULL;
-    }
-
-    if ((port = ni->ni_mport(&m)) == NULL)
-       return NULL;
-
-    *m0 = m;
-    return port;
-}
-
-void
-netisr_run(int num, struct mbuf *m)
-{
-    struct netisr *ni;
-    struct netmsg_packet *pmsg;
-
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-           ("%s: bad isr %d", __func__, num));
-
-    ni = &netisrs[num];
-    if (ni->ni_handler == NULL) {
-       kprintf("%s: unregistered isr %d\n", __func__, num);
-       m_freem(m);
-       return;
-    }
-
-    pmsg = &m->m_hdr.mh_netmsg;
-
-    netmsg_init(&pmsg->nm_netmsg, NULL, &netisr_apanic_rport,
-               0, ni->ni_handler);
-    pmsg->nm_packet = m;
-    pmsg->nm_netmsg.nm_lmsg.u.ms_result = num;
-
-    NETISR_GET_MPLOCK(ni);
-    ni->ni_handler(&pmsg->nm_netmsg);
-    NETISR_REL_MPLOCK(ni);
-}
-
-lwkt_port_t
-pktinfo_portfn_cpu0(const struct pktinfo *dummy __unused,
-                   struct mbuf *m)
-{
-    m->m_pkthdr.hash = 0;
-    return &netisr_cpu[0].td_msgport;
-}
-
-lwkt_port_t
-pktinfo_portfn_notsupp(const struct pktinfo *dummy __unused,
-                      struct mbuf *m __unused)
-{
-    return NULL;
-}
-
-lwkt_port_t
-netisr_find_pktinfo_port(const struct pktinfo *pi, struct mbuf *m)
-{
-    struct netisr *ni;
-    int num = pi->pi_netisr;
-
-    KASSERT(m->m_flags & M_HASH, ("packet does not contain hash\n"));
-    KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
-           ("%s: bad isr %d", __func__, num));
-
-    ni = &netisrs[num];
-    if (ni->ni_mport_pktinfo == NULL) {
-       kprintf("%s: unregistered isr %d\n", __func__, num);
-       return NULL;
-    }
-    return ni->ni_mport_pktinfo(pi, m);
-}
index 74c79a2..9a90419 100644 (file)
@@ -197,29 +197,28 @@ void netmsg_so_notify_doabort(lwkt_msg_t);
 
 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
 
+/*
+ * Temporary pktinfo structure passed directly from the driver to
+ * ether_input_chain(), allows us to bypass numerous checks.
+ */
 struct pktinfo {
        int             pi_netisr;      /* netisr index, e.g. NETISR_IP */
        uint32_t        pi_flags;       /* PKTINFO_FLAG_ */
        int             pi_l3proto;     /* layer3 protocol number */
 };
 
-#define PKTINFO_FLAG_FRAG      0x1
-
-typedef lwkt_port_t (*pkt_portfn_t)(struct mbuf **);
-typedef lwkt_port_t (*pktinfo_portfn_t)(const struct pktinfo *, struct mbuf *);
+#define PKTINFO_FLAG_FRAG      0x1
 
+/*
+ * NETISR_xxx registrations
+ */
 struct netisr {
-       lwkt_port       ni_port;        /* must be first */
-       pkt_portfn_t    ni_mport;
-       pktinfo_portfn_t ni_mport_pktinfo;
-       netisr_fn_t     ni_handler;
+       netisr_fn_t     ni_handler;     /* packet handler function */
+       netisr_ru_t     ni_rufunc;      /* rollup function */
+       netisr_cpufn_t  ni_cpufn;       /* characterize pkt return cpu */
        struct netmsg   ni_netmsg;      /* for sched_netisr() (no-data) */
-       uint32_t        ni_flags;       /* NETISR_FLAG_ */
 };
 
-#define NETISR_FLAG_NOTMPSAFE  0x0     /* ni_handler is not MPSAFE */
-#define NETISR_FLAG_MPSAFE     0x1     /* ni_handler is MPSAFE */
-
 #endif
 
 #ifdef _KERNEL
@@ -231,24 +230,16 @@ extern lwkt_port netisr_adone_rport;
 extern lwkt_port netisr_afree_rport;
 extern lwkt_port netisr_apanic_rport;
 
-lwkt_port_t    cpu0_portfn(struct mbuf **mptr);
 lwkt_port_t    cpu_portfn(int cpu);
-lwkt_port_t    pktinfo_portfn_cpu0(const struct pktinfo *, struct mbuf *);
-lwkt_port_t    pktinfo_portfn_notsupp(const struct pktinfo *, struct mbuf *);
 lwkt_port_t    cur_netport(void);
 
-lwkt_port_t    netisr_find_port(int, struct mbuf **);
-lwkt_port_t    netisr_find_pktinfo_port(const struct pktinfo *, struct mbuf *);
-void           netisr_dispatch(int, struct mbuf *);
-void           netisr_run(int, struct mbuf *);
+void           netisr_register(int, netisr_fn_t, netisr_cpufn_t);
+void           netisr_register_rollup(netisr_ru_t ru_func);
+
+void           netisr_characterize(int num, struct mbuf **mp, int hoff);
 int            netisr_queue(int, struct mbuf *);
-void           netisr_register(int, pkt_portfn_t, pktinfo_portfn_t,
-                               netisr_fn_t, uint32_t);
-int            netisr_unregister(int);
 
 void           netmsg_service_port_init(lwkt_port_t);
-void           netmsg_service_loop(void *arg);
-int            netmsg_service(struct netmsg *, int, int);
 void           netmsg_service_sync(void);
 void           schednetisr(int);
 
index bf642de..328f2d0 100644 (file)
 struct netmsg;
 
 typedef void (*netisr_fn_t)(struct netmsg *);
+typedef void (*netisr_ru_t)(void);
+typedef void (*netisr_cpufn_t)(struct mbuf **, int);
 
 /*
  * Base netmsg
  */
 typedef struct netmsg {
-    struct lwkt_msg     nm_lmsg;
-    netisr_fn_t                nm_dispatch;
-    struct socket      *nm_so;
+       struct lwkt_msg         nm_lmsg;
+       netisr_fn_t             nm_dispatch;
+       struct socket           *nm_so;
 } *netmsg_t;
 
-#define MSGF_MPSAFE    MSGF_USER0
-
 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
 
 /*
  * User protocol requests messages.
  */
 struct netmsg_pru_abort {
-    struct netmsg      nm_netmsg;
-    pru_abort_fn_t     nm_prufn;
+       struct netmsg           nm_netmsg;
+       pru_abort_fn_t          nm_prufn;
 };
 
 struct netmsg_pru_accept {
-    struct netmsg      nm_netmsg;
-    pru_accept_fn_t    nm_prufn;
-    struct sockaddr    **nm_nam;
+       struct netmsg           nm_netmsg;
+       pru_accept_fn_t         nm_prufn;
+       struct sockaddr         **nm_nam;
 };
 
 struct netmsg_pru_attach {
-    struct netmsg      nm_netmsg;
-    pru_attach_fn_t    nm_prufn;
-    int                        nm_proto;
-    struct pru_attach_info *nm_ai;
+       struct netmsg           nm_netmsg;
+       pru_attach_fn_t         nm_prufn;
+       int                     nm_proto;
+       struct pru_attach_info  *nm_ai;
 };
 
 struct netmsg_pru_bind {
-    struct netmsg      nm_netmsg;
-    pru_bind_fn_t      nm_prufn;
-    struct sockaddr    *nm_nam;
-    struct thread      *nm_td;
+       struct netmsg           nm_netmsg;
+       pru_bind_fn_t           nm_prufn;
+       struct sockaddr         *nm_nam;
+       struct thread           *nm_td;
 };
 
 struct netmsg_pru_connect {
-    struct netmsg      nm_netmsg;
-    pru_connect_fn_t   nm_prufn;
-    struct sockaddr    *nm_nam;
-    struct thread      *nm_td;
+       struct netmsg           nm_netmsg;
+       pru_connect_fn_t        nm_prufn;
+       struct sockaddr         *nm_nam;
+       struct thread           *nm_td;
 };
 
 struct netmsg_pru_connect2 {
-    struct netmsg      nm_netmsg;
-    pru_connect2_fn_t  nm_prufn;
-    struct socket      *nm_so1;
-    struct socket      *nm_so2;
+       struct netmsg           nm_netmsg;
+       pru_connect2_fn_t       nm_prufn;
+       struct socket           *nm_so1;
+       struct socket           *nm_so2;
 };
 
 struct netmsg_pru_control {
-    struct netmsg      nm_netmsg;
-    pru_control_fn_t   nm_prufn;
-    u_long             nm_cmd;
-    caddr_t            nm_data;
-    struct ifnet       *nm_ifp;
-    struct thread      *nm_td;
+       struct netmsg           nm_netmsg;
+       pru_control_fn_t        nm_prufn;
+       u_long                  nm_cmd;
+       caddr_t                 nm_data;
+       struct ifnet            *nm_ifp;
+       struct thread           *nm_td;
 };
 
 struct netmsg_pru_detach {
-    struct netmsg      nm_netmsg;
-    pru_detach_fn_t    nm_prufn;
+       struct netmsg           nm_netmsg;
+       pru_detach_fn_t         nm_prufn;
 };
 
 struct netmsg_pru_disconnect {
-    struct netmsg      nm_netmsg;
-    pru_disconnect_fn_t        nm_prufn;
+       struct netmsg           nm_netmsg;
+       pru_disconnect_fn_t     nm_prufn;
 };
 
 struct netmsg_pru_listen {
-    struct netmsg      nm_netmsg;
-    pru_listen_fn_t    nm_prufn;
-    struct thread      *nm_td;
+       struct netmsg           nm_netmsg;
+       pru_listen_fn_t         nm_prufn;
+       struct thread           *nm_td;
 };
 
 struct netmsg_pru_peeraddr {
-    struct netmsg      nm_netmsg;
-    pru_peeraddr_fn_t  nm_prufn;
-    struct sockaddr    **nm_nam;
+       struct netmsg           nm_netmsg;
+       pru_peeraddr_fn_t       nm_prufn;
+       struct sockaddr         **nm_nam;
 };
 
 struct netmsg_pru_rcvd {
-    struct netmsg      nm_netmsg;
-    pru_rcvd_fn_t      nm_prufn;
-    int                        nm_flags;
+       struct netmsg           nm_netmsg;
+       pru_rcvd_fn_t           nm_prufn;
+       int                     nm_flags;
 };
 
 struct netmsg_pru_rcvoob {
-    struct netmsg      nm_netmsg;
-    pru_rcvoob_fn_t    nm_prufn;
-    struct mbuf                *nm_m;
-    int                        nm_flags;
+       struct netmsg           nm_netmsg;
+       pru_rcvoob_fn_t         nm_prufn;
+       struct mbuf             *nm_m;
+       int                     nm_flags;
 };
 
 struct netmsg_pru_send {
-    struct netmsg      nm_netmsg;
-    pru_send_fn_t      nm_prufn;
-    int                        nm_flags;
-    struct mbuf                *nm_m;
-    struct sockaddr    *nm_addr;
-    struct mbuf                *nm_control;
-    struct thread      *nm_td;
+       struct netmsg           nm_netmsg;
+       pru_send_fn_t           nm_prufn;
+       int                     nm_flags;
+       struct mbuf             *nm_m;
+       struct sockaddr         *nm_addr;
+       struct mbuf             *nm_control;
+       struct thread           *nm_td;
 };
 
 struct netmsg_pru_sense {
-    struct netmsg      nm_netmsg;
-    pru_sense_fn_t     nm_prufn;
-    struct stat                *nm_stat;
+       struct netmsg           nm_netmsg;
+       pru_sense_fn_t          nm_prufn;
+       struct stat             *nm_stat;
 };
 
 struct netmsg_pru_shutdown {
-    struct netmsg      nm_netmsg;
-    pru_shutdown_fn_t  nm_prufn;
+       struct netmsg           nm_netmsg;
+       pru_shutdown_fn_t       nm_prufn;
 };
 
 struct netmsg_pru_sockaddr {
-    struct netmsg      nm_netmsg;
-    pru_sockaddr_fn_t  nm_prufn;
-    struct sockaddr    **nm_nam;
+       struct netmsg           nm_netmsg;
+       pru_sockaddr_fn_t       nm_prufn;
+       struct sockaddr         **nm_nam;
 };
 
 struct netmsg_pru_sosend {
-    struct netmsg      nm_netmsg;
-    pru_sosend_fn_t    nm_prufn;
-    struct sockaddr    *nm_addr;
-    struct uio         *nm_uio;
-    struct mbuf                *nm_top;
-    struct mbuf                *nm_control;
-    int                        nm_flags;
-    struct thread      *nm_td;
+       struct netmsg           nm_netmsg;
+       pru_sosend_fn_t         nm_prufn;
+       struct sockaddr         *nm_addr;
+       struct uio              *nm_uio;
+       struct mbuf             *nm_top;
+       struct mbuf             *nm_control;
+       int                     nm_flags;
+       struct thread           *nm_td;
 };
 
 struct netmsg_pru_soreceive {
-    struct netmsg      nm_netmsg;
-    struct sockaddr    *nm_addr;
-    struct sockaddr    **nm_paddr;
-    struct uio         *nm_uio;
-    struct sockbuf     *nm_sio;
-    struct mbuf                **nm_controlp;
-    int                        *nm_flagsp;
+       struct netmsg           nm_netmsg;
+       struct sockaddr         *nm_addr;
+       struct sockaddr         **nm_paddr;
+       struct uio              *nm_uio;
+       struct sockbuf          *nm_sio;
+       struct mbuf             **nm_controlp;
+       int                     *nm_flagsp;
 };
 
 struct netmsg_pru_ctloutput {
-    struct netmsg      nm_netmsg;
-    pru_ctloutput_fn_t nm_prufn;
-    struct sockopt     *nm_sopt;
+       struct netmsg           nm_netmsg;
+       pru_ctloutput_fn_t      nm_prufn;
+       struct sockopt          *nm_sopt;
 };
 
 struct netmsg_pru_ctlinput {
-    struct netmsg      nm_netmsg;
-    pru_ctlinput_fn_t  nm_prufn;
-    int                        nm_cmd;
-    struct sockaddr    *nm_arg;
-    void               *nm_extra;
+       struct netmsg           nm_netmsg;
+       pru_ctlinput_fn_t       nm_prufn;
+       int                     nm_cmd;
+       struct sockaddr         *nm_arg;
+       void                    *nm_extra;
 };
 
 #endif /* _KERNEL || _KERNEL_STRUCTURES */
index b55e9bb..da5299b 100644 (file)
@@ -49,9 +49,9 @@ static __inline void
 netmsg_init(netmsg_t msg, struct socket *so, lwkt_port_t rport,
            int flags, netisr_fn_t dispatch)
 {
-    lwkt_initmsg(&msg->nm_lmsg, rport, flags);
-    msg->nm_dispatch = dispatch;
-    msg->nm_so = so;
+       lwkt_initmsg(&msg->nm_lmsg, rport, flags);
+       msg->nm_dispatch = dispatch;
+       msg->nm_so = so;
 }
 
 static __inline void
@@ -59,9 +59,9 @@ netmsg_init_abortable(netmsg_t msg, struct socket *so, lwkt_port_t rport,
                      int flags, netisr_fn_t dispatch,
                      void (*abortfn)(lwkt_msg_t))
 {
-    lwkt_initmsg_abortable(&msg->nm_lmsg, rport, flags, abortfn);
-    msg->nm_dispatch = dispatch;
-    msg->nm_so = so;
+       lwkt_initmsg_abortable(&msg->nm_lmsg, rport, flags, abortfn);
+       msg->nm_dispatch = dispatch;
+       msg->nm_so = so;
 }
 
 #endif /* _NET_NETMSG2_H_ */
index 23c42fa..94fc751 100644 (file)
@@ -98,6 +98,7 @@
 #include <sys/malloc.h>
 
 #include <sys/msgport2.h>
+#include <sys/mplock2.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -211,6 +212,8 @@ pppintr(struct netmsg *msg)
      */
     lwkt_replymsg(&msg->nm_lmsg, 0);
 
+    get_mplock();
+
     sc = ppp_softc;
     for (i = 0; i < NPPP; ++i, ++sc) {
        ifnet_serialize_all(&sc->sc_if);
@@ -227,6 +230,7 @@ pppintr(struct netmsg *msg)
        }
        ifnet_deserialize_all(&sc->sc_if);
     }
+    rel_mplock();
 }
 
 /*
@@ -257,8 +261,7 @@ pppattach(void *dummy)
        if_attach(&sc->sc_if, NULL);
        bpfattach(&sc->sc_if, DLT_PPP, PPP_HDRLEN);
     }
-    netisr_register(NETISR_PPP, cpu0_portfn, pktinfo_portfn_cpu0,
-                   pppintr, NETISR_FLAG_NOTMPSAFE);
+    netisr_register(NETISR_PPP, pppintr, NULL);
     /*
      * XXX layering violation - if_ppp can work over any lower level
      * transport that cares to attach to it.
index 0046d2a..b92c1ef 100644 (file)
@@ -61,6 +61,9 @@ static u_long raw_recvspace = RAWRCVQ;
 /*
  * Allocate a control block and a nominal amount
  * of buffer space for the socket.
+ *
+ * The so->so_pcb has already been assigned by the caller, and the
+ * caller has also already bumped the socket refs.
  */
 int
 raw_attach(struct socket *so, int proto, struct rlimit *rl)
@@ -95,7 +98,7 @@ raw_detach(struct rawcb *rp)
        struct socket *so = rp->rcb_socket;
 
        so->so_pcb = NULL;
-       sofree(so);
+       sofree(so);             /* remove pcb ref */
        LIST_REMOVE(rp, list);
        kfree(rp, M_PCB);
 }
index 54be725..1e87404 100644 (file)
@@ -44,6 +44,8 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 
+#include <sys/socketvar2.h>
+
 #include <net/raw_cb.h>
 
 /*
@@ -133,6 +135,10 @@ raw_ctlinput(int cmd, struct sockaddr *arg, void *dummy)
        /* INCOMPLETE */
 }
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 raw_uabort(struct socket *so)
 {
@@ -141,7 +147,6 @@ raw_uabort(struct socket *so)
        if (rp == NULL)
                return EINVAL;
        raw_disconnect(rp);
-       sofree(so);
        soisdisconnected(so);
        return 0;
 }
@@ -198,8 +203,11 @@ raw_udisconnect(struct socket *so)
        if (rp->rcb_faddr == NULL) {
                return ENOTCONN;
        }
+       soreference(so);
        raw_disconnect(rp);
        soisdisconnected(so);
+       sofree(so);
+
        return 0;
 }
 
index 1bd97f6..4dea0fd 100644 (file)
@@ -81,7 +81,9 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/domain.h>
+
 #include <sys/thread2.h>
+#include <sys/socketvar2.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -160,6 +162,7 @@ rts_attach(struct socket *so, int proto, struct pru_attach_info *ai)
         */
        crit_enter();
        so->so_pcb = rp;
+       soreference(so);        /* so_pcb assignment */
        error = raw_attach(so, proto, ai->sb_rlimit);
        rp = sotorawcb(so);
        if (error) {
index 90f2c02..b28a342 100644 (file)
@@ -728,13 +728,14 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
 
        /* Check queue. */
 
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
+
+       /*
+        * Do only account for network packets, not for control
+        * packets.  This is used by some subsystems to detect
+        * idle lines.
+        */
        if (do_account)
-               /*
-                * Do only account for network packets, not for control
-                * packets.  This is used by some subsystems to detect
-                * idle lines.
-                */
                sp->pp_last_recv = time_second;
 }
 
index 9a88657..5d6d2b2 100644 (file)
@@ -587,7 +587,7 @@ in_stf_input(struct mbuf *m, ...)
         */
        ifp->if_ipackets++;
        ifp->if_ibytes += m->m_pkthdr.len;
-       netisr_dispatch(NETISR_IPV6, m);
+       netisr_queue(NETISR_IPV6, m);
 }
 
 /* ARGSUSED */
index d330ab6..889df2f 100644 (file)
@@ -70,8 +70,6 @@
 static uint32_t        toeplitz_keyseeds[TOEPLITZ_KEYSEED_CNT] =
        { TOEPLITZ_KEYSEED0, TOEPLITZ_KEYSEED1 };
 
-#ifdef RSS
-
 uint32_t       toeplitz_cache[TOEPLITZ_KEYSEED_CNT][256];
 
 TUNABLE_INT("net.toeplitz.keyseed0", &toeplitz_keyseeds[0]);
@@ -183,8 +181,6 @@ toeplitz_init(void *dummy __unused)
 }
 SYSINIT(toeplitz, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, toeplitz_init, NULL);
 
-#endif /* RSS */
-
 void
 toeplitz_get_key(uint8_t *key, int keylen)
 {
index fb8d317..3f53c1f 100644 (file)
@@ -45,8 +45,6 @@
 
 #define TOEPLITZ_KEYSEED_CNT   2
 
-#ifdef RSS
-
 extern uint32_t        toeplitz_cache[TOEPLITZ_KEYSEED_CNT][256];
 
 static __inline uint32_t
@@ -90,8 +88,6 @@ toeplitz_rawhash_addr(in_addr_t _faddr, in_addr_t _laddr)
        return _res;
 }
 
-#endif /* RSS */
-
 static __inline int
 toeplitz_hash(uint32_t _rawhash)
 {
index 6d20a05..6c851c5 100644 (file)
@@ -697,7 +697,7 @@ tunwrite(struct dev_write_args *ap)
                return (EAFNOSUPPORT);
        }
 
-       netisr_dispatch(isr, top);
+       netisr_queue(isr, top);
        return (0);
 }
 
index 8f89310..92ce6f5 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <net/netisr.h>
 
+#include <sys/mplock2.h>
+
 #include <netbt/hci.h>
 
 void
@@ -31,7 +33,9 @@ btintr(struct netmsg *msg)
 {
        struct hci_unit *unit;
 
+       get_mplock();
        TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
                hci_intr(unit);
        }
+       rel_mplock();
 }
index 67afacd..2ccfca5 100644 (file)
@@ -239,8 +239,7 @@ SYSCTL_INT(_net_bluetooth_sco, OID_AUTO, recvspace, CTLFLAG_RW, &sco_recvspace,
 static void
 netisr_netbt_setup(void *dummy __unused)
 {
-       netisr_register(NETISR_BLUETOOTH, cpu0_portfn, pktinfo_portfn_cpu0,
-                       btintr, NETISR_FLAG_NOTMPSAFE);
+       netisr_register(NETISR_BLUETOOTH, btintr, NULL);
 }
 
 SYSINIT(netbt_setup, SI_BOOT2_KLD, SI_ORDER_ANY, netisr_netbt_setup, NULL);
index ae785e7..9bc0a1a 100644 (file)
@@ -52,7 +52,9 @@
 #include <net/if.h>
 #include <net/if_var.h>
 #include <sys/sysctl.h>
+
 #include <sys/thread2.h>
+#include <sys/socketvar2.h>
 
 #include <netbt/bluetooth.h>
 #include <netbt/hci.h>
@@ -556,14 +558,20 @@ bad:
 
 /*
  * Implementation of usrreqs.
+ *
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
  */
 static int
 hci_sabort (struct socket *so)
 {
+       int error;
+
        /* struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;  */
 
        soisdisconnected(so);
-       return hci_sdetach(so);
+       error = hci_sdetach(so);
+       return (error);
 }
 
 static int
@@ -577,6 +585,8 @@ hci_sdetach(struct socket *so)
                hci_cmdwait_flush(so);
 
        so->so_pcb = NULL;
+       sofree(so);             /* remove pcb ref */
+
        LIST_REMOVE(pcb, hp_next);
        kfree(pcb, M_PCB);
        
@@ -599,7 +609,7 @@ hci_sdisconnect (struct socket *so)
         * this socket (which is permitted) you get a broken pipe when you
         * try to write any data.
         */
-       so->so_state &= ~SS_ISCONNECTED;
+       soclrstate(so, SS_ISCONNECTED);
        
        return 0;
 }
@@ -628,6 +638,7 @@ hci_sattach (struct socket *so, int proto, struct pru_attach_info *ai)
        if (pcb == NULL) 
                return ENOMEM;
 
+       soreference(so);
        so->so_pcb = pcb;
        pcb->hp_socket = so;
 
index 4eabfdf..355479f 100644 (file)
@@ -241,15 +241,21 @@ l2cap_sdetach(struct socket *so)
        return l2cap_detach((struct l2cap_channel **)&so->so_pcb);
 }
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 l2cap_sabort (struct socket *so)
 {
        struct l2cap_channel *pcb = so->so_pcb;
+       int error;
        
        l2cap_disconnect(pcb, 0);
        soisdisconnected(so);
        
-       return l2cap_sdetach(so);
+       error = l2cap_sdetach(so);
+       return error;
 }
 
 static int
index 7d5c02b..78664fa 100644 (file)
@@ -251,14 +251,20 @@ rfcomm_sdetach(struct socket *so)
        return rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
 }
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 rfcomm_sabort (struct socket *so)
 {
        struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
+       int error;
 
        rfcomm_disconnect(pcb, 0);
        soisdisconnected(so);
-       return rfcomm_sdetach(so);
+       error = rfcomm_sdetach(so);
+       return error;
 }
 
 static int
index 5695392..09cfb2f 100644 (file)
@@ -228,15 +228,21 @@ sco_sdetach(struct socket *so)
        return sco_detach((struct sco_pcb **)&so->so_pcb);
 }
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 sco_sabort (struct socket *so)
 {
        struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
+       int error;
 
        sco_disconnect(pcb, 0);
        soisdisconnected(so);
+       error = sco_sdetach(so);
 
-       return sco_sdetach(so);
+       return error;
 }
 
 static int
index 943df9b..8f971c2 100644 (file)
@@ -792,7 +792,7 @@ ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
                m_freem(m);
                return (EAFNOSUPPORT);
        }
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
index 3cc3c73..edcddd2 100644 (file)
@@ -732,7 +732,7 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
                        if ((so->so_state & SS_ISCONNECTING) != 0)
                                ERROUT(EALREADY);
                        if ((error = soconnect(so, sa, td)) != 0) {
-                               so->so_state &= ~SS_ISCONNECTING;
+                               soclrstate(so, SS_ISCONNECTING);
                                ERROUT(error);
                        }
                        if ((so->so_state & SS_ISCONNECTING) != 0) {
@@ -1006,7 +1006,7 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag)
        if (priv->flags & KSF_CONNECTING) {
                if ((error = so->so_error) != 0) {
                        so->so_error = 0;
-                       so->so_state &= ~SS_ISCONNECTING;
+                       soclrstate(so, SS_ISCONNECTING);
                }
                if (!(so->so_state & SS_ISCONNECTING)) {
                        NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE,
@@ -1132,16 +1132,20 @@ ng_ksocket_check_accept(priv_p priv)
        struct socket *const head = priv->so;
        int error;
 
+       lwkt_gettoken(&head->so_rcv.ssb_token);
        if ((error = head->so_error) != 0) {
                head->so_error = 0;
+               lwkt_reltoken(&head->so_rcv.ssb_token);
                return error;
        }
        if (TAILQ_EMPTY(&head->so_comp)) {
                if (head->so_state & SS_CANTRCVMORE)
-                       return ECONNABORTED;
-               return EWOULDBLOCK;
+                       error = ECONNABORTED;
+               else
+                       error = EWOULDBLOCK;
        }
-       return 0;
+       lwkt_reltoken(&head->so_rcv.ssb_token);
+       return error;
 }
 
 /*
@@ -1160,15 +1164,19 @@ ng_ksocket_finish_accept(priv_p priv, struct ng_mesg **rptr)
        priv_p priv2;
        int len;
 
+       lwkt_gettoken(&head->so_rcv.ssb_token);
        so = TAILQ_FIRST(&head->so_comp);
-       if (so == NULL)         /* Should never happen */
+       if (so == NULL) {       /* Should never happen */
+               lwkt_reltoken(&head->so_rcv.ssb_token);
                return;
+       }
        TAILQ_REMOVE(&head->so_comp, so, so_list);
        head->so_qlen--;
+       lwkt_reltoken(&head->so_rcv.ssb_token);
 
        /* XXX KNOTE(&head->so_rcv.ssb_sel.si_note, 0); */
 
-       so->so_state &= ~SS_COMP;
+       soclrstate(so, SS_COMP);
        so->so_head = NULL;
 
        soaccept(so, &sa);
index c83f335..dad0492 100644 (file)
@@ -1842,9 +1842,7 @@ ngb_mod_event(module_t mod, int event, void *data)
                        crit_exit();
                        break;
                }
-               netisr_register(NETISR_NETGRAPH, cpu0_portfn,
-                               pktinfo_portfn_notsupp, ngintr,
-                               NETISR_FLAG_NOTMPSAFE);
+               netisr_register(NETISR_NETGRAPH, ngintr, NULL);
                error = 0;
                crit_exit();
                break;
@@ -2058,6 +2056,8 @@ ngintr(struct netmsg *pmsg)
         */
        lwkt_replymsg(&pmsg->nm_lmsg, 0);
 
+       get_mplock();
+
        while (1) {
                crit_enter();
                if ((ngq = ngqbase)) {
@@ -2096,7 +2096,7 @@ ngintr(struct netmsg *pmsg)
                }
        }
 out:
-       ;
+       rel_mplock();
 }
 
 
index a11f1bd..c2d6317 100644 (file)
@@ -476,6 +476,7 @@ ng_attach_common(struct socket *so, int type)
        pcbp->type = type;
 
        /* Link the pcb and the socket */
+       soreference(so);
        so->so_pcb = (caddr_t) pcbp;
        pcbp->ng_socket = so;
 
@@ -494,6 +495,7 @@ static void
 ng_detach_common(struct ngpcb *pcbp, int which)
 {
        struct ngsock *sockdata;
+       struct socket *so;
 
        if (pcbp->sockdata) {
                sockdata = pcbp->sockdata;
@@ -511,8 +513,11 @@ ng_detach_common(struct ngpcb *pcbp, int which)
                if ((--sockdata->refs == 0) && (sockdata->node != NULL))
                        ng_rmnode(sockdata->node);
        }
-       pcbp->ng_socket->so_pcb = NULL;
+       so = pcbp->ng_socket;
+       so->so_pcb = NULL;
        pcbp->ng_socket = NULL;
+       sofree(so);             /* remove pcb ref */
+
        LIST_REMOVE(pcbp, socks);
        FREE(pcbp, M_PCB);
 }
index 0f43a2d..6d7f34b 100644 (file)
@@ -706,6 +706,8 @@ ng_btsocket_rfcomm_detach(struct socket *so)
 
        mtx_lock(&pcb->pcb_mtx);
 
+       so->so_pcb = NULL;
+
        switch (pcb->state) {
        case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
        case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
@@ -748,7 +750,7 @@ ng_btsocket_rfcomm_detach(struct socket *so)
        FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
 
        soisdisconnected(so);
-       so->so_pcb = NULL;
+       sofree(so);             /* for so_pcb = NULL */
 } /* ng_btsocket_rfcomm_detach */
 
 /*
@@ -1296,7 +1298,7 @@ ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
        SOCKBUF_LOCK(&l2so->so_snd);
        l2so->so_snd.sb_flags |= SB_UPCALL;
        SOCKBUF_UNLOCK(&l2so->so_snd);
-       l2so->so_state |= SS_NBIO;
+       sosetstate(l2so, SS_NBIO);
        s->l2so = l2so;
 
        mtx_lock(&s->session_mtx);
@@ -1380,7 +1382,7 @@ bad:
        SOCKBUF_LOCK(&l2so->so_snd);
        l2so->so_snd.sb_flags &= ~SB_UPCALL;
        SOCKBUF_UNLOCK(&l2so->so_snd);
-       l2so->so_state &= ~SS_NBIO;
+       soclrstate(l2so, SS_NBIO);
 
        mtx_destroy(&s->session_mtx);
        bzero(s, sizeof(*s));
@@ -1434,7 +1436,7 @@ ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
        l2so->so_head = NULL;
        SOCK_LOCK(l2so);
        soref(l2so);
-       l2so->so_state |= SS_NBIO;
+       sosetstate(l2so, SS_NBIO);
        SOCK_UNLOCK(l2so);
        ACCEPT_UNLOCK();
 
index 204fff5..3b19fae 100644 (file)
@@ -3068,8 +3068,7 @@ ngb_mod_event(module_t mod, int event, void *data)
                ng_qdzone = uma_zcreate("NetGraph data items", sizeof(struct ng_item),
                    NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
                uma_zone_set_max(ng_qdzone, maxdata);
-               netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL,
-                               NETISR_FLAG_NOTMPSAFE);
+               netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL);
                break;
        case MOD_UNLOAD:
                /* You can't unload it because an interface may be using it. */
@@ -3233,6 +3232,7 @@ SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RW,
 static void
 ngintr(void)
 {
+       XXX replymsg XXX
        for (;;) {
                node_p  node;
 
index 7162da3..0982bee 100644 (file)
@@ -756,7 +756,7 @@ ng_iface_rcvdata(hook_p hook, item_p item)
        /* First chunk of an mbuf contains good junk */
        if (harvest.point_to_point)
                random_harvest(m, 16, 3, 0, RANDOM_NET);
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return (0);
 }
 
index ae1adc1..df5b987 100644 (file)
@@ -121,7 +121,7 @@ ngipi_rcvdata(hook_p hook, item_p item)
 
        NGI_GET_M(item, m);
        NG_FREE_ITEM(item);
-       netisr_dispatch(NETISR_IP, m);
+       netisr_queue(NETISR_IP, m);
        return 0;
 }
 
index 8680bbe..b2b84bb 100644 (file)
@@ -626,7 +626,7 @@ ng_ksocket_connect(hook_p hook)
        priv->so->so_snd.sb_flags |= SB_UPCALL;
        SOCKBUF_UNLOCK(&priv->so->so_snd);
        SOCK_LOCK(priv->so);
-       priv->so->so_state |= SS_NBIO;
+       sosetstate(priv->so, SS_NBIO);
        SOCK_UNLOCK(priv->so);
        /*
         * --Original comment--
@@ -761,7 +761,7 @@ ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
                        if ((so->so_state & SS_ISCONNECTING) != 0)
                                ERROUT(EALREADY);
                        if ((error = soconnect(so, sa, td)) != 0) {
-                               so->so_state &= ~SS_ISCONNECTING;
+                               soclrstate(so, SS_ISCONNECTING);
                                ERROUT(error);
                        }
                        if ((so->so_state & SS_ISCONNECTING) != 0) {
@@ -1050,7 +1050,7 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2)
        if (priv->flags & KSF_CONNECTING) {
                if ((error = so->so_error) != 0) {
                        so->so_error = 0;
-                       so->so_state &= ~SS_ISCONNECTING;
+                       soclrstate(so, SS_ISCONNECTING);
                }
                if (!(so->so_state & SS_ISCONNECTING)) {
                        NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE,
@@ -1211,7 +1211,7 @@ ng_ksocket_finish_accept(priv_p priv)
        so->so_head = NULL;
        SOCK_LOCK(so);
        soref(so);
-       so->so_state |= SS_NBIO;
+       sosetstate(so, SS_NBIO);
        SOCK_UNLOCK(so);
        ACCEPT_UNLOCK();
 
index 237f97a..ed065c1 100644 (file)
@@ -824,9 +824,9 @@ ngs_connect(hook_p hook)
 
        if ((priv->datasock) && (priv->datasock->ng_socket)) {
                if (NG_NODE_NUMHOOKS(node) == 1)
-                       priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
+                       sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
                else
-                       priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
+                       soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
        }
        return (0);
 }
@@ -983,9 +983,9 @@ ngs_disconnect(hook_p hook)
 
        if ((priv->datasock) && (priv->datasock->ng_socket)) {
                if (NG_NODE_NUMHOOKS(node) == 1)
-                       priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
+                       sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
                else
-                       priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
+                       soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
        }
 
        if ((priv->flags & NGS_FLAG_NOLINGER) &&
index 11b86f6..02a4702 100644 (file)
@@ -149,9 +149,6 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW,
 SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
           &arp_proxyall, 0, "Enable proxy ARP for all suitable requests");
 
-static int     arp_mpsafe = 1;
-TUNABLE_INT("net.link.ether.inet.arp_mpsafe", &arp_mpsafe);
-
 static void    arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
 static void    arprequest(struct ifnet *, const struct in_addr *,
                           const struct in_addr *, const u_char *);
@@ -417,7 +414,7 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
 /*
  * Same as arprequest(), except:
  * - Caller is allowed to hold ifp's serializer
- * - Network output is done in TDF_NETWORK kernel thread
+ * - Network output is done in protocol thead
  */
 static void
 arprequest_async(struct ifnet *ifp, const struct in_addr *sip,
@@ -527,7 +524,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
        if (la->la_hold != NULL)
                m_freem(la->la_hold);
        la->la_hold = m;
-       la->la_msgport = curnetport;
+       la->la_msgport = cur_netport();
        if (rt->rt_expire || ((rt->rt_flags & RTF_STATIC) && !sdl->sdl_alen)) {
                rt->rt_flags &= ~RTF_REJECT;
                if (la->la_asked == 0 || rt->rt_expire != time_second) {
@@ -747,8 +744,7 @@ arp_update_oncpu(struct mbuf *m, in_addr_t saddr, boolean_t create,
                        pmsg = &m->m_hdr.mh_netmsg;
                        netmsg_init(&pmsg->nm_netmsg, NULL,
                                    &netisr_apanic_rport,
-                                   MSGF_MPSAFE | MSGF_PRIORITY,
-                                   arp_hold_output);
+                                   MSGF_PRIORITY, arp_hold_output);
                        pmsg->nm_packet = m;
 
                        /* Record necessary information */
@@ -1118,20 +1114,12 @@ arp_iainit(struct ifnet *ifp, const struct in_addr *addr, const u_char *enaddr)
 static void
 arp_init(void)
 {
-       uint32_t flags;
        int cpu;
 
        for (cpu = 0; cpu < ncpus2; cpu++)
                LIST_INIT(&llinfo_arp_list[cpu]);
 
-       if (arp_mpsafe) {
-               flags = NETISR_FLAG_MPSAFE;
-               kprintf("arp: MPSAFE\n");
-       } else {
-               flags = NETISR_FLAG_NOTMPSAFE;
-       }
-       netisr_register(NETISR_ARP, cpu0_portfn, pktinfo_portfn_cpu0,
-                       arpintr, flags);
+       netisr_register(NETISR_ARP, arpintr, NULL);
 }
 
 SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0);
index 1ae4c09..d974704 100644 (file)
@@ -84,7 +84,9 @@
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
+
 #include <sys/thread2.h>
+#include <sys/socketvar2.h>
 
 #include <machine/limits.h>
 
@@ -217,6 +219,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
        if (ip6_auto_flowlabel)
                inp->inp_flags |= IN6P_AUTOFLOWLABEL;
 #endif
+       soreference(so);
        so->so_pcb = inp;
        LIST_INSERT_HEAD(&pcbinfo->pcblisthead, inp, inp_list);
        pcbinfo->ipi_count++;
@@ -648,7 +651,7 @@ in_pcbdetach(struct inpcb *inp)
        inp->inp_gencnt = ++ipi->ipi_gencnt;
        in_pcbremlists(inp);
        so->so_pcb = NULL;
-       sofree(so);
+       sofree(so);                     /* remove pcb ref */
        if (inp->inp_options)
                m_free(inp->inp_options);
        if (inp->inp_route.ro_rt)
index 76d0719..ece006f 100644 (file)
@@ -122,14 +122,15 @@ struct protosw inetsw[] = {
   ip_init,     0,              ip_slowtimo,    ip_drain,
   &nousrreqs
 },
-{ SOCK_DGRAM,  &inetdomain,    IPPROTO_UDP,    PR_ATOMIC|PR_ADDR,
+{ SOCK_DGRAM,  &inetdomain,    IPPROTO_UDP,    PR_ATOMIC|PR_ADDR|PR_MPSAFE,
   udp_input,   0,              udp_ctlinput,   ip_ctloutput,
   udp_soport,  udp_ctlport,
   udp_init,    0,              0,              0,
   &udp_usrreqs
 },
-{ SOCK_STREAM, &inetdomain,    IPPROTO_TCP,
-       PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD,
+{ SOCK_STREAM, &inetdomain,    IPPROTO_TCP,    PR_CONNREQUIRED |
+                                               PR_IMPLOPCL | PR_WANTRCVD |
+                                               PR_MPSAFE,
   tcp_input,   0,              tcp_ctlinput,   tcp_ctloutput,
   tcp_soport,  tcp_ctlport,
   tcp_init,    0,              tcp_slowtimo,   tcp_drain,
index 5a0d164..e3e17d5 100644 (file)
@@ -47,9 +47,7 @@
 
 #include <net/if.h>
 #include <net/netisr.h>
-#ifdef RSS
 #include <net/toeplitz2.h>
-#endif
 
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
 
-extern struct thread netisr_cpu[];
 extern int udp_mpsafe_thread;
 
-static struct thread tcp_thread[MAXCPU];
-static struct thread udp_thread[MAXCPU];
-
-#ifndef RSS
-
-static __inline int
-INP_MPORT_HASH(in_addr_t faddr, in_addr_t laddr,
-              in_port_t fport, in_port_t lport)
-{
-       /*
-        * Use low order bytes.
-        */
-
-#if (BYTE_ORDER == LITTLE_ENDIAN)
-       KASSERT(ncpus2 < 256, ("need different hash function"));  /* XXX JH */
-       return (((faddr >> 24) ^ (fport >> 8) ^ (laddr >> 24) ^ (lport >> 8)) &
-               ncpus2_mask);
-#else
-       return ((faddr ^ fport ^ laddr ^ lport) & ncpus2_mask);
-#endif
-}
-
-#endif /* !RSS */
-
+/*
+ * Toeplitz hash functions - the idea is to match the hardware.
+ */
 static __inline int
 INP_MPORT_HASH_UDP(in_addr_t faddr, in_addr_t laddr,
                   in_port_t fport, in_port_t lport)
 {
-#ifndef RSS
-       return INP_MPORT_HASH(faddr, laddr, fport, lport);
-#else
        return toeplitz_hash(toeplitz_rawhash_addr(faddr, laddr));
-#endif
 }
 
 static __inline int
 INP_MPORT_HASH_TCP(in_addr_t faddr, in_addr_t laddr,
                   in_port_t fport, in_port_t lport)
 {
-#ifndef RSS
-       return INP_MPORT_HASH(faddr, laddr, fport, lport);
-#else
        return toeplitz_hash(
               toeplitz_rawhash_addrport(faddr, laddr, fport, lport));
-#endif
+}
+
+/*
+ * Map a network address to a processor.
+ */
+int
+tcp_addrcpu(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
+{
+       return (INP_MPORT_HASH_TCP(faddr, laddr, fport, lport));
+}
+
+int
+udp_addrcpu(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
+{
+       return (INP_MPORT_HASH_UDP(faddr, laddr, fport, lport));
 }
 
 /*
@@ -135,30 +118,35 @@ INP_MPORT_HASH_TCP(in_addr_t faddr, in_addr_t laddr,
  * o  IP total length is not less than (IP header length + TCP header length).
  */
 boolean_t
-ip_lengthcheck(struct mbuf **mp)
+ip_lengthcheck(struct mbuf **mp, int hoff)
 {
        struct mbuf *m = *mp;
        struct ip *ip;
-       int iphlen, iplen;
+       int len, iphlen, iplen;
        struct tcphdr *th;
        int thoff;                              /* TCP data offset */
 
+       len = hoff + sizeof(struct ip);
+
        /* The packet must be at least the size of an IP header. */
-       if (m->m_pkthdr.len < sizeof(struct ip)) {
+       if (m->m_pkthdr.len < len) {
+               kprintf("pkthdr %d %d < %d\n", (m->m_flags & M_PKTHDR),
+                       m->m_pkthdr.len, len);
                ipstat.ips_tooshort++;
                goto fail;
        }
 
        /* The fixed IP header must reside completely in the first mbuf. */
-       if (m->m_len < sizeof(struct ip)) {
-               m = m_pullup(m, sizeof(struct ip));
+       if (m->m_len < len) {
+               m = m_pullup(m, len);
                if (m == NULL) {
+                       kprintf("can't pullup %d\n", len);
                        ipstat.ips_toosmall++;
                        goto fail;
                }
        }
 
-       ip = mtod(m, struct ip *);
+       ip = mtodoff(m, struct ip *, hoff);
 
        /* Bound check the packet's stated IP header length. */
        iphlen = ip->ip_hl << 2;
@@ -168,13 +156,13 @@ ip_lengthcheck(struct mbuf **mp)
        }
 
        /* The full IP header must reside completely in the one mbuf. */
-       if (m->m_len < iphlen) {
-               m = m_pullup(m, iphlen);
+       if (m->m_len < hoff + iphlen) {
+               m = m_pullup(m, hoff + iphlen);
                if (m == NULL) {
                        ipstat.ips_badhlen++;
                        goto fail;
                }
-               ip = mtod(m, struct ip *);
+               ip = mtodoff(m, struct ip *, hoff);
        }
 
        iplen = ntohs(ip->ip_len);
@@ -183,7 +171,10 @@ ip_lengthcheck(struct mbuf **mp)
         * Check that the amount of data in the buffers is as
         * at least much as the IP header would have us expect.
         */
-       if (m->m_pkthdr.len < iplen) {
+       if (m->m_pkthdr.len < hoff + iplen) {
+               kprintf("data in buffer not enough %d -  %d vs %d+%d\n",
+                       (m->m_flags & M_PKTHDR),
+                       m->m_pkthdr.len, hoff, iplen);
                ipstat.ips_tooshort++;
                goto fail;
        }
@@ -210,13 +201,13 @@ ip_lengthcheck(struct mbuf **mp)
                        ++tcpstat.tcps_rcvshort;
                        goto fail;
                }
-               if (m->m_len < iphlen + sizeof(struct tcphdr)) {
-                       m = m_pullup(m, iphlen + sizeof(struct tcphdr));
+               if (m->m_len < hoff + iphlen + sizeof(struct tcphdr)) {
+                       m = m_pullup(m, hoff + iphlen + sizeof(struct tcphdr));
                        if (m == NULL) {
                                tcpstat.tcps_rcvshort++;
                                goto fail;
                        }
-                       ip = mtod(m, struct ip *);
+                       ip = mtodoff(m, struct ip *, hoff);
                }
                th = (struct tcphdr *)((caddr_t)ip + iphlen);
                thoff = th->th_off << 2;
@@ -225,8 +216,8 @@ ip_lengthcheck(struct mbuf **mp)
                        tcpstat.tcps_rcvbadoff++;
                        goto fail;
                }
-               if (m->m_len < iphlen + thoff) {
-                       m = m_pullup(m, iphlen + thoff);
+               if (m->m_len < hoff + iphlen + thoff) {
+                       m = m_pullup(m, hoff + iphlen + thoff);
                        if (m == NULL) {
                                tcpstat.tcps_rcvshort++;
                                goto fail;
@@ -238,8 +229,8 @@ ip_lengthcheck(struct mbuf **mp)
                        ++udpstat.udps_hdrops;
                        goto fail;
                }
-               if (m->m_len < iphlen + sizeof(struct udphdr)) {
-                       m = m_pullup(m, iphlen + sizeof(struct udphdr));
+               if (m->m_len < hoff + iphlen + sizeof(struct udphdr)) {
+                       m = m_pullup(m, hoff + iphlen + sizeof(struct udphdr));
                        if (m == NULL) {
                                udpstat.udps_hdrops++;
                                goto fail;
@@ -267,13 +258,13 @@ fail:
 }
 
 /*
- * Map a packet to a protocol processing thread and return the thread's port.
- * If an error occurs, the passed mbuf will be freed, *mptr will be set
- * to NULL, and NULL will be returned.  If no error occurs, the passed mbuf
- * may be modified and a port pointer will be returned.
+ * Assign a protocol processing thread to a packet.  The IP header is at
+ * offset (hoff) in the packet (i.e. the mac header might still be intact).
+ *
+ * This function can blow away the mbuf if the packet is malformed.
  */
-lwkt_port_t
-ip_mport(struct mbuf **mptr, int dir)
+void
+ip_cpufn(struct mbuf **mptr, int hoff, int dir)
 {
        struct ip *ip;
        int iphlen;
@@ -281,14 +272,13 @@ ip_mport(struct mbuf **mptr, int dir)
        struct udphdr *uh;
        struct mbuf *m;
        int thoff;                              /* TCP data offset */
-       lwkt_port_t port;
        int cpu;
 
-       if (!ip_lengthcheck(mptr))
-               return (NULL);
+       if (!ip_lengthcheck(mptr, hoff))
+               return;
 
        m = *mptr;
-       ip = mtod(m, struct ip *);
+       ip = mtodoff(m, struct ip *, hoff);
        iphlen = ip->ip_hl << 2;
 
        /*
@@ -296,7 +286,6 @@ ip_mport(struct mbuf **mptr, int dir)
         */
        if (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)) {
                cpu = 0;
-               port = &netisr_cpu[cpu].td_msgport;
                goto back;
        }
 
@@ -304,48 +293,41 @@ ip_mport(struct mbuf **mptr, int dir)
        case IPPROTO_TCP:
                th = (struct tcphdr *)((caddr_t)ip + iphlen);
                thoff = th->th_off << 2;
-               cpu = INP_MPORT_HASH_TCP(ip->ip_src.s_addr, ip->ip_dst.s_addr,
-                   th->th_sport, th->th_dport);
-               port = &tcp_thread[cpu].td_msgport;
+               cpu = INP_MPORT_HASH_TCP(ip->ip_src.s_addr,
+                                        ip->ip_dst.s_addr,
+                                        th->th_sport,
+                                        th->th_dport);
                break;
 
        case IPPROTO_UDP:
                uh = (struct udphdr *)((caddr_t)ip + iphlen);
 
-#ifndef RSS
-               if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
-                   (dir == IP_MPORT_IN &&
-                    in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) {
-                       cpu = 0;
-               } else
-#endif
-               {
-                       cpu = INP_MPORT_HASH_UDP(ip->ip_src.s_addr,
-                           ip->ip_dst.s_addr, uh->uh_sport, uh->uh_dport);
-               }
-               port = &udp_thread[cpu].td_msgport;
+               cpu = INP_MPORT_HASH_UDP(ip->ip_src.s_addr,
+                                        ip->ip_dst.s_addr,
+                                        uh->uh_sport,
+                                        uh->uh_dport);
                break;
 
        default:
                cpu = 0;
-               port = &netisr_cpu[cpu].td_msgport;
                break;
        }
 back:
        m->m_flags |= M_HASH;
        m->m_pkthdr.hash = cpu;
-       return (port);
 }
 
-lwkt_port_t
-ip_mport_in(struct mbuf **mptr)
+void
+ip_cpufn_in(struct mbuf **mptr, int hoff)
 {
-       return ip_mport(mptr, IP_MPORT_IN);
+       ip_cpufn(mptr, hoff, IP_MPORT_IN);
 }
 
+#if 0
+
 /*
  * Map a packet to a protocol processing thread and return the thread's port.
- * Unlike ip_mport(), the packet content is not accessed.  The packet info
+ * Unlike ip_cpufn(), the packet content is not accessed.  The packet info
  * (pi) and the hash of the packet (m_pkthdr.hash) is used instead.  NULL is
  * returned if the packet info does not contain enough information.
  *
@@ -365,16 +347,16 @@ ip_mport_pktinfo(const struct pktinfo *pi, struct mbuf *m)
         */
        if (pi->pi_flags & PKTINFO_FLAG_FRAG) {
                m->m_pkthdr.hash = 0;
-               return &netisr_cpu[0].td_msgport;
+               return cpu_portfn(0);
        }
 
        switch (pi->pi_l3proto) {
        case IPPROTO_TCP:
-               port = &tcp_thread[m->m_pkthdr.hash].td_msgport;
+               port = cpu_portfn(m->m_pkthdr.hash);
                break;
 
        case IPPROTO_UDP:
-               port = &udp_thread[m->m_pkthdr.hash].td_msgport;
+               port = cpu_portfn(m->m_pkthdr.hash);
                break;
 
        default:
@@ -384,6 +366,8 @@ ip_mport_pktinfo(const struct pktinfo *pi, struct mbuf *m)
        return port;
 }
 
+#endif
+
 /*
  * Initital port when creating the socket, generally before
  * binding or connect.
@@ -391,7 +375,7 @@ ip_mport_pktinfo(const struct pktinfo *pi, struct mbuf *m)
 lwkt_port_t
 tcp_soport_attach(struct socket *so)
 {
-       return(&tcp_thread[0].td_msgport);
+       return(cpu_portfn(0));
 }
 
 /*
@@ -442,27 +426,25 @@ tcp_ctlport(int cmd, struct sockaddr *sa, void *vip)
                cpu = tcp_addrcpu(faddr.s_addr, th->th_dport,
                                  ip->ip_src.s_addr, th->th_sport);
        }
-       return(&tcp_thread[cpu].td_msgport);
+       return(cpu_portfn(cpu));
 }
 
 lwkt_port_t
 tcp_addrport(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
 {
-       return (&tcp_thread[tcp_addrcpu(faddr, fport,
-                                       laddr, lport)].td_msgport);
+       return(cpu_portfn(tcp_addrcpu(faddr, fport, laddr, lport)));
 }
 
 lwkt_port_t
 tcp_addrport0(void)
 {
-       return (&tcp_thread[0].td_msgport);
+       return(cpu_portfn(0));
 }
 
 lwkt_port_t
 udp_addrport(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
 {
-       return (&udp_thread[udp_addrcpu(faddr, fport,
-                                       laddr, lport)].td_msgport);
+       return(cpu_portfn(udp_addrcpu(faddr, fport, laddr, lport)));
 }
 
 /*
@@ -472,7 +454,7 @@ udp_addrport(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
 lwkt_port_t
 udp_soport_attach(struct socket *so)
 {
-       return(&udp_thread[0].td_msgport);
+       return(cpu_portfn(0));
 }
 
 /*
@@ -523,66 +505,5 @@ udp_ctlport(int cmd, struct sockaddr *sa, void *vip)
                cpu = INP_MPORT_HASH_UDP(faddr.s_addr, ip->ip_src.s_addr,
                                         uh->uh_dport, uh->uh_sport);
        }
-       return (&udp_thread[cpu].td_msgport);
-}
-
-/*
- * Map a network address to a processor.
- */
-int
-tcp_addrcpu(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
-{
-       return (INP_MPORT_HASH_TCP(faddr, laddr, fport, lport));
-}
-
-int
-udp_addrcpu(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
-{
-#ifndef RSS
-       if (IN_MULTICAST(ntohl(laddr)))
-               return (0);
-       else
-#endif
-               return (INP_MPORT_HASH_UDP(faddr, laddr, fport, lport));
-}
-
-/*
- * Return LWKT port for cpu.
- */
-lwkt_port_t
-tcp_cport(int cpu)
-{
-       return (&tcp_thread[cpu].td_msgport);
-}
-
-lwkt_port_t
-udp_cport(int cpu)
-{
-       return (&udp_thread[cpu].td_msgport);
-}
-
-void
-tcp_thread_init(void)
-{
-       int cpu;
-
-       for (cpu = 0; cpu < ncpus2; cpu++) {
-               lwkt_create(tcpmsg_service_loop, NULL, NULL,
-                           &tcp_thread[cpu], TDF_NETWORK, cpu,
-                           "tcp_thread %d", cpu);
-               netmsg_service_port_init(&tcp_thread[cpu].td_msgport);
-       }
-}
-
-void
-udp_thread_init(void)
-{
-       int cpu;
-
-       for (cpu = 0; cpu < ncpus2; cpu++) {
-               lwkt_create(netmsg_service_loop, &udp_mpsafe_thread, NULL,
-                           &udp_thread[cpu], TDF_NETWORK, cpu,
-                           "udp_thread %d", cpu);
-               netmsg_service_port_init(&udp_thread[cpu].td_msgport);
-       }
+       return (cpu_portfn(cpu));
 }
index 07b2c47..4018d48 100644 (file)
@@ -126,6 +126,8 @@ static u_long       div_recvspace = DIVRCVQ;        /* XXX sysctl ? */
 
 static struct mbuf *ip_divert(struct mbuf *, int, int);
 
+static struct lwkt_token div_token = LWKT_TOKEN_MP_INITIALIZER(div_token);
+
 /*
  * Initialize divert connection block queue.
  */
@@ -215,7 +217,16 @@ div_soport(struct socket *so, struct sockaddr *nam, struct mbuf **mptr)
                m->m_pkthdr.rcvif = ifa->ifa_ifp;
        }
 
-       return ip_mport(mptr, dir);
+       /*
+        * Recalculate the protocol thread.
+        */
+       ip_cpufn(mptr, 0, dir);
+       m = *mptr;
+       if (m) {
+               KKASSERT(m->m_flash & M_HASH);
+               return(cpu_portfn(m->m_pkthdr.hash));
+       }
+       return(NULL);
 }
 
 /*
@@ -298,7 +309,7 @@ div_packet(struct mbuf *m, int incoming, int port)
         * saving/testing the socket pointer is not MPSAFE.  So we still
         * need to hold BGL here.
         */
-       get_mplock();
+       lwkt_gettoken(&div_token);
        LIST_FOREACH(inp, &divcbinfo.pcblisthead, inp_list) {
                if (inp->inp_flags & INP_PLACEMARKER)
                        continue;
@@ -306,18 +317,18 @@ div_packet(struct mbuf *m, int incoming, int port)
                        sa = inp->inp_socket;
        }
        if (sa) {
-               if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m,
-                                NULL) == 0)
+               lwkt_gettoken(&sa->so_rcv.ssb_token);
+               if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, NULL) == 0)
                        m_freem(m);
                else
                        sorwakeup(sa);
-               rel_mplock();
+               lwkt_reltoken(&sa->so_rcv.ssb_token);
        } else {
-               rel_mplock();
                m_freem(m);
                ipstat.ips_noproto++;
                ipstat.ips_delivered--;
        }
+       lwkt_reltoken(&div_token);
 }
 
 #ifdef SMP
@@ -369,7 +380,7 @@ divert_packet(struct mbuf *m, int incoming)
 
                nmp = &m->m_hdr.mh_netmsg;
                netmsg_init(&nmp->nm_netmsg, NULL, &netisr_apanic_rport,
-                   MSGF_MPSAFE, div_packet_handler);
+                           0, div_packet_handler);
                nmp->nm_packet = m;
 
                msg = &nmp->nm_netmsg.nm_lmsg;
@@ -467,9 +478,12 @@ div_attach(struct socket *so, int proto, struct pru_attach_info *ai)
        error = soreserve(so, div_sendspace, div_recvspace, ai->sb_rlimit);
        if (error)
                return error;
+       lwkt_gettoken(&div_token);
        error = in_pcballoc(so, &divcbinfo);
-       if (error)
+       if (error) {
+               lwkt_reltoken(&div_token);
                return error;
+       }
        inp = (struct inpcb *)so->so_pcb;
        inp->inp_ip_p = proto;
        inp->inp_vflag |= INP_IPV4;
@@ -479,7 +493,8 @@ div_attach(struct socket *so, int proto, struct pru_attach_info *ai)
         * we always know "where" to send the packet.
         */
        so->so_port = cpu0_soport(so, NULL, NULL);
-       so->so_state |= SS_ISCONNECTED;
+       sosetstate(so, SS_ISCONNECTED);
+       lwkt_reltoken(&div_token);
        return 0;
 }
 
@@ -495,19 +510,33 @@ div_detach(struct socket *so)
        return 0;
 }
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 div_abort(struct socket *so)
 {
+       int error;
+
        soisdisconnected(so);
-       return div_detach(so);
+       error = div_detach(so);
+
+       return error;
 }
 
 static int
 div_disconnect(struct socket *so)
 {
+       int error;
+
        if (!(so->so_state & SS_ISCONNECTED))
                return ENOTCONN;
-       return div_abort(so);
+       soreference(so);
+       error = div_abort(so);
+       sofree(so);
+
+       return error;
 }
 
 static int
@@ -543,7 +572,7 @@ static int
 div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
         struct mbuf *control, struct thread *td)
 {
-       /* Length check already done in ip_mport() */
+       /* Length check already done in ip_cpufn() */
        KASSERT(m->m_len >= sizeof(struct ip), ("IP header not in one mbuf"));
 
        /* Send packet */
index 7603027..5c8f19b 100644 (file)
@@ -204,7 +204,7 @@ ipflow_fastforward(struct mbuf *m)
        if (m->m_flags & (M_BCAST | M_MCAST))
                return 0;
 
-       /* length checks already done in ip_mport() */
+       /* length checks already done in ip_cpufn() */
        KASSERT(m->m_len >= sizeof(struct ip), ("IP header not in one mbuf"));
        ip = mtod(m, struct ip *);
 
@@ -215,7 +215,7 @@ ipflow_fastforward(struct mbuf *m)
                return 0;
 
        iplen = ntohs(ip->ip_len);
-       /* length checks already done in ip_mport() */
+       /* length checks already done in ip_cpufn() */
        KASSERT(iplen >= sizeof(struct ip),
                ("total length less then header length"));
        KASSERT(m->m_pkthdr.len >= iplen, ("mbuf too short"));
@@ -573,7 +573,7 @@ ipflow_init(void)
 
        for (i = 0; i < ncpus; ++i) {
                netmsg_init(&ipflow_timo_netmsgs[i], NULL, &netisr_adone_rport,
-                           MSGF_MPSAFE, ipflow_timo_dispatch);
+                           0, ipflow_timo_dispatch);
 
                ksnprintf(oid_name, sizeof(oid_name), "inuse%d", i);
 
index 4eba6de..7ecf5cb 100644 (file)
@@ -206,7 +206,7 @@ gre_input2(struct mbuf *m ,int hlen, u_char proto)
                bpf_ptap(sc->sc_if.if_bpf, m, &af, sizeof(af));
 
        m->m_pkthdr.rcvif = &sc->sc_if;
-       netisr_dispatch(isr, m);
+       netisr_queue(isr, m);
        return(1);      /* packet is done, no further processing needed */
 }
 
@@ -278,7 +278,7 @@ gre_mobile_input(struct mbuf *m, ...)
 
        m->m_pkthdr.rcvif = &sc->sc_if;
 
-       netisr_dispatch(NETISR_IP, m);
+       netisr_queue(NETISR_IP, m);
 }
 
 /*
index 428f217..171a39f 100644 (file)
@@ -140,9 +140,6 @@ int rsvp_on = 0;
 static int ip_rsvp_on;
 struct socket *ip_rsvpd;
 
-int ip_mpsafe = 1;
-TUNABLE_INT("net.inet.ip.mpsafe", &ip_mpsafe);
-
 int ipforwarding = 0;
 SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW,
     &ipforwarding, 0, "Enable IP forwarding between interfaces");
@@ -206,15 +203,25 @@ static int ip_checkinterface = 0;
 SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW,
     &ip_checkinterface, 0, "Verify packet arrives on correct interface");
 
+static int ip_dispatch_fast = 0;
+static int ip_dispatch_slow = 0;
+static int ip_dispatch_recheck = 0;
+static int ip_dispatch_software = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, dispatch_fast_count, CTLFLAG_RW,
+          &ip_dispatch_fast, 0, "");
+SYSCTL_INT(_net_inet_ip, OID_AUTO, dispatch_slow_count, CTLFLAG_RW,
+          &ip_dispatch_slow, 0, "");
+SYSCTL_INT(_net_inet_ip, OID_AUTO, dispatch_software_count, CTLFLAG_RW,
+          &ip_dispatch_software, 0, "");
+SYSCTL_INT(_net_inet_ip, OID_AUTO, dispatch_recheck_count, CTLFLAG_RW,
+          &ip_dispatch_recheck, 0, "");
+
 static struct lwkt_token ipq_token = LWKT_TOKEN_MP_INITIALIZER(ipq_token);
 
 #ifdef DIAGNOSTIC
 static int ipprintfs = 0;
 #endif
 
-extern int udp_mpsafe_proto;
-extern int tcp_mpsafe_proto;
-
 extern struct domain inetdomain;
 extern struct protosw inetsw[];
 u_char ip_protox[IPPROTO_MAX];
@@ -315,7 +322,6 @@ void
 ip_init(void)
 {
        struct protosw *pr;
-       uint32_t flags;
        int i;
 #ifdef SMP
        int cpu;
@@ -342,19 +348,6 @@ ip_init(void)
                if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol) {
                        if (pr->pr_protocol != IPPROTO_RAW)
                                ip_protox[pr->pr_protocol] = pr - inetsw;
-
-                       /* XXX */
-                       switch (pr->pr_protocol) {
-                       case IPPROTO_TCP:
-                               if (tcp_mpsafe_proto)
-                                       pr->pr_flags |= PR_MPSAFE;
-                               break;
-
-                       case IPPROTO_UDP:
-                               if (udp_mpsafe_proto)
-                                       pr->pr_flags |= PR_MPSAFE;
-                               break;
-                       }
                }
        }
 
@@ -385,19 +378,7 @@ ip_init(void)
        bzero(&ipstat, sizeof(struct ip_stats));
 #endif
 
-#if defined(IPSEC) || defined(FAST_IPSEC)
-       /* XXX IPSEC is not MPSAFE yet */
-       flags = NETISR_FLAG_NOTMPSAFE;
-#else
-       if (ip_mpsafe) {
-               kprintf("ip: MPSAFE\n");
-               flags = NETISR_FLAG_MPSAFE;
-       } else {
-               flags = NETISR_FLAG_NOTMPSAFE;
-       }
-#endif
-       netisr_register(NETISR_IP, ip_mport_in, ip_mport_pktinfo,
-                       ip_input_handler, flags);
+       netisr_register(NETISR_IP, ip_input_handler, ip_cpufn_in);
 }
 
 /* Do transport protocol processing. */
@@ -464,16 +445,16 @@ ip_input(struct mbuf *m)
        M_ASSERTPKTHDR(m);
 
        /*
-        * This does necessary pullups and figures out the protocol
-        * port.  If the packet is really badly formed it will blow
-        * it away and return NULL.
-        *
-        * We do not necessarily make use of the port (forwarding,
-        * defragmentation, etc).
+        * This routine is called from numerous places which may not have
+        * characterized the packet.
         */
-       port = ip_mport(&m, IP_MPORT_IN);
-       if (port == NULL)
-               return;
+       if ((m->m_flags & M_HASH) == 0) {
+               ++ip_dispatch_software;
+               ip_cpufn(&m, 0, IP_MPORT_IN);
+               if (m == NULL)
+                       return;
+               KKASSERT(m->m_flags & M_HASH);
+       }
        ip = mtod(m, struct ip *);
 
        /*
@@ -495,7 +476,7 @@ ip_input(struct mbuf *m)
 
        ipstat.ips_total++;
 
-       /* length checks already done in ip_mport() */
+       /* length checks already done in ip_cpufn() */
        KASSERT(m->m_len >= sizeof(struct ip), ("IP header not in one mbuf"));
 
        if (IP_VHL_V(ip->ip_vhl) != IPVERSION) {
@@ -504,7 +485,7 @@ ip_input(struct mbuf *m)
        }
 
        hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-       /* length checks already done in ip_mport() */
+       /* length checks already done in ip_cpufn() */
        KASSERT(hlen >= sizeof(struct ip), ("IP header len too small"));
        KASSERT(m->m_len >= hlen, ("complete IP header not in one mbuf"));
 
@@ -542,7 +523,7 @@ ip_input(struct mbuf *m)
        ip->ip_len = ntohs(ip->ip_len);
        ip->ip_off = ntohs(ip->ip_off);
 
-       /* length checks already done in ip_mport() */
+       /* length checks already done in ip_cpufn() */
        KASSERT(ip->ip_len >= hlen, ("total length less then header length"));
        KASSERT(m->m_pkthdr.len >= ip->ip_len, ("mbuf too short"));
 
@@ -602,9 +583,8 @@ iphack:
        /*
         * Run through list of hooks for input packets.
         *
-        * NB: Beware of the destination address changing (e.g.
-        *     by NAT rewriting). When this happens, tell
-        *     ip_forward to do the right thing.
+        * NOTE!  If the packet is rewritten pf/ipfw/whoever must
+        *        clear M_HASH.
         */
        odst = ip->ip_dst;
        if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN))
@@ -870,8 +850,11 @@ ours:
         */
        if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
                /*
-                * Attempt reassembly; if it succeeds, proceed.
-                * ip_reass() will return a different mbuf.
+                * Attempt reassembly; if it succeeds, proceed.  ip_reass()
+                * will return a different mbuf.
+                *
+                * NOTE: ip_reass() returns m with M_HASH cleared to force
+                *       us to recharacterize the packet.
                 */
                m = ip_reass(m);
                if (m == NULL)
@@ -937,25 +920,45 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
 #endif /* FAST_IPSEC */
 
        /*
-        * NOTE: ip_len is now in host form and adjusted down by hlen for
-        *       protocol processing.
-        *
         * We must forward the packet to the correct protocol thread if
         * we are not already in it.
+        *
+        * NOTE: ip_len is now in host form.  ip_len is not adjusted
+        *       further for protocol processing, instead we pass hlen
+        *       to the protosw and let it deal with it.
         */
        ipstat.ips_delivered++;
 
+       if ((m->m_flags & M_HASH) == 0) {
+               ++ip_dispatch_recheck;
+               ip->ip_len = htons(ip->ip_len);
+               ip->ip_off = htons(ip->ip_off);
+
+               ip_cpufn(&m, 0, IP_MPORT_IN);
+               if (m == NULL)
+                       return;
+
+               ip = mtod(m, struct ip *);
+               ip->ip_len = ntohs(ip->ip_len);
+               ip->ip_off = ntohs(ip->ip_off);
+               KKASSERT(m->m_flags & M_HASH);
+       }
+       port = cpu_portfn(m->m_pkthdr.hash);
+
        if (port != &curthread->td_msgport) {
                struct netmsg_packet *pmsg;
 
+               ++ip_dispatch_slow;
+
                pmsg = &m->m_hdr.mh_netmsg;
                netmsg_init(&pmsg->nm_netmsg, NULL, &netisr_apanic_rport,
-                           MSGF_MPSAFE, transport_processing_handler);
+                           0, transport_processing_handler);
                pmsg->nm_packet = m;
                pmsg->nm_netmsg.nm_lmsg.u.ms_result = hlen;
 
                lwkt_sendmsg(port, &pmsg->nm_netmsg.nm_lmsg);
        } else {
+               ++ip_dispatch_fast;
                transport_processing_oncpu(m, hlen, ip);
        }
        return;
@@ -1242,6 +1245,16 @@ inserted:
                m->m_pkthdr.len = plen;
        }
 
+       /*
+        * Reassembly complete, return the next protocol.
+        *
+        * Be sure to clear M_HASH to force the packet
+        * to be re-characterized.
+        *
+        * Clear M_FRAG, we are no longer a fragment.
+        */
+       m->m_flags &= ~(M_HASH | M_FRAG);
+
        ipstat.ips_reassembled++;
        lwkt_reltoken(&ipq_token);
        return (m);
index 8be331b..140ccba 100644 (file)
@@ -169,7 +169,7 @@ extern struct ip_stats      ipstats_percpu[MAXCPU];
 #define        IP_ALLOWBROADCAST       SO_BROADCAST    /* can send broadcast packets */
 #define        IP_DEBUGROUTE           0x10000         /* debug route */
 
-/* direction passed to ip_mport as last parameter */
+/* direction passed to ip_cpufn as last parameter */
 #define IP_MPORT_IN            0 /* Find lwkt port for incoming packets */
 #define IP_MPORT_OUT           1 /* Find lwkt port for outgoing packets */
 
@@ -202,12 +202,11 @@ void       ip_init(void);
 extern int      (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
                          struct ip_moptions *);
 
-struct lwkt_port *ip_mport(struct mbuf **, int);
-struct lwkt_port *ip_mport_in(struct mbuf **);
-struct lwkt_port *ip_mport_pktinfo(const struct pktinfo *, struct mbuf *);
+void   ip_cpufn(struct mbuf **, int, int);
+void   ip_cpufn_in(struct mbuf **, int);
 
 boolean_t
-        ip_lengthcheck(struct mbuf **);
+        ip_lengthcheck(struct mbuf **, int);
 int     ip_output(struct mbuf *,
            struct mbuf *, struct route *, int, struct ip_moptions *,
            struct inpcb *);
index 80b1b9b..20be825 100644 (file)
@@ -50,7 +50,9 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
+
 #include <sys/thread2.h>
+#include <sys/socketvar2.h>
 
 #include <machine/stdarg.h>
 
@@ -83,6 +85,9 @@ struct        inpcbinfo ripcbinfo;
 ip_fw_ctl_t *ip_fw_ctl_ptr;
 ip_dn_ctl_t *ip_dn_ctl_ptr;
 
+static struct lwkt_token raw_token = LWKT_TOKEN_MP_INITIALIZER(raw_token);
+
+
 /*
  * hooks for multicast routing. They all default to NULL,
  * so leave them not initialized and rely on BSS being set to 0.
@@ -156,6 +161,7 @@ rip_input(struct mbuf *m, ...)
        __va_end(ap);
 
        ripsrc.sin_addr = ip->ip_src;
+       lwkt_gettoken(&raw_token);
        LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) {
                if (inp->inp_flags & INP_PLACEMARKER)
                        continue;
@@ -190,18 +196,21 @@ rip_input(struct mbuf *m, ...)
                        } else
 #endif /*FAST_IPSEC*/
                        if (n) {
+                               lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
                                if (last->inp_flags & INP_CONTROLOPTS ||
                                    last->inp_socket->so_options & SO_TIMESTAMP)
                                    ip_savecontrol(last, &opts, ip, n);
                                if (ssb_appendaddr(&last->inp_socket->so_rcv,
-                                   (struct sockaddr *)&ripsrc, n,
-                                   opts) == 0) {
+                                           (struct sockaddr *)&ripsrc, n,
+                                           opts) == 0) {
                                        /* should notify about lost packet */
                                        m_freem(n);
                                        if (opts)
                                            m_freem(opts);
-                               } else
+                               } else {
                                        sorwakeup(last->inp_socket);
+                               }
+                               lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
                                opts = 0;
                        }
                }
@@ -232,18 +241,22 @@ rip_input(struct mbuf *m, ...)
                if (last->inp_flags & INP_CONTROLOPTS ||
                    last->inp_socket->so_options & SO_TIMESTAMP)
                        ip_savecontrol(last, &opts, ip, m);
+               lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
                if (ssb_appendaddr(&last->inp_socket->so_rcv,
                    (struct sockaddr *)&ripsrc, m, opts) == 0) {
                        m_freem(m);
                        if (opts)
                            m_freem(opts);
-               } else
+               } else {
                        sorwakeup(last->inp_socket);
+               }
+               lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
        } else {
                m_freem(m);
                ipstat.ips_noproto++;
                ipstat.ips_delivered--;
        }
+       lwkt_reltoken(&raw_token);
 }
 
 /*
@@ -538,15 +551,15 @@ rip_attach(struct socket *so, int proto, struct pru_attach_info *ai)
        error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit);
        if (error)
                return error;
-       crit_enter();
+       lwkt_gettoken(&raw_token);
        error = in_pcballoc(so, &ripcbinfo);
-       crit_exit();
-       if (error)
-               return error;
-       inp = (struct inpcb *)so->so_pcb;
-       inp->inp_vflag |= INP_IPV4;
-       inp->inp_ip_p = proto;
-       inp->inp_ip_ttl = ip_defttl;
+       if (error == 0) {
+               inp = (struct inpcb *)so->so_pcb;
+               inp->inp_vflag |= INP_IPV4;
+               inp->inp_ip_p = proto;
+               inp->inp_ip_ttl = ip_defttl;
+       }
+       lwkt_reltoken(&raw_token);
        return 0;
 }
 
@@ -568,21 +581,36 @@ rip_detach(struct socket *so)
        return 0;
 }
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 rip_abort(struct socket *so)
 {
+       int error;
+
        soisdisconnected(so);
-       if (so->so_state & SS_NOFDREF)
-               return rip_detach(so);
-       return 0;
+       if (so->so_state & SS_NOFDREF)  /* XXX not sure why this test */
+               error = rip_detach(so);
+       else
+               error = 0;
+
+       return error;
 }
 
 static int
 rip_disconnect(struct socket *so)
 {
+       int error;
+
        if ((so->so_state & SS_ISCONNECTED) == 0)
                return ENOTCONN;
-       return rip_abort(so);
+       soreference(so);
+       error = rip_abort(so);
+       sofree(so);
+
+       return error;
 }
 
 static int
index be68768..e1d5c13 100644 (file)
@@ -459,6 +459,7 @@ sctp_deliver_data(struct sctp_tcb *stcb, struct sctp_association *asoc,
                        }
                        goto skip;
                }
+               lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
                if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
                    to, chk->data, control, stcb->asoc.my_vtag,
                    stcb->sctp_ep)) {
@@ -479,13 +480,16 @@ sctp_deliver_data(struct sctp_tcb *stcb, struct sctp_association *asoc,
                        }
                        free_it = 1;
                }
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        } else {
                /* append to a already started message. */
+               lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
                if (sctp_sbspace(&stcb->sctp_socket->so_rcv) >=
                    (long)chk->send_size) {
                        ssb_append(&stcb->sctp_socket->so_rcv, chk->data);
                        free_it = 1;
                }
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        }
  skip:
        if (hold_locks == 0)
@@ -684,6 +688,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc, in
                                        SCTP_INP_WUNLOCK(stcb->sctp_ep);
                                return;
                        }
+                       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
                        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
                                                  to, chk->data, control, stcb->asoc.my_vtag,
                                                  stcb->sctp_ep)) {
@@ -697,8 +702,10 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc, in
                                               stcb->sctp_socket);
                                if (hold_locks == 0)
                                        SCTP_INP_WUNLOCK(stcb->sctp_ep);
+                               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                                return;
                        }
+                       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                        if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) {
                                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
                                        stcb->asoc.my_rwnd_control_len +=
@@ -711,7 +718,9 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc, in
                } else {
                        if (sctp_sbspace(&stcb->sctp_socket->so_rcv) >=
                            (long)chk->send_size) {
+                               lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
                                ssb_append(&stcb->sctp_socket->so_rcv, chk->data);
+                               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                                cntDel++;
                        } else {
                                /* out of space in the sb */
@@ -1996,6 +2005,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
                SCTP_TCB_UNLOCK(stcb);
                SCTP_INP_WLOCK(stcb->sctp_ep);
                SCTP_TCB_LOCK(stcb);
+               lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
                if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to, dmbuf,
                    control, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                        if (control) {
@@ -2004,8 +2014,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
                                    CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
                        }
                        sctp_m_freem(dmbuf);
+                       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                        goto failed_express_del;
                }
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) {
                        if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
                                stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
index fbe20f8..750d112 100644 (file)
@@ -591,7 +591,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
 #if defined(__FreeBSD__) && __FreeBSD_version >= 502115
                        stcb->sctp_ep->sctp_socket->so_rcv.sb_state |= SBS_CANTSENDMORE;
 #else
-                       stcb->sctp_ep->sctp_socket->so_state |= SS_CANTSENDMORE;
+                       sosetstate(stcb->sctp_ep->sctp_socket, SS_CANTSENDMORE);
 #endif
                }
                /* reset time */
index bca9e66..96b3032 100644 (file)
@@ -2237,13 +2237,11 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate)
 #endif
        int cnt;
 
-       crit_enter();
        SCTP_ASOC_CREATE_LOCK(inp);
        SCTP_INP_WLOCK(inp);
 
        if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
                /* been here before */
-               crit_exit();
                kprintf("Endpoint was all gone (dup free)?\n");
                SCTP_INP_WUNLOCK(inp);
                SCTP_ASOC_CREATE_UNLOCK(inp);
@@ -2333,7 +2331,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate)
                /* now is there some left in our SHUTDOWN state? */
                if (cnt_in_sd) {
                        inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE;
-                       crit_exit();
                        SCTP_INP_WUNLOCK(inp);
                        SCTP_ASOC_CREATE_UNLOCK(inp);
                        return;
@@ -2359,7 +2356,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate)
 #ifdef IPSEC
 #ifdef __OpenBSD__
        /* XXX IPsec cleanup here */
-               crit_enter();
                if (ip_pcb->inp_tdb_in)
                    TAILQ_REMOVE(&ip_pcb->inp_tdb_in->tdb_inp_in,
                                 ip_pcb, inp_tdb_in_next);
@@ -2378,7 +2374,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate)
                    ipsp_reffree(ip_pcb->inp_ipsec_localauth);
                if (ip_pcb->inp_ipsec_remoteauth)
                    ipsp_reffree(ip_pcb->inp_ipsec_remoteauth);
-               crit_exit();
 #else
                ipsec4_delete_pcbpolicy(ip_pcb);
 #endif
@@ -2387,12 +2382,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate)
                ACCEPT_LOCK();
                SOCK_LOCK(so);
 #endif
-               so->so_pcb = 0;
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
-               sotryfree(so);
-#else
+               so->so_pcb = NULL;
                sofree(so);
-#endif
        }
 
        if (ip_pcb->inp_options) {
@@ -2516,7 +2507,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate)
        sctppcbinfo.ipi_count_ep--;
 
        SCTP_INP_INFO_WUNLOCK();
-       crit_exit();
 }
 
 
@@ -3319,11 +3309,9 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
        struct sctp_socket_q_list *sq;
 
        /* first, lets purge the entry from the hash table. */
-       crit_enter();
        if (stcb->asoc.state == 0) {
                kprintf("Freeing already free association:%p - huh??\n",
                    stcb);
-               crit_exit();
                return;
        }
        asoc = &stcb->asoc;
@@ -3627,7 +3615,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
        if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
                sctp_inpcb_free(inp, 0);
        }
-       crit_exit();
 }
 
 
@@ -3923,11 +3910,9 @@ int
 sctp_insert_laddr(struct sctpladdr *list, struct ifaddr *ifa) {
        struct sctp_laddr *laddr;
 
-       crit_enter();
        laddr = (struct sctp_laddr *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr);
        if (laddr == NULL) {
                /* out of memory? */
-               crit_exit();
                return (EINVAL);
        }
        sctppcbinfo.ipi_count_laddr++;
@@ -3937,7 +3922,6 @@ sctp_insert_laddr(struct sctpladdr *list, struct ifaddr *ifa) {
        /* insert it */
        LIST_INSERT_HEAD(list, laddr, sctp_nxt_addr);
 
-       crit_exit();
        return (0);
 }
 
@@ -3947,13 +3931,11 @@ sctp_insert_laddr(struct sctpladdr *list, struct ifaddr *ifa) {
 void
 sctp_remove_laddr(struct sctp_laddr *laddr)
 {
-       crit_enter();
        /* remove from the list */
        LIST_REMOVE(laddr, sctp_nxt_addr);
        SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
        sctppcbinfo.ipi_count_laddr--;
        sctppcbinfo.ipi_gencnt_laddr++;
-       crit_exit();
 }
 
 /*
@@ -5065,9 +5047,7 @@ sctp_initiate_iterator(asoc_func af, uint32_t pcb_state, uint32_t asoc_state,
        SCTP_INP_INFO_WLOCK();
        LIST_INSERT_HEAD(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
        SCTP_INP_INFO_WUNLOCK();
-       crit_enter();
        sctp_iterator_timer(it);
-       crit_exit();
        return (0);
 }
 
@@ -5089,7 +5069,6 @@ callout_init(struct callout *c)
 void
 callout_reset(struct callout *c, int to_ticks, void (*ftn)(void *), void *arg)
 {
-       crit_enter();
        if (c->c_flags & CALLOUT_PENDING)
                callout_stop(c);
 
@@ -5111,19 +5090,16 @@ callout_reset(struct callout *c, int to_ticks, void (*ftn)(void *), void *arg)
        c->c_time = ticks + to_ticks;
        TAILQ_INSERT_TAIL(&sctppcbinfo.callqueue, c, tqe);
 #endif
-       crit_exit();
 }
 
 int
 callout_stop(struct callout *c)
 {
-       crit_enter();
        /*
         * Don't attempt to delete a callout that's not on the queue.
         */
        if (!(c->c_flags & CALLOUT_PENDING)) {
                c->c_flags &= ~CALLOUT_ACTIVE;
-               crit_exit();
                return (0);
        }
        c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING| CALLOUT_FIRED);
@@ -5134,7 +5110,6 @@ callout_stop(struct callout *c)
        TAILQ_REMOVE(&sctppcbinfo.callqueue, c, tqe);
        c->c_func = NULL;
 #endif
-       crit_exit();
        return (1);
 }
 
@@ -5146,7 +5121,6 @@ sctp_fasttim(void)
        struct calloutlist locallist;
        int inited = 0;
 
-       crit_enter();
        /* run through and subtract and mark all callouts */
        c = TAILQ_FIRST(&sctppcbinfo.callqueue);
        while (c) {
@@ -5173,14 +5147,11 @@ sctp_fasttim(void)
                        /* now validate that it did not get canceled */
                        if (c->c_flags & CALLOUT_FIRED) {
                                c->c_flags &= ~CALLOUT_PENDING;
-                               crit_exit();
                                (*c->c_func)(c->c_arg);
-                               crit_enter();
                        }
                        c = TAILQ_FIRST(&locallist);
                }
        }
-       crit_exit();
 }
 #endif
 #endif /* _SCTP_NEEDS_CALLOUT_ */
index 77395c9..63f053f 100644 (file)
@@ -187,12 +187,14 @@ sctp_get_peeloff(struct socket *head, caddr_t assoc_id, int *error)
            SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */
            (SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
        n_inp->sctp_socket = newso;
-       newso->so_state |= SS_ISCONNECTED;
+       sosetstate(newso, SS_ISCONNECTED);
        /* We remove it right away */
 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
        SOCK_LOCK(head);
+       lwkt_gettoken(&head->so_rcv.ssb_token);
        TAILQ_REMOVE(&head->so_comp, newso, so_list);
        head->so_qlen--;
+       lwkt_reltoken(&head->so_rcv.ssb_token);
        SOCK_UNLOCK(head);
 #else
 
index cf09ad2..20fce83 100644 (file)
@@ -697,19 +697,24 @@ SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW,
 #endif /* SCTP_DEBUG */
 #endif
 
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ *      will sofree() it when we return.
+ */
 static int
 sctp_abort(struct socket *so)
 {
        struct sctp_inpcb *inp;
+       int error;
 
        inp = (struct sctp_inpcb *)so->so_pcb;
-       if (inp == 0)
-               return EINVAL;  /* ??? possible? panic instead? */
-
-       crit_enter();
-       sctp_inpcb_free(inp, 1);
-       crit_exit();
-       return 0;
+       if (inp) {
+               sctp_inpcb_free(inp, 1);
+               error = 0;
+       } else {
+               error = EINVAL;
+       }
+       return error;
 }
 
 static int
@@ -1077,7 +1082,7 @@ sctp_shutdown(struct socket *so)
 #if defined(__FreeBSD__) && __FreeBSD_version >= 502115
                so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
 #else
-               so->so_state &= ~SS_CANTRCVMORE;
+               soclrstate(so, SS_CANTRCVMORE);
 #endif
                /* This proc will wakeup for read and do nothing (I hope) */
                crit_exit();
index 493a7a2..3167f03 100644 (file)
@@ -2189,13 +2189,16 @@ sctp_notify_assoc_change(u_int32_t event, struct sctp_tcb *stcb,
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
            to, m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -2281,13 +2284,16 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
            m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -2382,13 +2388,16 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, u_int32_t error,
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
            m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -2458,13 +2467,16 @@ sctp_notify_adaption_layer(struct sctp_tcb *stcb,
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
            m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -2534,13 +2546,16 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
            m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -2619,13 +2634,16 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
            m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -2717,13 +2735,16 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
        SCTP_TCB_UNLOCK(stcb);
        SCTP_INP_WLOCK(stcb->sctp_ep);
        SCTP_TCB_LOCK(stcb);
+       lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
            m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
                /* not enough room */
                sctp_m_freem(m_notify);
+               lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
                SCTP_INP_WUNLOCK(stcb->sctp_ep);
                return;
        }
+       lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
        if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
           ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
                if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
@@ -3385,6 +3406,7 @@ sctp_get_first_vtag_from_sb(struct socket *so)
        u_int32_t retval;
 
        retval = 0;
+       lwkt_gettoken(&so->so_rcv.ssb_token);
        if (so->so_rcv.ssb_mb) {
                /* grubbing time */
                this = so->so_rcv.ssb_mb;
@@ -3421,6 +3443,7 @@ sctp_get_first_vtag_from_sb(struct socket *so)
                }
 
        }
+       lwkt_reltoken(&so->so_rcv.ssb_token);
        return (retval);
 
 }
@@ -3442,6 +3465,8 @@ sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
        }
        SOCKBUF_LOCK(old_sb);
        SOCKBUF_LOCK(new_sb);
+       lwkt_gettoken(&old_sb->ssb_token);
+       lwkt_gettoken(&new_sb->ssb_token);
 
        if (inp->sctp_vtag_first == asoc->my_vtag) {
                /* First one must be moved */
@@ -3501,6 +3526,8 @@ sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
                 */
                inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
        }
+       lwkt_reltoken(&new_sb->ssb_token);
+       lwkt_reltoken(&old_sb->ssb_token);
        SOCKBUF_UNLOCK(old_sb);
        SOCKBUF_UNLOCK(new_sb);
 }
index 3069521..f97379a 100644 (file)
@@ -88,6 +88,8 @@
 #include <sys/syslog.h>
 #include <sys/in_cksum.h>
 
+#include <sys/socketvar2.h>
+
 #include <machine/cpu.h>       /* before tcp_seq.h, for tcp_random18() */
 #include <machine/stdarg.h>
 
@@ -468,10 +470,13 @@ present:
        KASSERT(LIST_EMPTY(&tp->t_segq) ||
                LIST_FIRST(&tp->t_segq)->tqe_th->th_seq != tp->rcv_nxt,
                ("segment not coalesced"));
-       if (so->so_state & SS_CANTRCVMORE)
+       if (so->so_state & SS_CANTRCVMORE) {
                m_freem(q->tqe_m);
-       else
+       } else {
+               lwkt_gettoken(&so->so_rcv.ssb_token);
                ssb_appendstream(&so->so_rcv, q->tqe_m);
+               lwkt_reltoken(&so->so_rcv.ssb_token);
+       }
        kfree(q, M_TSEGQ);
        atomic_add_int(&tcp_reass_qsize, -1);
        ND6_HINT(tp);
@@ -1364,6 +1369,7 @@ after_listen:
                                 * being avoided (which is the default),
                                 * so force an ack.
                                 */
+                               lwkt_gettoken(&so->so_rcv.ssb_token);
                                if (newsize) {
                                        tp->t_flags |= TF_RXRESIZED;
                                        if (!ssb_reserve(&so->so_rcv, newsize,
@@ -1377,6 +1383,7 @@ after_listen:
                                }
                                m_adj(m, drop_hdrlen); /* delayed header drop */
                                ssb_appendstream(&so->so_rcv, m);
+                               lwkt_reltoken(&so->so_rcv.ssb_token);
                        }
                        sorwakeup(so);
                        /*
@@ -2395,7 +2402,7 @@ step6:
                        so->so_oobmark = so->so_rcv.ssb_cc +
                            (tp->rcv_up - tp->rcv_nxt) - 1;
                        if (so->so_oobmark == 0)
-                               so->so_state |= SS_RCVATMARK;
+                               sosetstate(so, SS_RCVATMARK);
                        sohasoutofband(so);
                        tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
                }
@@ -2457,10 +2464,13 @@ dodata:                                                 /* XXX */
                        tcpstat.tcps_rcvpack++;
                        tcpstat.tcps_rcvbyte += tlen;
                        ND6_HINT(tp);
-                       if (so->so_state & SS_CANTRCVMORE)
+                       if (so->so_state & SS_CANTRCVMORE) {
                                m_freem(m);
-                       else
+                       } else {
+                               lwkt_gettoken(&so->so_rcv.ssb_token);
                                ssb_appendstream(&so->so_rcv, m);
+                               lwkt_reltoken(&so->so_rcv.ssb_token);
+                       }
                        sorwakeup(so);
                } else {
                        if (!(tp->t_flags & TF_DUPSEG)) {
@@ -3041,8 +3051,11 @@ tcp_mss(struct tcpcb *tp, int offer)
                bufsize = roundup(bufsize, mss);
                if (bufsize > sb_max)
                        bufsize = sb_max;
-               if (bufsize > so->so_rcv.ssb_hiwat)
+               if (bufsize > so->so_rcv.ssb_hiwat) {
+                       lwkt_gettoken(&so->so_rcv.ssb_token);
                        ssb_reserve(&so->so_rcv, bufsize, so, NULL);
+                       lwkt_reltoken(&so->so_rcv.ssb_token);
+               }
        }
 
        /*
index 7f07a7d..ed7a9e8 100644 (file)
 #define KTR_TCP                KTR_ALL
 #endif
 KTR_INFO_MASTER(tcp);
+/*
 KTR_INFO(KTR_TCP, tcp, rxmsg, 0, "tcp getmsg", 0);
 KTR_INFO(KTR_TCP, tcp, wait, 1, "tcp waitmsg", 0);
 KTR_INFO(KTR_TCP, tcp, delayed, 2, "tcp execute delayed ops", 0);
+*/
 #define logtcp(name)   KTR_LOG(tcp_ ## name)
 
 struct inpcbinfo tcbinfo[MAXCPU];
 struct tcpcbackqhead tcpcbackq[MAXCPU];
 
-int tcp_mpsafe_proto = 0;
-TUNABLE_INT("net.inet.tcp.mpsafe_proto", &tcp_mpsafe_proto);
-
-static int tcp_mpsafe_thread = NETMSG_SERVICE_ADAPTIVE;
-TUNABLE_INT("net.inet.tcp.mpsafe_thread", &tcp_mpsafe_thread);
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, mpsafe_thread, CTLFLAG_RW,
-          &tcp_mpsafe_thread, 0,
-          "0:BGL, 1:Adaptive BGL, 2:No BGL(experimental)");
-
 int tcp_mssdflt = TCP_MSS;
 SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt, CTLFLAG_RW,
     &tcp_mssdflt, 0, "Default TCP Maximum Segment Size");
@@ -254,7 +247,7 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, inflight_stab, CTLFLAG_RW,
 static MALLOC_DEFINE(M_TCPTEMP, "tcptemp", "TCP Templates for Keepalives");
 static struct malloc_pipe tcptemp_mpipe;
 
-static void tcp_willblock(int);
+static void tcp_willblock(void);
 static void tcp_notify (struct inpcb *, int);
 
 struct tcp_stats tcpstats_percpu[MAXCPU];
@@ -392,48 +385,14 @@ tcp_init(void)
 #endif
 
        syncache_init();
-       tcp_thread_init();
-}
-
-void
-tcpmsg_service_loop(void *dummy)
-{
-       struct netmsg *msg;
-       int mplocked;
-
-       /*
-        * Threads always start mpsafe.
-        */
-       mplocked = 0;
-
-       while ((msg = lwkt_waitport(&curthread->td_msgport, 0))) {
-               do {
-                       logtcp(rxmsg);
-                       mplocked = netmsg_service(msg, tcp_mpsafe_thread,
-                                                 mplocked);
-               } while ((msg = lwkt_getport(&curthread->td_msgport)) != NULL);
-
-               logtcp(delayed);
-               tcp_willblock(mplocked);
-               logtcp(wait);
-       }
+       netisr_register_rollup(tcp_willblock);
 }
 
 static void
-tcp_willblock(int mplocked)
+tcp_willblock(void)
 {
        struct tcpcb *tp;
        int cpu = mycpu->gd_cpuid;
-       int unlock = 0;
-
-       if (!mplocked && !tcp_mpsafe_proto) {
-               if (TAILQ_EMPTY(&tcpcbackq[cpu]))
-                       return;
-
-               get_mplock();
-               mplocked = 1;
-               unlock = 1;
-       }
 
        while ((tp = TAILQ_FIRST(&tcpcbackq[cpu])) != NULL) {
                KKASSERT(tp->t_flags & TF_ONOUTPUTQ);
@@ -441,12 +400,8 @@ tcp_willblock(int mplocked)
                TAILQ_REMOVE(&tcpcbackq[cpu], tp, t_outputq);
                tcp_output(tp);
        }
-
-       if (unlock)
-               rel_mplock();
 }
 
-
 /*
  * Fill in the IP and TCP headers for an outgoing packet, given the tcpcb.
  * tcp_template used to store this data in mbufs, but we now recopy it out
@@ -819,7 +774,7 @@ in_pcbremwildcardhash_handler(struct netmsg *msg0)
                in_pcbremwildcardhash_oncpu(msg->nm_inp, msg->nm_pcbinfo);
                cpu = (cpu + 1) % ncpus2;
                msg->nm_pcbinfo = &tcbinfo[cpu];
-               lwkt_forwardmsg(tcp_cport(cpu), &msg->nm_netmsg.nm_lmsg);
+               lwkt_forwardmsg(cpu_portfn(cpu), &msg->nm_netmsg.nm_lmsg);
        }
 }
 
@@ -992,6 +947,7 @@ no_valid_rt:
 
        inp->inp_ppcb = NULL;
        soisdisconnected(so);
+       /* note: pcb detached later on */
 
        tcp_destroy_timermsg(tp);
        if (tp->t_flags & TF_SYNCACHE)
@@ -1021,7 +977,7 @@ no_valid_rt:
 #endif
                msg->nm_inp = inp;
                msg->nm_pcbinfo = &tcbinfo[cpu];
-               lwkt_sendmsg(tcp_cport(cpu), &msg->nm_netmsg.nm_lmsg);
+               lwkt_sendmsg(cpu_portfn(cpu), &msg->nm_netmsg.nm_lmsg);
        } else
 #endif
        {
@@ -1118,7 +1074,7 @@ tcp_drain(void)
                        netmsg_init(&msg->nm_netmsg, NULL, &netisr_afree_rport,
                                    0, tcp_drain_handler);
                        msg->nm_head = &tcbinfo[cpu].pcblisthead;
-                       lwkt_sendmsg(tcp_cport(cpu), &msg->nm_netmsg.nm_lmsg);
+                       lwkt_sendmsg(cpu_portfn(cpu), &msg->nm_netmsg.nm_lmsg);
                }
        }
 #else
@@ -1374,7 +1330,7 @@ tcp_notifyall_oncpu(struct netmsg *netmsg)
 
        nextcpu = mycpuid + 1;
        if (nextcpu < ncpus2)
-               lwkt_forwardmsg(tcp_cport(nextcpu), &netmsg->nm_lmsg);
+               lwkt_forwardmsg(cpu_portfn(nextcpu), &netmsg->nm_lmsg);
        else
                lwkt_replymsg(&netmsg->nm_lmsg, 0);
 }
@@ -1458,7 +1414,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
                nmsg.nm_arg = arg;
                nmsg.nm_notify = notify;
 
-               lwkt_domsg(tcp_cport(0), &nmsg.nm_nmsg.nm_lmsg, 0);
+               lwkt_domsg(cpu_portfn(0), &nmsg.nm_nmsg.nm_lmsg, 0);
        }
 }
 
index bc5fc02..88bb81b 100644 (file)
@@ -332,9 +332,9 @@ syncache_init(void)
                        callout_init(&syncache_percpu->tt_timerq[i]);
 
                        syncache_percpu->mrec[i].slot = i;
-                       syncache_percpu->mrec[i].port = tcp_cport(cpu);
+                       syncache_percpu->mrec[i].port = cpu_portfn(cpu);
                        syncache_percpu->mrec[i].msg.nm_mrec =
-                           &syncache_percpu->mrec[i];
+                                   &syncache_percpu->mrec[i];
                        netmsg_init(&syncache_percpu->mrec[i].msg.nm_netmsg,
                    &