xref: /freebsd/tests/sys/netgraph/hub.c (revision 61e21613)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright 2021 Lutz Donnerhacke
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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
13  *    copyright notice, this list of conditions and the following
14  *    disclaimer in the documentation and/or other materials provided
15  *    with the distribution.
16  * 3. Neither the name of the copyright holder nor the names of its
17  *    contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
21  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
22  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
31  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include <atf-c.h>
35 #include <errno.h>
36 #include <stdio.h>
37 
38 #include "util.h"
39 
40 ATF_TC(basic);
41 ATF_TC_HEAD(basic, conf)
42 {
43 	atf_tc_set_md_var(conf, "require.user", "root");
44 }
45 
46 ATF_TC_BODY(basic, dummy)
47 {
48 	char		msg[] = "test";
49 	ng_counter_t	r;
50 
51 	ng_errors(PASS);
52 	ng_shutdown("hub:");
53 	ng_errors(FAIL);
54 
55 	ng_init();
56 	ng_mkpeer(".", "a", "hub", "a");
57 	ng_name("a", "hub");
58 	ng_connect(".", "b", "hub:", "b");
59 	ng_connect(".", "c", "hub:", "c");
60 
61 	/* do not bounce back */
62 	ng_register_data("a", get_data0);
63 	ng_counter_clear(r);
64 	ng_send_data("a", msg, sizeof(msg));
65 	ng_handle_events(50, r);
66 	ATF_CHECK(r[0] == 0);
67 
68 	/* send to others */
69 	ng_register_data("b", get_data0);
70 	ng_register_data("c", get_data0);
71 	ng_counter_clear(r);
72 	ng_send_data("a", msg, sizeof(msg));
73 	ng_handle_events(50, r);
74 	ATF_CHECK(r[0] == 2);
75 
76 	ng_counter_clear(r);
77 	ng_send_data("b", msg, sizeof(msg));
78 	ng_handle_events(50, r);
79 	ATF_CHECK(r[0] == 2);
80 
81 	ng_counter_clear(r);
82 	ng_send_data("c", msg, sizeof(msg));
83 	ng_handle_events(50, r);
84 	ATF_CHECK(r[0] == 2);
85 
86 	/* remove a link */
87 	ng_rmhook(".", "b");
88 	ng_counter_clear(r);
89 	ng_send_data("a", msg, sizeof(msg));
90 	ng_handle_events(50, r);
91 	ATF_CHECK(r[0] == 1);
92 
93 	ng_shutdown("hub:");
94 }
95 
96 ATF_TC(persistence);
97 ATF_TC_HEAD(persistence, conf)
98 {
99 	atf_tc_set_md_var(conf, "require.user", "root");
100 }
101 
102 ATF_TC_BODY(persistence, dummy)
103 {
104 	ng_errors(PASS);
105 	ng_shutdown("hub:");
106 	ng_errors(FAIL);
107 
108 	ng_init();
109 	ng_mkpeer(".", "a", "hub", "a");
110 	ng_name("a", "hub");
111 
112 	ng_send_msg("hub:", "setpersistent");
113 	ng_rmhook(".", "a");
114 
115 	ng_shutdown("hub:");
116 }
117 
118 ATF_TC(loop);
119 ATF_TC_HEAD(loop, conf)
120 {
121 	atf_tc_set_md_var(conf, "require.user", "root");
122 }
123 
124 ATF_TC_BODY(loop, dummy)
125 {
126 	ng_counter_t	r;
127 	int		i;
128 	char		msg[] = "LOOP Alert!";
129 
130 	ng_errors(PASS);
131 	ng_shutdown("hub1:");
132 	ng_shutdown("hub2:");
133 	ng_errors(FAIL);
134 
135 	ng_init();
136 	ng_mkpeer(".", "a", "hub", "a");
137 	ng_name("a", "hub1");
138 	ng_mkpeer(".", "b", "hub", "b");
139 	ng_name("b", "hub2");
140 
141 	ng_register_data("a", get_data0);
142 	ng_register_data("b", get_data0);
143 
144 	/*-
145 	 * Open loop
146 	 *
147 	 *    /-- hub1
148 	 * . <    |
149 	 *    \-- hub2
150 	 */
151 	ng_connect("hub1:", "xc1", "hub2:", "xc1");
152 
153 	ng_counter_clear(r);
154 	ng_send_data("a", msg, sizeof(msg));
155 	ng_handle_events(50, r);
156 	ATF_CHECK(r[0] == 1);
157 
158 	/*-
159 	 * Closed loop, DANGEROUS!
160 	 *
161 	 *    /-- hub1 -\
162 	 * . <     |    |
163 	 *    \-- hub2 -/
164 	 */
165 	ng_connect("hub1:", "xc2", "hub2:", "xc2");
166 
167 	ng_counter_clear(r);
168 	ng_send_data("a", msg, sizeof(msg));
169 	for (i = 0; i < 10; i++)	/* don't run forever */
170 		if (!ng_handle_event(50, r))
171 			break;
172 	ATF_CHECK(r[0] > 7);
173 
174 	ng_shutdown("hub1:");
175 	ng_shutdown("hub2:");
176 }
177 
178 ATF_TC(many_hooks);
179 ATF_TC_HEAD(many_hooks, conf)
180 {
181 	atf_tc_set_md_var(conf, "require.user", "root");
182 }
183 
184 ATF_TC_BODY(many_hooks, dummy)
185 {
186 	ng_counter_t	r;
187 	int		i;
188 	char		msg[] = "test";
189 	const int	HOOKS = 1000;
190 
191 	ng_errors(PASS);
192 	ng_shutdown("hub:");
193 	ng_errors(FAIL);
194 
195 	ng_init();
196 	ng_mkpeer(".", "a", "hub", "a");
197 	ng_name("a", "hub");
198 
199 	ng_register_data("a", get_data0);
200 	ng_counter_clear(r);
201 	for (i = 0; i < HOOKS; i++)
202 	{
203 		char		hook[20];
204 
205 		snprintf(hook, sizeof(hook), "hook%d", i);
206 		ng_connect(".", hook, "hub:", hook);
207 		ng_errors(PASS);
208 		ng_send_data(hook, msg, sizeof(msg));
209 		ng_errors(FAIL);
210 		if (errno != 0)
211 			break;
212 		ng_handle_events(50, r);
213 	}
214 	ATF_CHECK(r[0] > 100);
215 	atf_tc_expect_fail("Implementation limitation (%d)", i);
216 	ATF_CHECK(r[0] == HOOKS);
217 	atf_tc_expect_pass();
218 
219 	ng_shutdown("hub:");
220 }
221 
222 
223 ATF_TP_ADD_TCS(hub)
224 {
225 	ATF_TP_ADD_TC(hub, basic);
226 	ATF_TP_ADD_TC(hub, loop);
227 	ATF_TP_ADD_TC(hub, persistence);
228 	ATF_TP_ADD_TC(hub, many_hooks);
229 
230 	return atf_no_error();
231 }
232