/* $NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #ifndef lint __RCSID("$NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos Exp $"); #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../config/netconfig.c" #include "../../h_macros.h" static bool oknow = false; static void sighnd(int sig) { ATF_REQUIRE_EQ(sig, SIGCHLD); if (oknow) return; atf_tc_fail("child died unexpectedly"); } ATF_TC(handover); ATF_TC_HEAD(handover, tc) { atf_tc_set_md_var(tc, "descr", "check that carp handover works if " "the master dies"); } #define THEBUS "buuuuuuus,etherbus" static void child(bool master) { char ifname[IFNAMSIZ]; struct carpreq cr; struct ifreq ifr; const char *carpif; int s; /* helps reading carp debug output */ if (master) carpif = "carp0"; else carpif = "carp1"; /* * Should use sysctl, bug debug is dabug. */ { //extern int rumpns_carp_opts[]; /* XXX */ //rumpns_carp_opts[CARPCTL_LOG] = 1; } rump_init(); memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, carpif, sizeof(ifr.ifr_name)); RL(s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)); RL(rump_sys_ioctl(s, SIOCIFCREATE, &ifr)); netcfg_rump_makeshmif(THEBUS, ifname); if (master) netcfg_rump_if(ifname, "10.1.1.1", "255.255.255.0"); else netcfg_rump_if(ifname, "10.1.1.2", "255.255.255.0"); /* configure the carp interface */ ifr.ifr_data = &cr; RL(rump_sys_ioctl(s, SIOCGVH, &ifr)); strlcpy(cr.carpr_carpdev, ifname, sizeof(cr.carpr_carpdev)); cr.carpr_vhid = 175; if (master) cr.carpr_advskew = 0; else cr.carpr_advskew = 200; cr.carpr_advbase = 1; strcpy((char *)cr.carpr_key, "s3cret"); RL(rump_sys_ioctl(s, SIOCSVH, &ifr)); netcfg_rump_if(carpif, "10.1.1.100", "255.255.255.0"); /* tassa pause()en enka muuta voi */ pause(); } ATF_TC_BODY(handover, tc) { char ifname[IFNAMSIZ]; pid_t mpid, cpid; int i, status; signal(SIGCHLD, sighnd); /* fork master */ switch (mpid = fork()) { case -1: atf_tc_fail_errno("fork failed"); /*NOTREACHED*/ case 0: child(true); /*NOTREACHED*/ default: break; } usleep(500000); /* fork backup */ switch (cpid = fork()) { case -1: kill(mpid, SIGKILL); atf_tc_fail_errno("fork failed"); /*NOTREACHED*/ case 0: child(false); /*NOTREACHED*/ default: break; } usleep(500000); rump_init(); netcfg_rump_makeshmif(THEBUS, ifname); netcfg_rump_if(ifname, "10.1.1.240", "255.255.255.0"); /* check that the primary addresses are up */ ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 1000), true); ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.2", 1000), true); /* give carp a while to croak */ sleep(4); /* check that the shared IP works */ ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.100", 500), true); /* KILLING SPREE */ oknow = true; kill(mpid, SIGKILL); wait(&status); usleep(10000); /* just in case */ oknow = false; /* check that primary is now dead */ ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 100), false); /* do it in installments. carp will cluck meanwhile */ for (i = 0; i < 5; i++) { if (netcfg_rump_pingtest("10.1.1.100", 1000) == true) break; } if (i == 5) atf_tc_fail("failed to failover"); /* to kill the child */ oknow = true; kill(cpid, SIGKILL); /* clean & done */ } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, handover); return atf_no_error(); }