]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/netbsd-tests/net/carp/t_basic.c
MFC r314062
[FreeBSD/stable/10.git] / contrib / netbsd-tests / net / carp / t_basic.c
1 /*      $NetBSD: t_basic.c,v 1.5 2011/06/26 13:13:31 christos 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.5 2011/06/26 13:13:31 christos 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
57 static bool oknow = false;
58
59 static void
60 sighnd(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
70 ATF_TC(handover);
71 ATF_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
80 static void
81 child(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
139 ATF_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
215 ATF_TP_ADD_TCS(tp)
216 {
217
218         ATF_TP_ADD_TC(tp, handover);
219
220         return atf_no_error();
221 }