xref: /freebsd-src/tests/sys/netgraph/vlan_rotate.c (revision 6b08e68be111d50931b0d30145f8b7e3402decaf)
1*6b08e68bSLutz Donnerhacke /*-
2*6b08e68bSLutz Donnerhacke  * SPDX-License-Identifier: BSD-3-Clause
3*6b08e68bSLutz Donnerhacke  *
4*6b08e68bSLutz Donnerhacke  * Copyright 2021 Lutz Donnerhacke
5*6b08e68bSLutz Donnerhacke  *
6*6b08e68bSLutz Donnerhacke  * Redistribution and use in source and binary forms, with or without
7*6b08e68bSLutz Donnerhacke  * modification, are permitted provided that the following conditions
8*6b08e68bSLutz Donnerhacke  * are met:
9*6b08e68bSLutz Donnerhacke  *
10*6b08e68bSLutz Donnerhacke  * 1. Redistributions of source code must retain the above copyright
11*6b08e68bSLutz Donnerhacke  *    notice, this list of conditions and the following disclaimer.
12*6b08e68bSLutz Donnerhacke  * 2. Redistributions in binary form must reproduce the above
13*6b08e68bSLutz Donnerhacke  *    copyright notice, this list of conditions and the following
14*6b08e68bSLutz Donnerhacke  *    disclaimer in the documentation and/or other materials provided
15*6b08e68bSLutz Donnerhacke  *    with the distribution.
16*6b08e68bSLutz Donnerhacke  * 3. Neither the name of the copyright holder nor the names of its
17*6b08e68bSLutz Donnerhacke  *    contributors may be used to endorse or promote products derived
18*6b08e68bSLutz Donnerhacke  *    from this software without specific prior written permission.
19*6b08e68bSLutz Donnerhacke  *
20*6b08e68bSLutz Donnerhacke  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
21*6b08e68bSLutz Donnerhacke  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
22*6b08e68bSLutz Donnerhacke  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23*6b08e68bSLutz Donnerhacke  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24*6b08e68bSLutz Donnerhacke  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25*6b08e68bSLutz Donnerhacke  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26*6b08e68bSLutz Donnerhacke  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27*6b08e68bSLutz Donnerhacke  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*6b08e68bSLutz Donnerhacke  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29*6b08e68bSLutz Donnerhacke  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30*6b08e68bSLutz Donnerhacke  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
31*6b08e68bSLutz Donnerhacke  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*6b08e68bSLutz Donnerhacke  * SUCH DAMAGE.
33*6b08e68bSLutz Donnerhacke  */
34*6b08e68bSLutz Donnerhacke #include <atf-c.h>
35*6b08e68bSLutz Donnerhacke #include <errno.h>
36*6b08e68bSLutz Donnerhacke #include <stdlib.h>
37*6b08e68bSLutz Donnerhacke #include <stdio.h>
38*6b08e68bSLutz Donnerhacke 
39*6b08e68bSLutz Donnerhacke #include <net/ethernet.h>
40*6b08e68bSLutz Donnerhacke #include <netinet/in.h>
41*6b08e68bSLutz Donnerhacke 
42*6b08e68bSLutz Donnerhacke #include "util.h"
43*6b08e68bSLutz Donnerhacke #include <netgraph/ng_bridge.h>
44*6b08e68bSLutz Donnerhacke 
45*6b08e68bSLutz Donnerhacke struct vlan
46*6b08e68bSLutz Donnerhacke {
47*6b08e68bSLutz Donnerhacke 	uint16_t	proto;
48*6b08e68bSLutz Donnerhacke 	uint16_t	tag;
49*6b08e68bSLutz Donnerhacke }		__packed;
50*6b08e68bSLutz Donnerhacke 
51*6b08e68bSLutz Donnerhacke struct frame
52*6b08e68bSLutz Donnerhacke {
53*6b08e68bSLutz Donnerhacke 	u_char		dst[ETHER_ADDR_LEN];
54*6b08e68bSLutz Donnerhacke 	u_char		src[ETHER_ADDR_LEN];
55*6b08e68bSLutz Donnerhacke 	struct vlan	vlan[10];
56*6b08e68bSLutz Donnerhacke }		__packed;
57*6b08e68bSLutz Donnerhacke 
58*6b08e68bSLutz Donnerhacke static struct frame msg = {
59*6b08e68bSLutz Donnerhacke 	.src = {2, 4, 6, 1, 3, 5},
60*6b08e68bSLutz Donnerhacke 	.dst = {2, 4, 6, 1, 3, 7},
61*6b08e68bSLutz Donnerhacke 	.vlan[0] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(1, 0, 0))},
62*6b08e68bSLutz Donnerhacke 	.vlan[1] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(2, 0, 0))},
63*6b08e68bSLutz Donnerhacke 	.vlan[2] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(3, 0, 0))},
64*6b08e68bSLutz Donnerhacke 	.vlan[3] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(4, 0, 0))},
65*6b08e68bSLutz Donnerhacke 	.vlan[4] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(5, 0, 0))},
66*6b08e68bSLutz Donnerhacke 	.vlan[5] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(6, 0, 0))},
67*6b08e68bSLutz Donnerhacke 	.vlan[6] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(7, 0, 0))},
68*6b08e68bSLutz Donnerhacke 	.vlan[7] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(8, 0, 0))},
69*6b08e68bSLutz Donnerhacke 	.vlan[8] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(9, 0, 0))},
70*6b08e68bSLutz Donnerhacke 	.vlan[9] = {0}
71*6b08e68bSLutz Donnerhacke };
72*6b08e68bSLutz Donnerhacke 
73*6b08e68bSLutz Donnerhacke static void	_basic(int);
74*6b08e68bSLutz Donnerhacke static void	get_vlan(void *data, size_t len, void *ctx);
75*6b08e68bSLutz Donnerhacke 
76*6b08e68bSLutz Donnerhacke static void
get_vlan(void * data,size_t len,void * ctx)77*6b08e68bSLutz Donnerhacke get_vlan(void *data, size_t len, void *ctx)
78*6b08e68bSLutz Donnerhacke {
79*6b08e68bSLutz Donnerhacke 	int	       *v = ctx, i;
80*6b08e68bSLutz Donnerhacke 	struct frame   *f = data;
81*6b08e68bSLutz Donnerhacke 
82*6b08e68bSLutz Donnerhacke 	(void)len;
83*6b08e68bSLutz Donnerhacke 	for (i = 0; i < 10; i++)
84*6b08e68bSLutz Donnerhacke 		v[i] = EVL_VLANOFTAG(ntohs(f->vlan[i].tag));
85*6b08e68bSLutz Donnerhacke }
86*6b08e68bSLutz Donnerhacke 
87*6b08e68bSLutz Donnerhacke static void
_basic(int direction)88*6b08e68bSLutz Donnerhacke _basic(int direction)
89*6b08e68bSLutz Donnerhacke {
90*6b08e68bSLutz Donnerhacke 	int		r[10];
91*6b08e68bSLutz Donnerhacke 	int		i, rot, len;
92*6b08e68bSLutz Donnerhacke 
93*6b08e68bSLutz Donnerhacke 	ng_init();
94*6b08e68bSLutz Donnerhacke 	ng_errors(PASS);
95*6b08e68bSLutz Donnerhacke 	ng_shutdown("vr:");
96*6b08e68bSLutz Donnerhacke 	ng_errors(FAIL);
97*6b08e68bSLutz Donnerhacke 
98*6b08e68bSLutz Donnerhacke 	ng_mkpeer(".", "a", "vlan_rotate", direction > 0 ? "original" : "ordered");
99*6b08e68bSLutz Donnerhacke 	ng_name("a", "vr");
100*6b08e68bSLutz Donnerhacke 	ng_connect(".", "b", "vr:", direction > 0 ? "ordered" : "original");
101*6b08e68bSLutz Donnerhacke 	ng_register_data("b", get_vlan);
102*6b08e68bSLutz Donnerhacke 
103*6b08e68bSLutz Donnerhacke 	for (len = 9; len > 0; len--)
104*6b08e68bSLutz Donnerhacke 	{
105*6b08e68bSLutz Donnerhacke 		/* reduce the number of vlans */
106*6b08e68bSLutz Donnerhacke 		msg.vlan[len].proto = htons(ETHERTYPE_IP);
107*6b08e68bSLutz Donnerhacke 
108*6b08e68bSLutz Donnerhacke 		for (rot = -len + 1; rot < len; rot++)
109*6b08e68bSLutz Donnerhacke 		{
110*6b08e68bSLutz Donnerhacke 			char		cmd[40];
111*6b08e68bSLutz Donnerhacke 
112*6b08e68bSLutz Donnerhacke 			/* set rotation offset */
113*6b08e68bSLutz Donnerhacke 			snprintf(cmd, sizeof(cmd), "setconf { min=0 max=9 rot=%d }", rot);
114*6b08e68bSLutz Donnerhacke 			ng_send_msg("vr:", cmd);
115*6b08e68bSLutz Donnerhacke 
116*6b08e68bSLutz Donnerhacke 			ng_send_data("a", &msg, sizeof(msg));
117*6b08e68bSLutz Donnerhacke 			ng_handle_events(50, &r);
118*6b08e68bSLutz Donnerhacke 
119*6b08e68bSLutz Donnerhacke 			/* check rotation */
120*6b08e68bSLutz Donnerhacke 			for (i = 0; i < len; i++)
121*6b08e68bSLutz Donnerhacke 			{
122*6b08e68bSLutz Donnerhacke 				int		expect = (2 * len + i - direction * rot) % len + 1;
123*6b08e68bSLutz Donnerhacke 				int		vlan = r[i];
124*6b08e68bSLutz Donnerhacke 
125*6b08e68bSLutz Donnerhacke 				ATF_CHECK_MSG(vlan == expect,
126*6b08e68bSLutz Donnerhacke 				 "len=%d rot=%d i=%d -> vlan=%d, expect=%d",
127*6b08e68bSLutz Donnerhacke 					      len, rot, i, r[i], expect);
128*6b08e68bSLutz Donnerhacke 			}
129*6b08e68bSLutz Donnerhacke 		}
130*6b08e68bSLutz Donnerhacke 	}
131*6b08e68bSLutz Donnerhacke 
132*6b08e68bSLutz Donnerhacke 	ng_shutdown("vr:");
133*6b08e68bSLutz Donnerhacke }
134*6b08e68bSLutz Donnerhacke 
135*6b08e68bSLutz Donnerhacke ATF_TC(basic);
ATF_TC_HEAD(basic,conf)136*6b08e68bSLutz Donnerhacke ATF_TC_HEAD(basic, conf)
137*6b08e68bSLutz Donnerhacke {
138*6b08e68bSLutz Donnerhacke 	atf_tc_set_md_var(conf, "require.user", "root");
139*6b08e68bSLutz Donnerhacke }
140*6b08e68bSLutz Donnerhacke 
ATF_TC_BODY(basic,dummy)141*6b08e68bSLutz Donnerhacke ATF_TC_BODY(basic, dummy)
142*6b08e68bSLutz Donnerhacke {
143*6b08e68bSLutz Donnerhacke 	_basic(1);
144*6b08e68bSLutz Donnerhacke }
145*6b08e68bSLutz Donnerhacke 
146*6b08e68bSLutz Donnerhacke ATF_TC(reverse);
ATF_TC_HEAD(reverse,conf)147*6b08e68bSLutz Donnerhacke ATF_TC_HEAD(reverse, conf)
148*6b08e68bSLutz Donnerhacke {
149*6b08e68bSLutz Donnerhacke 	atf_tc_set_md_var(conf, "require.user", "root");
150*6b08e68bSLutz Donnerhacke }
151*6b08e68bSLutz Donnerhacke 
ATF_TC_BODY(reverse,dummy)152*6b08e68bSLutz Donnerhacke ATF_TC_BODY(reverse, dummy)
153*6b08e68bSLutz Donnerhacke {
154*6b08e68bSLutz Donnerhacke 	_basic(-1);
155*6b08e68bSLutz Donnerhacke }
156*6b08e68bSLutz Donnerhacke 
157*6b08e68bSLutz Donnerhacke static void	_ethertype(int);
158*6b08e68bSLutz Donnerhacke static void	get_ethertype(void *data, size_t len, void *ctx);
159*6b08e68bSLutz Donnerhacke 
160*6b08e68bSLutz Donnerhacke static void
get_ethertype(void * data,size_t len,void * ctx)161*6b08e68bSLutz Donnerhacke get_ethertype(void *data, size_t len, void *ctx)
162*6b08e68bSLutz Donnerhacke {
163*6b08e68bSLutz Donnerhacke 	int	       *v = ctx, i;
164*6b08e68bSLutz Donnerhacke 	struct frame   *f = data;
165*6b08e68bSLutz Donnerhacke 
166*6b08e68bSLutz Donnerhacke 	(void)len;
167*6b08e68bSLutz Donnerhacke 	for (i = 0; i < 10; i++)
168*6b08e68bSLutz Donnerhacke 		v[i] = ntohs(f->vlan[i].proto);
169*6b08e68bSLutz Donnerhacke }
170*6b08e68bSLutz Donnerhacke 
171*6b08e68bSLutz Donnerhacke static void
_ethertype(int direction)172*6b08e68bSLutz Donnerhacke _ethertype(int direction)
173*6b08e68bSLutz Donnerhacke {
174*6b08e68bSLutz Donnerhacke 	int		r[10];
175*6b08e68bSLutz Donnerhacke 	int		i, rounds = 20;
176*6b08e68bSLutz Donnerhacke 
177*6b08e68bSLutz Donnerhacke 	ng_init();
178*6b08e68bSLutz Donnerhacke 	ng_errors(PASS);
179*6b08e68bSLutz Donnerhacke 	ng_shutdown("vr:");
180*6b08e68bSLutz Donnerhacke 	ng_errors(FAIL);
181*6b08e68bSLutz Donnerhacke 
182*6b08e68bSLutz Donnerhacke 	ng_mkpeer(".", "a", "vlan_rotate", direction > 0 ? "original" : "ordered");
183*6b08e68bSLutz Donnerhacke 	ng_name("a", "vr");
184*6b08e68bSLutz Donnerhacke 	ng_connect(".", "b", "vr:", direction > 0 ? "ordered" : "original");
185*6b08e68bSLutz Donnerhacke 	ng_register_data("b", get_ethertype);
186*6b08e68bSLutz Donnerhacke 
187*6b08e68bSLutz Donnerhacke 	while (rounds-- > 0)
188*6b08e68bSLutz Donnerhacke 	{
189*6b08e68bSLutz Donnerhacke 		char		cmd[40];
190*6b08e68bSLutz Donnerhacke 		int		len = 9;
191*6b08e68bSLutz Donnerhacke 		int		rot = rand() % (2 * len - 1) - len + 1;
192*6b08e68bSLutz Donnerhacke 		int		vlan[10];
193*6b08e68bSLutz Donnerhacke 
194*6b08e68bSLutz Donnerhacke 		for (i = 0; i < len; i++)
195*6b08e68bSLutz Donnerhacke 		{
196*6b08e68bSLutz Donnerhacke 			switch (rand() % 3)
197*6b08e68bSLutz Donnerhacke 			{
198*6b08e68bSLutz Donnerhacke 			default:
199*6b08e68bSLutz Donnerhacke 				msg.vlan[i].proto = htons(ETHERTYPE_VLAN);
200*6b08e68bSLutz Donnerhacke 				break;
201*6b08e68bSLutz Donnerhacke 			case 1:
202*6b08e68bSLutz Donnerhacke 				msg.vlan[i].proto = htons(ETHERTYPE_QINQ);
203*6b08e68bSLutz Donnerhacke 				break;
204*6b08e68bSLutz Donnerhacke 			case 2:
205*6b08e68bSLutz Donnerhacke 				msg.vlan[i].proto = htons(ETHERTYPE_8021Q9100);
206*6b08e68bSLutz Donnerhacke 				break;
207*6b08e68bSLutz Donnerhacke 			}
208*6b08e68bSLutz Donnerhacke 		}
209*6b08e68bSLutz Donnerhacke 		msg.vlan[i].proto = htons(ETHERTYPE_IP);
210*6b08e68bSLutz Donnerhacke 
211*6b08e68bSLutz Donnerhacke 		for (i = 0; i < len; i++)
212*6b08e68bSLutz Donnerhacke 			vlan[i] = msg.vlan[i].proto;
213*6b08e68bSLutz Donnerhacke 
214*6b08e68bSLutz Donnerhacke 		snprintf(cmd, sizeof(cmd), "setconf { min=0 max=9 rot=%d }", rot);
215*6b08e68bSLutz Donnerhacke 		ng_send_msg("vr:", cmd);
216*6b08e68bSLutz Donnerhacke 
217*6b08e68bSLutz Donnerhacke 		bzero(r, sizeof(r));
218*6b08e68bSLutz Donnerhacke 		ng_send_data("a", &msg, sizeof(msg));
219*6b08e68bSLutz Donnerhacke 		ng_handle_events(50, &r);
220*6b08e68bSLutz Donnerhacke 
221*6b08e68bSLutz Donnerhacke 		/* check rotation */
222*6b08e68bSLutz Donnerhacke 		for (i = 0; i < len; i++)
223*6b08e68bSLutz Donnerhacke 		{
224*6b08e68bSLutz Donnerhacke 			int		expect = (2 * len + i - direction * rot) % len;
225*6b08e68bSLutz Donnerhacke 
226*6b08e68bSLutz Donnerhacke 			ATF_CHECK_MSG(r[i] == ntohs(vlan[expect]),
227*6b08e68bSLutz Donnerhacke 			 "len=%d rot=%d i=%d -> vlan=%04x, expect(%d)=%04x",
228*6b08e68bSLutz Donnerhacke 			    len, rot, i, ntohs(r[i]), expect, vlan[expect]);
229*6b08e68bSLutz Donnerhacke 		}
230*6b08e68bSLutz Donnerhacke 	}
231*6b08e68bSLutz Donnerhacke 
232*6b08e68bSLutz Donnerhacke 	ng_shutdown("vr:");
233*6b08e68bSLutz Donnerhacke }
234*6b08e68bSLutz Donnerhacke 
235*6b08e68bSLutz Donnerhacke ATF_TC(ethertype);
ATF_TC_HEAD(ethertype,conf)236*6b08e68bSLutz Donnerhacke ATF_TC_HEAD(ethertype, conf)
237*6b08e68bSLutz Donnerhacke {
238*6b08e68bSLutz Donnerhacke 	atf_tc_set_md_var(conf, "require.user", "root");
239*6b08e68bSLutz Donnerhacke }
240*6b08e68bSLutz Donnerhacke 
ATF_TC_BODY(ethertype,dummy)241*6b08e68bSLutz Donnerhacke ATF_TC_BODY(ethertype, dummy)
242*6b08e68bSLutz Donnerhacke {
243*6b08e68bSLutz Donnerhacke 	_ethertype(1);
244*6b08e68bSLutz Donnerhacke }
245*6b08e68bSLutz Donnerhacke 
246*6b08e68bSLutz Donnerhacke ATF_TC(typeether);
ATF_TC_HEAD(typeether,conf)247*6b08e68bSLutz Donnerhacke ATF_TC_HEAD(typeether, conf)
248*6b08e68bSLutz Donnerhacke {
249*6b08e68bSLutz Donnerhacke 	atf_tc_set_md_var(conf, "require.user", "root");
250*6b08e68bSLutz Donnerhacke }
251*6b08e68bSLutz Donnerhacke 
ATF_TC_BODY(typeether,dummy)252*6b08e68bSLutz Donnerhacke ATF_TC_BODY(typeether, dummy)
253*6b08e68bSLutz Donnerhacke {
254*6b08e68bSLutz Donnerhacke 	_ethertype(-1);
255*6b08e68bSLutz Donnerhacke }
256*6b08e68bSLutz Donnerhacke 
257*6b08e68bSLutz Donnerhacke ATF_TC(minmax);
ATF_TC_HEAD(minmax,conf)258*6b08e68bSLutz Donnerhacke ATF_TC_HEAD(minmax, conf)
259*6b08e68bSLutz Donnerhacke {
260*6b08e68bSLutz Donnerhacke 	atf_tc_set_md_var(conf, "require.user", "root");
261*6b08e68bSLutz Donnerhacke }
262*6b08e68bSLutz Donnerhacke 
ATF_TC_BODY(minmax,dummy)263*6b08e68bSLutz Donnerhacke ATF_TC_BODY(minmax, dummy)
264*6b08e68bSLutz Donnerhacke {
265*6b08e68bSLutz Donnerhacke 	ng_counter_t	r;
266*6b08e68bSLutz Donnerhacke 	int		len;
267*6b08e68bSLutz Donnerhacke 
268*6b08e68bSLutz Donnerhacke 	ng_init();
269*6b08e68bSLutz Donnerhacke 	ng_errors(PASS);
270*6b08e68bSLutz Donnerhacke 	ng_shutdown("vr:");
271*6b08e68bSLutz Donnerhacke 	ng_errors(FAIL);
272*6b08e68bSLutz Donnerhacke 
273*6b08e68bSLutz Donnerhacke 	ng_mkpeer(".", "a", "vlan_rotate", "original");
274*6b08e68bSLutz Donnerhacke 	ng_name("a", "vr");
275*6b08e68bSLutz Donnerhacke 	ng_connect(".", "b", "vr:", "ordered");
276*6b08e68bSLutz Donnerhacke 	ng_connect(".", "c", "vr:", "excessive");
277*6b08e68bSLutz Donnerhacke 	ng_connect(".", "d", "vr:", "incomplete");
278*6b08e68bSLutz Donnerhacke 	ng_register_data("a", get_data0);
279*6b08e68bSLutz Donnerhacke 	ng_register_data("b", get_data1);
280*6b08e68bSLutz Donnerhacke 	ng_register_data("c", get_data2);
281*6b08e68bSLutz Donnerhacke 	ng_register_data("d", get_data3);
282*6b08e68bSLutz Donnerhacke 
283*6b08e68bSLutz Donnerhacke 	ng_send_msg("vr:", "setconf { min=3 max=7 rot=0 }");
284*6b08e68bSLutz Donnerhacke 	for (len = 9; len > 0; len--)
285*6b08e68bSLutz Donnerhacke 	{
286*6b08e68bSLutz Donnerhacke 		/* reduce the number of vlans */
287*6b08e68bSLutz Donnerhacke 		msg.vlan[len].proto = htons(ETHERTYPE_IP);
288*6b08e68bSLutz Donnerhacke 
289*6b08e68bSLutz Donnerhacke 		ng_counter_clear(r);
290*6b08e68bSLutz Donnerhacke 		ng_send_data("a", &msg, sizeof(msg));
291*6b08e68bSLutz Donnerhacke 		ng_handle_events(50, &r);
292*6b08e68bSLutz Donnerhacke 		if (len < 3)
293*6b08e68bSLutz Donnerhacke 			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 0 && r[3] == 1);
294*6b08e68bSLutz Donnerhacke 		else if (len > 7)
295*6b08e68bSLutz Donnerhacke 			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0);
296*6b08e68bSLutz Donnerhacke 		else
297*6b08e68bSLutz Donnerhacke 			ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 0 && r[3] == 0);
298*6b08e68bSLutz Donnerhacke 
299*6b08e68bSLutz Donnerhacke 		ng_counter_clear(r);
300*6b08e68bSLutz Donnerhacke 		ng_send_data("b", &msg, sizeof(msg));
301*6b08e68bSLutz Donnerhacke 		ng_handle_events(50, &r);
302*6b08e68bSLutz Donnerhacke 		if (len < 3)
303*6b08e68bSLutz Donnerhacke 			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 0 && r[3] == 1);
304*6b08e68bSLutz Donnerhacke 		else if (len > 7)
305*6b08e68bSLutz Donnerhacke 			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0);
306*6b08e68bSLutz Donnerhacke 		else
307*6b08e68bSLutz Donnerhacke 			ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
308*6b08e68bSLutz Donnerhacke 
309*6b08e68bSLutz Donnerhacke 		ng_counter_clear(r);
310*6b08e68bSLutz Donnerhacke 		ng_send_data("c", &msg, sizeof(msg));
311*6b08e68bSLutz Donnerhacke 		ng_handle_events(50, &r);
312*6b08e68bSLutz Donnerhacke 		ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
313*6b08e68bSLutz Donnerhacke 
314*6b08e68bSLutz Donnerhacke 		ng_counter_clear(r);
315*6b08e68bSLutz Donnerhacke 		ng_send_data("d", &msg, sizeof(msg));
316*6b08e68bSLutz Donnerhacke 		ng_handle_events(50, &r);
317*6b08e68bSLutz Donnerhacke 		ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
318*6b08e68bSLutz Donnerhacke 	}
319*6b08e68bSLutz Donnerhacke 
320*6b08e68bSLutz Donnerhacke 	ng_shutdown("vr:");
321*6b08e68bSLutz Donnerhacke }
322*6b08e68bSLutz Donnerhacke 
ATF_TP_ADD_TCS(vlan_rotate)323*6b08e68bSLutz Donnerhacke ATF_TP_ADD_TCS(vlan_rotate)
324*6b08e68bSLutz Donnerhacke {
325*6b08e68bSLutz Donnerhacke 	/* Use "dd if=/dev/random bs=2 count=1 | od -x" to reproduce */
326*6b08e68bSLutz Donnerhacke 	srand(0xb93b);
327*6b08e68bSLutz Donnerhacke 
328*6b08e68bSLutz Donnerhacke 	ATF_TP_ADD_TC(vlan_rotate, basic);
329*6b08e68bSLutz Donnerhacke 	ATF_TP_ADD_TC(vlan_rotate, ethertype);
330*6b08e68bSLutz Donnerhacke 	ATF_TP_ADD_TC(vlan_rotate, reverse);
331*6b08e68bSLutz Donnerhacke 	ATF_TP_ADD_TC(vlan_rotate, typeether);
332*6b08e68bSLutz Donnerhacke 	ATF_TP_ADD_TC(vlan_rotate, minmax);
333*6b08e68bSLutz Donnerhacke 
334*6b08e68bSLutz Donnerhacke 	return atf_no_error();
335*6b08e68bSLutz Donnerhacke }
336