1/* $NetBSD: t_basic.c,v 1.4 2010/11/07 17:51:21 jmmv Exp $ */ 2 3/*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31#ifndef lint 32__RCSID("$NetBSD: t_basic.c,v 1.4 2010/11/07 17:51:21 jmmv Exp $"); 33#endif /* not lint */ 34 35#include <sys/types.h> 36#include <sys/socket.h> 37#include <sys/wait.h> 38 39#include <netinet/in.h> 40#include <netinet/in_systm.h> 41#include <netinet/ip_carp.h> 42 43#include <rump/rump.h> 44#include <rump/rump_syscalls.h> 45 46#include <atf-c.h> 47#include <errno.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <unistd.h> 52#include <signal.h> 53 54#include "../config/netconfig.c" 55#include "../../h_macros.h" 56 57static bool oknow = false; 58 59static void 60sighnd(int sig) 61{ 62 63 ATF_REQUIRE_EQ(sig, SIGCHLD); 64 if (oknow) 65 return; 66 67 atf_tc_fail("child died unexpectedly"); 68} 69 70ATF_TC(handover); 71ATF_TC_HEAD(handover, tc) 72{ 73 74 atf_tc_set_md_var(tc, "descr", "check that carp handover works if " 75 "the master dies"); 76} 77 78#define THEBUS "buuuuuuus,etherbus" 79 80static void 81child(bool master) 82{ 83 char ifname[IFNAMSIZ]; 84 struct carpreq cr; 85 struct ifreq ifr; 86 const char *carpif; 87 int s; 88 89 /* helps reading carp debug output */ 90 if (master) 91 carpif = "carp0"; 92 else 93 carpif = "carp1"; 94 95 /* 96 * Should use sysctl, bug debug is dabug. 97 */ 98 { 99 //extern int rumpns_carp_opts[]; /* XXX */ 100 //rumpns_carp_opts[CARPCTL_LOG] = 1; 101 } 102 103 104 rump_init(); 105 106 memset(&ifr, 0, sizeof(ifr)); 107 strlcpy(ifr.ifr_name, carpif, sizeof(ifr.ifr_name)); 108 109 RL(s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)); 110 RL(rump_sys_ioctl(s, SIOCIFCREATE, &ifr)); 111 112 netcfg_rump_makeshmif(THEBUS, ifname); 113 114 if (master) 115 netcfg_rump_if(ifname, "10.1.1.1", "255.255.255.0"); 116 else 117 netcfg_rump_if(ifname, "10.1.1.2", "255.255.255.0"); 118 119 /* configure the carp interface */ 120 ifr.ifr_data = &cr; 121 RL(rump_sys_ioctl(s, SIOCGVH, &ifr)); 122 123 strlcpy(cr.carpr_carpdev, ifname, sizeof(cr.carpr_carpdev)); 124 cr.carpr_vhid = 175; 125 if (master) 126 cr.carpr_advskew = 0; 127 else 128 cr.carpr_advskew = 200; 129 cr.carpr_advbase = 1; 130 strcpy((char *)cr.carpr_key, "s3cret"); 131 132 RL(rump_sys_ioctl(s, SIOCSVH, &ifr)); 133 netcfg_rump_if(carpif, "10.1.1.100", "255.255.255.0"); 134 135 /* tassa pause()en enka muuta voi */ 136 pause(); 137} 138 139ATF_TC_BODY(handover, tc) 140{ 141 char ifname[IFNAMSIZ]; 142 pid_t mpid, cpid; 143 int i, status; 144 145 signal(SIGCHLD, sighnd); 146 147 /* fork master */ 148 switch (mpid = fork()) { 149 case -1: 150 atf_tc_fail_errno("fork failed"); 151 /*NOTREACHED*/ 152 case 0: 153 child(true); 154 /*NOTREACHED*/ 155 default: 156 break; 157 } 158 159 usleep(500000); 160 161 /* fork backup */ 162 switch (cpid = fork()) { 163 case -1: 164 kill(mpid, SIGKILL); 165 atf_tc_fail_errno("fork failed"); 166 /*NOTREACHED*/ 167 case 0: 168 child(false); 169 /*NOTREACHED*/ 170 default: 171 break; 172 } 173 174 usleep(500000); 175 176 rump_init(); 177 netcfg_rump_makeshmif(THEBUS, ifname); 178 netcfg_rump_if(ifname, "10.1.1.240", "255.255.255.0"); 179 180 /* check that the primary addresses are up */ 181 ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 1000), true); 182 ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.2", 1000), true); 183 184 /* give carp a while to croak */ 185 sleep(4); 186 187 /* check that the shared IP works */ 188 ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.100", 500), true); 189 190 /* KILLING SPREE */ 191 oknow = true; 192 kill(mpid, SIGKILL); 193 wait(&status); 194 usleep(10000); /* just in case */ 195 oknow = false; 196 197 /* check that primary is now dead */ 198 ATF_REQUIRE_EQ(netcfg_rump_pingtest("10.1.1.1", 100), false); 199 200 /* do it in installments. carp will cluck meanwhile */ 201 for (i = 0; i < 5; i++) { 202 if (netcfg_rump_pingtest("10.1.1.100", 1000) == true) 203 break; 204 } 205 if (i == 5) 206 atf_tc_fail("failed to failover"); 207 208 /* to kill the child */ 209 oknow = true; 210 kill(cpid, SIGKILL); 211 212 /* clean & done */ 213} 214 215ATF_TP_ADD_TCS(tp) 216{ 217 218 ATF_TP_ADD_TC(tp, handover); 219 220 return atf_no_error(); 221} 222