carp: Lockless MPSAFE step 9 of many
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 7 Apr 2012 14:17:44 +0000 (22:17 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 7 Apr 2012 14:20:11 +0000 (22:20 +0800)
Carry out timeout processing in netisr0

sys/netinet/ip_carp.c

index 03f7394..132ca11 100644 (file)
@@ -85,6 +85,8 @@
 #define CARP_IS_RUNNING(ifp)   \
        (((ifp)->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
 
+struct carp_softc;
+
 struct carp_vhaddr {
        uint32_t                vha_flags;      /* CARP_VHAF_ */
        struct in_ifaddr        *vha_ia;        /* carp address */
@@ -93,6 +95,14 @@ struct carp_vhaddr {
 };
 TAILQ_HEAD(carp_vhaddr_list, carp_vhaddr);
 
+struct netmsg_carp {
+       struct netmsg_base      base;
+       struct ifnet            *nc_carpdev;
+       struct carp_softc       *nc_softc;
+       void                    *nc_data;
+       size_t                  nc_datalen;
+};
+
 struct carp_softc {
        struct arpcom            arpcom;
        struct ifnet            *sc_carpdev;    /* parent interface */
@@ -133,8 +143,10 @@ struct carp_softc {
        SHA1_CTX                 sc_sha1;
 
        struct callout           sc_ad_tmo;     /* advertisement timeout */
-       struct callout           sc_md_tmo;     /* master down timeout */
-       struct callout           sc_md6_tmo;    /* master down timeout */
+       struct netmsg_carp       sc_ad_msg;     /* adv timeout netmsg */
+       struct callout           sc_md_tmo;     /* ip4 master down timeout */
+       struct callout           sc_md6_tmo;    /* ip6 master down timeout */
+       struct netmsg_carp       sc_md_msg;     /* master down timeout netmsg */
 
        LIST_ENTRY(carp_softc)   sc_next;       /* Interface clue */
 };
@@ -145,14 +157,6 @@ struct carp_if {
        TAILQ_HEAD(, carp_softc) vhif_vrs;
 };
 
-struct netmsg_carp {
-       struct netmsg_base      base;
-       struct ifnet            *nc_carpdev;
-       struct carp_softc       *nc_softc;
-       void                    *nc_data;
-       size_t                  nc_datalen;
-};
-
 SYSCTL_DECL(_net_inet_carp);
 
 static int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0 }; /* XXX for now */
@@ -270,6 +274,8 @@ static void carp_ioctl_setvh_dispatch(netmsg_t);
 static void    carp_ioctl_getvh_dispatch(netmsg_t);
 static void    carp_ioctl_getdevname_dispatch(netmsg_t);
 static void    carp_ioctl_getvhaddr_dispatch(netmsg_t);
+static void    carp_send_ad_timeout_dispatch(netmsg_t);
+static void    carp_master_down_timeout_dispatch(netmsg_t);
 
 static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces");
 
@@ -456,8 +462,15 @@ carp_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
 #endif
 
        callout_init_mp(&sc->sc_ad_tmo);
+       netmsg_init(&sc->sc_ad_msg.base, NULL, &netisr_adone_rport,
+           MSGF_DROPABLE | MSGF_PRIORITY, carp_send_ad_timeout_dispatch);
+       sc->sc_ad_msg.nc_softc = sc;
+
        callout_init_mp(&sc->sc_md_tmo);
        callout_init_mp(&sc->sc_md6_tmo);
+       netmsg_init(&sc->sc_md_msg.base, NULL, &netisr_adone_rport,
+           MSGF_DROPABLE | MSGF_PRIORITY, carp_master_down_timeout_dispatch);
+       sc->sc_md_msg.nc_softc = sc;
 
        if_initname(ifp, CARP_IFNAME, unit);
        ifp->if_softc = sc;
@@ -499,6 +512,17 @@ carp_clone_destroy_dispatch(netmsg_t msg)
 
        carp_reltok();
 
+       callout_stop_sync(&sc->sc_ad_tmo);
+       callout_stop_sync(&sc->sc_md_tmo);
+       callout_stop_sync(&sc->sc_md6_tmo);
+
+       crit_enter();
+       if ((sc->sc_ad_msg.base.lmsg.ms_flags & MSGF_DONE) == 0)
+               lwkt_dropmsg(&sc->sc_ad_msg.base.lmsg);
+       if ((sc->sc_md_msg.base.lmsg.ms_flags & MSGF_DONE) == 0)
+               lwkt_dropmsg(&sc->sc_md_msg.base.lmsg);
+       crit_exit();
+
        lwkt_replymsg(&cmsg->base.lmsg, 0);
 }
 
@@ -973,8 +997,31 @@ carp_send_ad_all(void)
 static void
 carp_send_ad_timeout(void *xsc)
 {
+       struct carp_softc *sc = xsc;
+       struct netmsg_carp *cmsg = &sc->sc_ad_msg;
+
+       KASSERT(mycpuid == 0, ("%s not on cpu0 but on cpu%d\n",
+           __func__, mycpuid));
+
+       crit_enter();
+       if (cmsg->base.lmsg.ms_flags & MSGF_DONE)
+               lwkt_sendmsg(cpu_portfn(0), &cmsg->base.lmsg);
+       crit_exit();
+}
+
+static void
+carp_send_ad_timeout_dispatch(netmsg_t msg)
+{
+       struct netmsg_carp *cmsg = (struct netmsg_carp *)msg;
+       struct carp_softc *sc = cmsg->nc_softc;
+
+       /* Reply ASAP */
+       crit_enter();
+       lwkt_replymsg(&cmsg->base.lmsg, 0);
+       crit_exit();
+
        carp_gettok();
-       carp_send_ad(xsc);
+       carp_send_ad(sc);
        carp_reltok();
 }
 
@@ -1369,6 +1416,27 @@ static void
 carp_master_down_timeout(void *xsc)
 {
        struct carp_softc *sc = xsc;
+       struct netmsg_carp *cmsg = &sc->sc_md_msg;
+
+       KASSERT(mycpuid == 0, ("%s not on cpu0 but on cpu%d\n",
+           __func__, mycpuid));
+
+       crit_enter();
+       if (cmsg->base.lmsg.ms_flags & MSGF_DONE)
+               lwkt_sendmsg(cpu_portfn(0), &cmsg->base.lmsg);
+       crit_exit();
+}
+
+static void
+carp_master_down_timeout_dispatch(netmsg_t msg)
+{
+       struct netmsg_carp *cmsg = (struct netmsg_carp *)msg;
+       struct carp_softc *sc = cmsg->nc_softc;
+
+       /* Reply ASAP */
+       crit_enter();
+       lwkt_replymsg(&cmsg->base.lmsg, 0);
+       crit_exit();
 
        CARP_DEBUG("%s: BACKUP -> MASTER (master timed out)\n",
                   sc->sc_if.if_xname);