1272343Sngie/* $NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17272343Sngie * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18272343Sngie * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19272343Sngie * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20272343Sngie * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21272343Sngie * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23272343Sngie * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25272343Sngie * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26272343Sngie * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27272343Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28272343Sngie */ 29272343Sngie 30272343Sngie#include <sys/cdefs.h> 31272343Sngie#ifndef lint 32272343Sngie__RCSID("$NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos Exp $"); 33272343Sngie#endif /* not lint */ 34272343Sngie 35272343Sngie#include <sys/types.h> 36272343Sngie#include <sys/socket.h> 37272343Sngie#include <sys/wait.h> 38272343Sngie 39272343Sngie#include <netinet/in.h> 40272343Sngie#include <netinet/in_systm.h> 41272343Sngie#include <netinet/ip_carp.h> 42272343Sngie 43272343Sngie#include <rump/rump.h> 44272343Sngie#include <rump/rump_syscalls.h> 45272343Sngie 46272343Sngie#include <atf-c.h> 47272343Sngie#include <errno.h> 48272343Sngie#include <stdio.h> 49272343Sngie#include <stdlib.h> 50272343Sngie#include <string.h> 51272343Sngie#include <unistd.h> 52272343Sngie#include <signal.h> 53272343Sngie 54272343Sngie#include "../config/netconfig.c" 55272343Sngie#include "../../h_macros.h" 56272343Sngie 57272343Sngiestatic bool oknow = false; 58272343Sngie 59272343Sngiestatic void 60272343Sngiesighnd(int sig) 61272343Sngie{ 62272343Sngie 63272343Sngie ATF_REQUIRE_EQ(sig, SIGCHLD); 64272343Sngie if (oknow) 65272343Sngie return; 66272343Sngie 67272343Sngie atf_tc_fail("child died unexpectedly"); 68272343Sngie} 69272343Sngie 70272343SngieATF_TC(handover); 71272343SngieATF_TC_HEAD(handover, tc) 72272343Sngie{ 73272343Sngie 74272343Sngie atf_tc_set_md_var(tc, "descr", "check that carp handover works if " 75272343Sngie "the master dies"); 76272343Sngie} 77272343Sngie 78272343Sngie#define THEBUS "buuuuuuus,etherbus" 79272343Sngie 80272343Sngiestatic void 81272343Sngiechild(bool master) 82272343Sngie{ 83272343Sngie char ifname[IFNAMSIZ]; 84272343Sngie struct carpreq cr; 85272343Sngie struct ifreq ifr; 86272343Sngie const char *carpif; 87272343Sngie int s; 88272343Sngie 89272343Sngie /* helps reading carp debug output */ 90272343Sngie if (master) 91272343Sngie carpif = "carp0"; 92272343Sngie else 93272343Sngie carpif = "carp1"; 94272343Sngie 95272343Sngie /* 96272343Sngie * Should use sysctl, bug debug is dabug. 97272343Sngie */ 98272343Sngie { 99272343Sngie //extern int rumpns_carp_opts[]; /* XXX */ 100272343Sngie //rumpns_carp_opts[CARPCTL_LOG] = 1; 101272343Sngie } 102272343Sngie 103272343Sngie 104272343Sngie rump_init(); 105272343Sngie 106272343Sngie memset(&ifr, 0, sizeof(ifr)); 107272343Sngie strlcpy(ifr.ifr_name, carpif, sizeof(ifr.ifr_name)); 108272343Sngie 109272343Sngie RL(s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)); 110272343Sngie RL(rump_sys_ioctl(s, SIOCIFCREATE, &ifr)); 111272343Sngie 112272343Sngie netcfg_rump_makeshmif(THEBUS, ifname); 113272343Sngie 114272343Sngie if (master) 115272343Sngie netcfg_rump_if(ifname, "10.1.1.1", "255.255.255.0"); 116272343Sngie else 117272343Sngie netcfg_rump_if(ifname, "10.1.1.2", "255.255.255.0"); 118272343Sngie 119272343Sngie /* configure the carp interface */ 120272343Sngie ifr.ifr_data = &cr; 121272343Sngie RL(rump_sys_ioctl(s, SIOCGVH, &ifr)); 122272343Sngie 123272343Sngie strlcpy(cr.carpr_carpdev, ifname, sizeof(cr.carpr_carpdev)); 124272343Sngie cr.carpr_vhid = 175; 125272343Sngie if (master) 126272343Sngie cr.carpr_advskew = 0; 127272343Sngie else 128272343Sngie cr.carpr_advskew = 200; 129272343Sngie cr.carpr_advbase = 1; 130272343Sngie strcpy((char *)cr.carpr_key, "s3cret"); 131272343Sngie 132272343Sngie RL(rump_sys_ioctl(s, SIOCSVH, &ifr)); 133272343Sngie netcfg_rump_if(carpif, "10.1.1.100", "255.255.255.0"); 134272343Sngie 135272343Sngie /* tassa pause()en enka muuta voi */ 136272343Sngie pause(); 137272343Sngie} 138272343Sngie 139272343SngieATF_TC_BODY(handover, tc) 140272343Sngie{ 141272343Sngie char ifname[IFNAMSIZ]; 142272343Sngie pid_t mpid, cpid; 143272343Sngie int i, status; 144272343Sngie 145272343Sngie signal(SIGCHLD, sighnd); 146272343Sngie 147272343Sngie /* fork master */ 148272343Sngie switch (mpid = fork()) { 149272343Sngie case -1: 150272343Sngie atf_tc_fail_errno("fork failed"); 151272343Sngie /*NOTREACHED*/ 152272343Sngie case 0: 153272343Sngie child(true); 154272343Sngie /*NOTREACHED*/ 155272343Sngie default: 156272343Sngie break; 157272343Sngie } 158272343Sngie 159272343Sngie usleep(500000); 160272343Sngie 161272343Sngie /* fork backup */ 162272343Sngie switch (cpid = fork()) { 163272343Sngie case -1: 164272343Sngie kill(mpid, SIGKILL); 165272343Sngie atf_tc_fail_errno("fork failed"); 166272343Sngie /*NOTREACHED*/ 167272343Sngie case 0: 168272343Sngie child(false); 169272343Sngie /*NOTREACHED*/ 170272343Sngie default: 171272343Sngie break; 172272343Sngie } 173272343Sngie 174272343Sngie usleep(500000); 175272343Sngie 176272343Sngie rump_init(); 177272343Sngie netcfg_rump_makeshmif(THEBUS, ifname); 178272343Sngie netcfg_rump_if(ifname, "10.1.1.240", "255.255.255.0"); 179272343Sngie 180272343Sngie /* check that the primary addresses are up */ 181272343Sngie ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 1000), true); 182272343Sngie ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.2", 1000), true); 183272343Sngie 184272343Sngie /* give carp a while to croak */ 185272343Sngie sleep(4); 186272343Sngie 187272343Sngie /* check that the shared IP works */ 188272343Sngie ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.100", 500), true); 189272343Sngie 190272343Sngie /* KILLING SPREE */ 191272343Sngie oknow = true; 192272343Sngie kill(mpid, SIGKILL); 193272343Sngie wait(&status); 194272343Sngie usleep(10000); /* just in case */ 195272343Sngie oknow = false; 196272343Sngie 197272343Sngie /* check that primary is now dead */ 198272343Sngie ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 100), false); 199272343Sngie 200272343Sngie /* do it in installments. carp will cluck meanwhile */ 201272343Sngie for (i = 0; i < 5; i++) { 202272343Sngie if (netcfg_rump_pingtest("10.1.1.100", 1000) == true) 203272343Sngie break; 204272343Sngie } 205272343Sngie if (i == 5) 206272343Sngie atf_tc_fail("failed to failover"); 207272343Sngie 208272343Sngie /* to kill the child */ 209272343Sngie oknow = true; 210272343Sngie kill(cpid, SIGKILL); 211272343Sngie 212272343Sngie /* clean & done */ 213272343Sngie} 214272343Sngie 215272343SngieATF_TP_ADD_TCS(tp) 216272343Sngie{ 217272343Sngie 218272343Sngie ATF_TP_ADD_TC(tp, handover); 219272343Sngie 220272343Sngie return atf_no_error(); 221272343Sngie} 222