xref: /xnu-11417.121.6/tests/net_vlan.c (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1*a1e26a70SApple OSS Distributions /*
2*a1e26a70SApple OSS Distributions  * Copyright (c) 2024 Apple Inc. All rights reserved.
3*a1e26a70SApple OSS Distributions  *
4*a1e26a70SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*a1e26a70SApple OSS Distributions  *
6*a1e26a70SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*a1e26a70SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*a1e26a70SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*a1e26a70SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*a1e26a70SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*a1e26a70SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*a1e26a70SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*a1e26a70SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*a1e26a70SApple OSS Distributions  *
15*a1e26a70SApple OSS Distributions  * Please obtain a copy of the License at
16*a1e26a70SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*a1e26a70SApple OSS Distributions  *
18*a1e26a70SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*a1e26a70SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*a1e26a70SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*a1e26a70SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*a1e26a70SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*a1e26a70SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*a1e26a70SApple OSS Distributions  * limitations under the License.
25*a1e26a70SApple OSS Distributions  *
26*a1e26a70SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*a1e26a70SApple OSS Distributions  */
28*a1e26a70SApple OSS Distributions 
29*a1e26a70SApple OSS Distributions /*
30*a1e26a70SApple OSS Distributions  * net_vlan.c
31*a1e26a70SApple OSS Distributions  * - test if_vlan.c functionality
32*a1e26a70SApple OSS Distributions  */
33*a1e26a70SApple OSS Distributions 
34*a1e26a70SApple OSS Distributions #include <darwintest.h>
35*a1e26a70SApple OSS Distributions #include <stdio.h>
36*a1e26a70SApple OSS Distributions #include <unistd.h>
37*a1e26a70SApple OSS Distributions #include <stddef.h>
38*a1e26a70SApple OSS Distributions #include <stdlib.h>
39*a1e26a70SApple OSS Distributions #include <string.h>
40*a1e26a70SApple OSS Distributions #include <sys/socket.h>
41*a1e26a70SApple OSS Distributions #include <arpa/inet.h>
42*a1e26a70SApple OSS Distributions #include <sys/event.h>
43*a1e26a70SApple OSS Distributions #include <net/if.h>
44*a1e26a70SApple OSS Distributions #include <net/if_vlan_var.h>
45*a1e26a70SApple OSS Distributions #include <netinet/in.h>
46*a1e26a70SApple OSS Distributions #include <netinet6/in6_var.h>
47*a1e26a70SApple OSS Distributions #include <netinet6/nd6.h>
48*a1e26a70SApple OSS Distributions #include <netinet/in.h>
49*a1e26a70SApple OSS Distributions #include <netinet/ip.h>
50*a1e26a70SApple OSS Distributions #include <netinet/udp.h>
51*a1e26a70SApple OSS Distributions #include <netinet/tcp.h>
52*a1e26a70SApple OSS Distributions #include <netinet/if_ether.h>
53*a1e26a70SApple OSS Distributions #include <netinet/ip6.h>
54*a1e26a70SApple OSS Distributions #include <netinet/icmp6.h>
55*a1e26a70SApple OSS Distributions #include <net/if_arp.h>
56*a1e26a70SApple OSS Distributions #include <net/bpf.h>
57*a1e26a70SApple OSS Distributions #include <sys/ioctl.h>
58*a1e26a70SApple OSS Distributions #include <sys/types.h>
59*a1e26a70SApple OSS Distributions #include <sys/stat.h>
60*a1e26a70SApple OSS Distributions #include <errno.h>
61*a1e26a70SApple OSS Distributions #include <pthread.h>
62*a1e26a70SApple OSS Distributions #include <stdbool.h>
63*a1e26a70SApple OSS Distributions #include <TargetConditionals.h>
64*a1e26a70SApple OSS Distributions #include <darwintest_utils.h>
65*a1e26a70SApple OSS Distributions #include <os/variant_private.h>
66*a1e26a70SApple OSS Distributions 
67*a1e26a70SApple OSS Distributions #include "net_test_lib.h"
68*a1e26a70SApple OSS Distributions #include "inet_transfer.h"
69*a1e26a70SApple OSS Distributions #include "bpflib.h"
70*a1e26a70SApple OSS Distributions #include "in_cksum.h"
71*a1e26a70SApple OSS Distributions 
72*a1e26a70SApple OSS Distributions #define VLAN_UNIT_START         200 /* start at vlan200 to avoid conflicts */
73*a1e26a70SApple OSS Distributions #define TEN_NET                 0x0a000000
74*a1e26a70SApple OSS Distributions #define TEN_1_NET               (TEN_NET | 0x010000)
75*a1e26a70SApple OSS Distributions #define VLAN_TAG_START          1
76*a1e26a70SApple OSS Distributions 
77*a1e26a70SApple OSS Distributions static void
get_ipv4_address(u_int unit,u_int addr_index,struct in_addr * ip)78*a1e26a70SApple OSS Distributions get_ipv4_address(u_int unit, u_int addr_index, struct in_addr *ip)
79*a1e26a70SApple OSS Distributions {
80*a1e26a70SApple OSS Distributions 	/* up to 255 units, 255 addresses */
81*a1e26a70SApple OSS Distributions 	ip->s_addr = htonl(TEN_1_NET | (unit << 8) | addr_index);
82*a1e26a70SApple OSS Distributions 	return;
83*a1e26a70SApple OSS Distributions }
84*a1e26a70SApple OSS Distributions 
85*a1e26a70SApple OSS Distributions /**
86*a1e26a70SApple OSS Distributions ** interface management
87*a1e26a70SApple OSS Distributions **/
88*a1e26a70SApple OSS Distributions 
89*a1e26a70SApple OSS Distributions /**
90*a1e26a70SApple OSS Distributions ** Test Main
91*a1e26a70SApple OSS Distributions **/
92*a1e26a70SApple OSS Distributions static network_interface_pair_list_t    S_feth_pairs;
93*a1e26a70SApple OSS Distributions static network_interface_pair_list_t    S_vlan_pairs;
94*a1e26a70SApple OSS Distributions static const char *                     S_bridge;
95*a1e26a70SApple OSS Distributions 
96*a1e26a70SApple OSS Distributions #define VLAN_SYSCTL                     "net.link.vlan"
97*a1e26a70SApple OSS Distributions #define VLAN_SYSCTL_ENABLED             VLAN_SYSCTL ".enabled"
98*a1e26a70SApple OSS Distributions 
99*a1e26a70SApple OSS Distributions #define FAKE_SYSCTL                     "net.link.fake"
100*a1e26a70SApple OSS Distributions #define FAKE_SYSCTL_BSD_MODE            FAKE_SYSCTL ".bsd_mode"
101*a1e26a70SApple OSS Distributions #define FAKE_SYSCTL_VLAN_TAGGING        FAKE_SYSCTL ".vlan_tagging"
102*a1e26a70SApple OSS Distributions 
103*a1e26a70SApple OSS Distributions static int fake_bsd_mode;
104*a1e26a70SApple OSS Distributions static bool fake_bsd_mode_was_set;
105*a1e26a70SApple OSS Distributions static int fake_vlan_tagging;
106*a1e26a70SApple OSS Distributions static bool fake_vlan_tagging_was_set;
107*a1e26a70SApple OSS Distributions 
108*a1e26a70SApple OSS Distributions static void
sysctl_set_integer(const char * name,int val,int * restore_val,bool * was_set)109*a1e26a70SApple OSS Distributions sysctl_set_integer(const char * name, int val, int * restore_val,
110*a1e26a70SApple OSS Distributions     bool * was_set)
111*a1e26a70SApple OSS Distributions {
112*a1e26a70SApple OSS Distributions 	int     error;
113*a1e26a70SApple OSS Distributions 	size_t  len;
114*a1e26a70SApple OSS Distributions 
115*a1e26a70SApple OSS Distributions 	T_LOG("%s\n", __func__);
116*a1e26a70SApple OSS Distributions 	len = sizeof(int);
117*a1e26a70SApple OSS Distributions 	error = sysctlbyname(name, restore_val, &len, &val, sizeof(int));
118*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ(error, 0, "sysctl %s %d -> %d", name, *restore_val, val);
119*a1e26a70SApple OSS Distributions 	*was_set = (*restore_val != val);
120*a1e26a70SApple OSS Distributions }
121*a1e26a70SApple OSS Distributions 
122*a1e26a70SApple OSS Distributions static void
sysctl_restore_integer(const char * name,int restore_val,bool was_set)123*a1e26a70SApple OSS Distributions sysctl_restore_integer(const char * name, int restore_val, bool was_set)
124*a1e26a70SApple OSS Distributions {
125*a1e26a70SApple OSS Distributions 	if (was_set) {
126*a1e26a70SApple OSS Distributions 		int     error;
127*a1e26a70SApple OSS Distributions 
128*a1e26a70SApple OSS Distributions 		error = sysctlbyname(name, NULL, 0, &restore_val, sizeof(int));
129*a1e26a70SApple OSS Distributions 		T_ASSERT_EQ(error, 0, "sysctl %s %d", name, restore_val);
130*a1e26a70SApple OSS Distributions 	} else {
131*a1e26a70SApple OSS Distributions 		T_LOG("sysctl %s not modified", name);
132*a1e26a70SApple OSS Distributions 	}
133*a1e26a70SApple OSS Distributions }
134*a1e26a70SApple OSS Distributions 
135*a1e26a70SApple OSS Distributions static void
fake_set_bsd_mode(bool enable)136*a1e26a70SApple OSS Distributions fake_set_bsd_mode(bool enable)
137*a1e26a70SApple OSS Distributions {
138*a1e26a70SApple OSS Distributions 	sysctl_set_integer(FAKE_SYSCTL_BSD_MODE, enable ? 1 : 0,
139*a1e26a70SApple OSS Distributions 	    &fake_bsd_mode, &fake_bsd_mode_was_set);
140*a1e26a70SApple OSS Distributions }
141*a1e26a70SApple OSS Distributions 
142*a1e26a70SApple OSS Distributions static void
fake_restore_bsd_mode(void)143*a1e26a70SApple OSS Distributions fake_restore_bsd_mode(void)
144*a1e26a70SApple OSS Distributions {
145*a1e26a70SApple OSS Distributions 	sysctl_restore_integer(FAKE_SYSCTL_BSD_MODE,
146*a1e26a70SApple OSS Distributions 	    fake_bsd_mode, fake_bsd_mode_was_set);
147*a1e26a70SApple OSS Distributions }
148*a1e26a70SApple OSS Distributions 
149*a1e26a70SApple OSS Distributions static void
fake_set_vlan_tagging(bool enable)150*a1e26a70SApple OSS Distributions fake_set_vlan_tagging(bool enable)
151*a1e26a70SApple OSS Distributions {
152*a1e26a70SApple OSS Distributions 	sysctl_set_integer(FAKE_SYSCTL_VLAN_TAGGING, enable ? 1 : 0,
153*a1e26a70SApple OSS Distributions 	    &fake_vlan_tagging, &fake_vlan_tagging_was_set);
154*a1e26a70SApple OSS Distributions }
155*a1e26a70SApple OSS Distributions 
156*a1e26a70SApple OSS Distributions static void
fake_restore_vlan_tagging(void)157*a1e26a70SApple OSS Distributions fake_restore_vlan_tagging(void)
158*a1e26a70SApple OSS Distributions {
159*a1e26a70SApple OSS Distributions 	sysctl_restore_integer(FAKE_SYSCTL_VLAN_TAGGING, fake_vlan_tagging,
160*a1e26a70SApple OSS Distributions 	    fake_vlan_tagging_was_set);
161*a1e26a70SApple OSS Distributions }
162*a1e26a70SApple OSS Distributions 
163*a1e26a70SApple OSS Distributions #if !TARGET_OS_BRIDGE
164*a1e26a70SApple OSS Distributions #if !TARGET_OS_OSX
165*a1e26a70SApple OSS Distributions static bool
vlan_is_enabled(void)166*a1e26a70SApple OSS Distributions vlan_is_enabled(void)
167*a1e26a70SApple OSS Distributions {
168*a1e26a70SApple OSS Distributions 	size_t  len = sizeof(int);
169*a1e26a70SApple OSS Distributions 	int     val = 0;
170*a1e26a70SApple OSS Distributions 
171*a1e26a70SApple OSS Distributions 	(void)sysctlbyname(VLAN_SYSCTL_ENABLED, &val, &len, NULL, 0);
172*a1e26a70SApple OSS Distributions 	return val != 0;
173*a1e26a70SApple OSS Distributions }
174*a1e26a70SApple OSS Distributions #endif /* !TARGET_OS_OSX */
175*a1e26a70SApple OSS Distributions #endif /* !TARGET_OS_BRIDGE */
176*a1e26a70SApple OSS Distributions 
177*a1e26a70SApple OSS Distributions static void
cleanup_common(void)178*a1e26a70SApple OSS Distributions cleanup_common(void)
179*a1e26a70SApple OSS Distributions {
180*a1e26a70SApple OSS Distributions 	if (G_debug) {
181*a1e26a70SApple OSS Distributions 		T_LOG("Sleeping for 5 seconds\n");
182*a1e26a70SApple OSS Distributions 		sleep(5);
183*a1e26a70SApple OSS Distributions 	}
184*a1e26a70SApple OSS Distributions 	if (S_bridge != NULL) {
185*a1e26a70SApple OSS Distributions 		ifnet_destroy(S_bridge, false);
186*a1e26a70SApple OSS Distributions 	}
187*a1e26a70SApple OSS Distributions 	fake_restore_bsd_mode();
188*a1e26a70SApple OSS Distributions 	fake_restore_vlan_tagging();
189*a1e26a70SApple OSS Distributions 	network_interface_pair_list_destroy(S_feth_pairs);
190*a1e26a70SApple OSS Distributions 	network_interface_pair_list_destroy(S_vlan_pairs);
191*a1e26a70SApple OSS Distributions 	return;
192*a1e26a70SApple OSS Distributions }
193*a1e26a70SApple OSS Distributions 
194*a1e26a70SApple OSS Distributions static void
cleanup(void)195*a1e26a70SApple OSS Distributions cleanup(void)
196*a1e26a70SApple OSS Distributions {
197*a1e26a70SApple OSS Distributions 	cleanup_common();
198*a1e26a70SApple OSS Distributions 	return;
199*a1e26a70SApple OSS Distributions }
200*a1e26a70SApple OSS Distributions 
201*a1e26a70SApple OSS Distributions static void
sigint_handler(__unused int sig)202*a1e26a70SApple OSS Distributions sigint_handler(__unused int sig)
203*a1e26a70SApple OSS Distributions {
204*a1e26a70SApple OSS Distributions 	cleanup_common();
205*a1e26a70SApple OSS Distributions 	signal(SIGINT, SIG_DFL);
206*a1e26a70SApple OSS Distributions }
207*a1e26a70SApple OSS Distributions 
208*a1e26a70SApple OSS Distributions static void
test_traffic_for_network_interfaces(network_interface_t one,network_interface_t two,uint8_t af)209*a1e26a70SApple OSS Distributions test_traffic_for_network_interfaces(network_interface_t one,
210*a1e26a70SApple OSS Distributions     network_interface_t two,
211*a1e26a70SApple OSS Distributions     uint8_t af)
212*a1e26a70SApple OSS Distributions {
213*a1e26a70SApple OSS Distributions 	inet_address    server;
214*a1e26a70SApple OSS Distributions 
215*a1e26a70SApple OSS Distributions 	T_LOG("Testing %s -> %s\n",
216*a1e26a70SApple OSS Distributions 	    one->if_name, two->if_name);
217*a1e26a70SApple OSS Distributions 	if (af == AF_INET) {
218*a1e26a70SApple OSS Distributions 		server.v4 = one->ip;
219*a1e26a70SApple OSS Distributions 	} else {
220*a1e26a70SApple OSS Distributions 		server.v6 = two->ip6;
221*a1e26a70SApple OSS Distributions 	}
222*a1e26a70SApple OSS Distributions 	inet_test_traffic(af, &server, one->if_name, one->if_index,
223*a1e26a70SApple OSS Distributions 	    two->if_name, two->if_index);
224*a1e26a70SApple OSS Distributions }
225*a1e26a70SApple OSS Distributions 
226*a1e26a70SApple OSS Distributions static void
test_traffic_for_pair(network_interface_pair_t pair,uint8_t af)227*a1e26a70SApple OSS Distributions test_traffic_for_pair(network_interface_pair_t pair, uint8_t af)
228*a1e26a70SApple OSS Distributions {
229*a1e26a70SApple OSS Distributions 	test_traffic_for_network_interfaces(&pair->one, &pair->two, af);
230*a1e26a70SApple OSS Distributions }
231*a1e26a70SApple OSS Distributions 
232*a1e26a70SApple OSS Distributions static void
test_traffic_for_af(uint8_t af)233*a1e26a70SApple OSS Distributions test_traffic_for_af(uint8_t af)
234*a1e26a70SApple OSS Distributions {
235*a1e26a70SApple OSS Distributions 	test_traffic_for_pair(S_feth_pairs->list, af);
236*a1e26a70SApple OSS Distributions 
237*a1e26a70SApple OSS Distributions 	for (u_int i = 0; i < S_vlan_pairs->count; i++) {
238*a1e26a70SApple OSS Distributions 		network_interface_pair_t        pair;
239*a1e26a70SApple OSS Distributions 
240*a1e26a70SApple OSS Distributions 		pair = &S_vlan_pairs->list[i];
241*a1e26a70SApple OSS Distributions 		test_traffic_for_pair(pair, af);
242*a1e26a70SApple OSS Distributions 	}
243*a1e26a70SApple OSS Distributions }
244*a1e26a70SApple OSS Distributions 
245*a1e26a70SApple OSS Distributions static void
network_interface_assign_address(network_interface_t netif,unsigned int unit,unsigned int address_index)246*a1e26a70SApple OSS Distributions network_interface_assign_address(network_interface_t netif,
247*a1e26a70SApple OSS Distributions     unsigned int unit, unsigned int address_index)
248*a1e26a70SApple OSS Distributions {
249*a1e26a70SApple OSS Distributions 	get_ipv4_address(unit, address_index, &netif->ip);
250*a1e26a70SApple OSS Distributions 	ifnet_add_ip_address(netif->if_name, netif->ip,
251*a1e26a70SApple OSS Distributions 	    inet_class_c_subnet_mask);
252*a1e26a70SApple OSS Distributions 	route_add_inet_scoped_subnet(netif->if_name, netif->if_index,
253*a1e26a70SApple OSS Distributions 	    netif->ip, inet_class_c_subnet_mask);
254*a1e26a70SApple OSS Distributions }
255*a1e26a70SApple OSS Distributions 
256*a1e26a70SApple OSS Distributions static void
initialize_feth_pairs(u_int n,bool need_address)257*a1e26a70SApple OSS Distributions initialize_feth_pairs(u_int n, bool need_address)
258*a1e26a70SApple OSS Distributions {
259*a1e26a70SApple OSS Distributions 	network_interface_pair_t        scan;
260*a1e26a70SApple OSS Distributions 
261*a1e26a70SApple OSS Distributions 	S_feth_pairs = network_interface_pair_list_alloc(n);
262*a1e26a70SApple OSS Distributions 	scan = S_feth_pairs->list;
263*a1e26a70SApple OSS Distributions 	for (unsigned int i = 0; i < n; i++, scan++) {
264*a1e26a70SApple OSS Distributions 		network_interface_create(&scan->one, FETH_NAME);
265*a1e26a70SApple OSS Distributions 		network_interface_create(&scan->two, FETH_NAME);
266*a1e26a70SApple OSS Distributions 		if (need_address) {
267*a1e26a70SApple OSS Distributions 			network_interface_assign_address(&scan->one, i, 1);
268*a1e26a70SApple OSS Distributions 			network_interface_assign_address(&scan->two, i, 2);
269*a1e26a70SApple OSS Distributions 		}
270*a1e26a70SApple OSS Distributions 		fake_set_peer(scan->one.if_name, scan->two.if_name);
271*a1e26a70SApple OSS Distributions 	}
272*a1e26a70SApple OSS Distributions }
273*a1e26a70SApple OSS Distributions 
274*a1e26a70SApple OSS Distributions static void
initialize_vlan_pairs(u_int n,bool need_address)275*a1e26a70SApple OSS Distributions initialize_vlan_pairs(u_int n, bool need_address)
276*a1e26a70SApple OSS Distributions {
277*a1e26a70SApple OSS Distributions 	network_interface_pair_t        feth_pair;
278*a1e26a70SApple OSS Distributions 	network_interface_pair_t        scan;
279*a1e26a70SApple OSS Distributions 	int                             vlan_unit = VLAN_UNIT_START;
280*a1e26a70SApple OSS Distributions 
281*a1e26a70SApple OSS Distributions 	feth_pair = S_feth_pairs->list;
282*a1e26a70SApple OSS Distributions 	S_vlan_pairs = network_interface_pair_list_alloc(n);
283*a1e26a70SApple OSS Distributions 	scan = S_vlan_pairs->list;
284*a1e26a70SApple OSS Distributions 	for (size_t i = 0; i < n; i++, scan++) {
285*a1e26a70SApple OSS Distributions 		if_name_t       name;
286*a1e26a70SApple OSS Distributions 		uint16_t        tag = (uint16_t)(i + VLAN_TAG_START);
287*a1e26a70SApple OSS Distributions 
288*a1e26a70SApple OSS Distributions 		snprintf(name, sizeof(name), "%s%d", VLAN_NAME, vlan_unit++);
289*a1e26a70SApple OSS Distributions 		network_interface_create(&scan->one, name);
290*a1e26a70SApple OSS Distributions 		siocsifvlan(scan->one.if_name, feth_pair->one.if_name, tag);
291*a1e26a70SApple OSS Distributions 		if (need_address) {
292*a1e26a70SApple OSS Distributions 			network_interface_assign_address(&scan->one, tag, 1);
293*a1e26a70SApple OSS Distributions 		}
294*a1e26a70SApple OSS Distributions 
295*a1e26a70SApple OSS Distributions 		snprintf(name, sizeof(name), "%s%d", VLAN_NAME, vlan_unit++);
296*a1e26a70SApple OSS Distributions 		network_interface_create(&scan->two, name);
297*a1e26a70SApple OSS Distributions 		siocsifvlan(scan->two.if_name, feth_pair->two.if_name, tag);
298*a1e26a70SApple OSS Distributions 		if (need_address) {
299*a1e26a70SApple OSS Distributions 			network_interface_assign_address(&scan->two, tag, 2);
300*a1e26a70SApple OSS Distributions 		}
301*a1e26a70SApple OSS Distributions 	}
302*a1e26a70SApple OSS Distributions }
303*a1e26a70SApple OSS Distributions 
304*a1e26a70SApple OSS Distributions static void
vlan_send_short_packet(void)305*a1e26a70SApple OSS Distributions vlan_send_short_packet(void)
306*a1e26a70SApple OSS Distributions {
307*a1e26a70SApple OSS Distributions 	ether_addr_t                    eaddr;
308*a1e26a70SApple OSS Distributions 	struct ether_vlan_header *      evl_p;
309*a1e26a70SApple OSS Distributions 	int                             fd;
310*a1e26a70SApple OSS Distributions 	size_t                          frame_length;
311*a1e26a70SApple OSS Distributions 	const char *                    ifname;
312*a1e26a70SApple OSS Distributions 	uint16_t *                      length;
313*a1e26a70SApple OSS Distributions 	uint8_t *                       data;
314*a1e26a70SApple OSS Distributions 	ssize_t                         n;
315*a1e26a70SApple OSS Distributions 	int                             opt;
316*a1e26a70SApple OSS Distributions 	ether_packet                    pkt;
317*a1e26a70SApple OSS Distributions 
318*a1e26a70SApple OSS Distributions 	ifname = S_feth_pairs->list->one.if_name;
319*a1e26a70SApple OSS Distributions 	fd = bpf_new();
320*a1e26a70SApple OSS Distributions 	T_ASSERT_GE(fd, 0, "bpf_new() %d", fd);
321*a1e26a70SApple OSS Distributions 	bpf_set_traffic_class(fd, SO_TC_CTL);
322*a1e26a70SApple OSS Distributions 	opt = 1;
323*a1e26a70SApple OSS Distributions 	T_QUIET;
324*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ioctl(fd, FIONBIO, &opt), NULL);
325*a1e26a70SApple OSS Distributions 	T_QUIET;
326*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(bpf_set_immediate(fd, 1), NULL);
327*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(bpf_setif(fd, ifname), "bpf set if %s",
328*a1e26a70SApple OSS Distributions 	    ifname);
329*a1e26a70SApple OSS Distributions 	T_QUIET;
330*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(bpf_set_see_sent(fd, 0), NULL);
331*a1e26a70SApple OSS Distributions 	T_QUIET;
332*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(bpf_set_header_complete(fd, 1), NULL);
333*a1e26a70SApple OSS Distributions 	T_QUIET;
334*a1e26a70SApple OSS Distributions 	ifnet_get_lladdr(ifname, &eaddr);
335*a1e26a70SApple OSS Distributions 
336*a1e26a70SApple OSS Distributions #define VLAN_SHORT_PAYLOAD_LENGTH       6
337*a1e26a70SApple OSS Distributions 	/* send broadcast 802.3 LLC frame of length 6 (rdar://129012466) */
338*a1e26a70SApple OSS Distributions 	bzero(&pkt, sizeof(pkt));
339*a1e26a70SApple OSS Distributions 	frame_length = sizeof(*evl_p) + VLAN_SHORT_PAYLOAD_LENGTH;
340*a1e26a70SApple OSS Distributions 	evl_p = (struct ether_vlan_header *)&pkt;
341*a1e26a70SApple OSS Distributions 	bcopy(&ether_broadcast, evl_p->evl_dhost, sizeof(evl_p->evl_dhost));
342*a1e26a70SApple OSS Distributions 	bcopy(&eaddr, evl_p->evl_shost, sizeof(evl_p->evl_shost));
343*a1e26a70SApple OSS Distributions 	evl_p->evl_tag = htons(VLAN_TAG_START);
344*a1e26a70SApple OSS Distributions 	evl_p->evl_encap_proto = htons(ETHERTYPE_VLAN);
345*a1e26a70SApple OSS Distributions 	length = (uint16_t *)&evl_p->evl_proto;
346*a1e26a70SApple OSS Distributions 	*length = htons(VLAN_SHORT_PAYLOAD_LENGTH);
347*a1e26a70SApple OSS Distributions 	/* make it an LLC frame so that it will decode as a valid packet */
348*a1e26a70SApple OSS Distributions 	data = (uint8_t *)(length + 1);
349*a1e26a70SApple OSS Distributions 	*data++ = 0x00;
350*a1e26a70SApple OSS Distributions 	*data++ = 0x0a;
351*a1e26a70SApple OSS Distributions 	*data++ = 0x00;
352*a1e26a70SApple OSS Distributions 	*data++ = 0x06;
353*a1e26a70SApple OSS Distributions 	*data++ = 0x00;
354*a1e26a70SApple OSS Distributions 	*data++ = 0x01;
355*a1e26a70SApple OSS Distributions 	n = write(fd, &pkt, frame_length);
356*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ((size_t)n, frame_length, "write");
357*a1e26a70SApple OSS Distributions 	close(fd);
358*a1e26a70SApple OSS Distributions }
359*a1e26a70SApple OSS Distributions 
360*a1e26a70SApple OSS Distributions static void
vlan_test_check_skip(void)361*a1e26a70SApple OSS Distributions vlan_test_check_skip(void)
362*a1e26a70SApple OSS Distributions {
363*a1e26a70SApple OSS Distributions #if TARGET_OS_BRIDGE
364*a1e26a70SApple OSS Distributions 	T_SKIP("Skipping test on bridgeOS");
365*a1e26a70SApple OSS Distributions #else /* TARGET_OS_BRIDGE */
366*a1e26a70SApple OSS Distributions #if !TARGET_OS_OSX
367*a1e26a70SApple OSS Distributions #define XNU_TEST_NET_VLAN       "com.apple.xnu.test.net_vlan"
368*a1e26a70SApple OSS Distributions 	if (!vlan_is_enabled()) {
369*a1e26a70SApple OSS Distributions 		if (os_variant_is_darwinos(XNU_TEST_NET_VLAN)) {
370*a1e26a70SApple OSS Distributions 			T_FAIL("darwinos should support VLAN");
371*a1e26a70SApple OSS Distributions 		}
372*a1e26a70SApple OSS Distributions 		if (os_variant_has_factory_content(XNU_TEST_NET_VLAN)) {
373*a1e26a70SApple OSS Distributions 			T_FAIL("non-ui should support VLAN");
374*a1e26a70SApple OSS Distributions 		}
375*a1e26a70SApple OSS Distributions 		T_SKIP("VLAN is not available on this os variant");
376*a1e26a70SApple OSS Distributions 	}
377*a1e26a70SApple OSS Distributions #endif /* !TARGET_OS_OSX */
378*a1e26a70SApple OSS Distributions #endif /* TARGET_OS_BRIDGE */
379*a1e26a70SApple OSS Distributions }
380*a1e26a70SApple OSS Distributions 
381*a1e26a70SApple OSS Distributions 
382*a1e26a70SApple OSS Distributions static void
vlan_test_traffic(bool hw_vlan)383*a1e26a70SApple OSS Distributions vlan_test_traffic(bool hw_vlan)
384*a1e26a70SApple OSS Distributions {
385*a1e26a70SApple OSS Distributions 	vlan_test_check_skip();
386*a1e26a70SApple OSS Distributions 
387*a1e26a70SApple OSS Distributions 	signal(SIGINT, sigint_handler);
388*a1e26a70SApple OSS Distributions 	T_ATEND(cleanup);
389*a1e26a70SApple OSS Distributions 	T_LOG("VLAN test %s\n",
390*a1e26a70SApple OSS Distributions 	    hw_vlan ? "hardware tagging" : "software tagging");
391*a1e26a70SApple OSS Distributions 	fake_set_bsd_mode(true);
392*a1e26a70SApple OSS Distributions 	fake_set_vlan_tagging(hw_vlan);
393*a1e26a70SApple OSS Distributions 	initialize_feth_pairs(1, true);
394*a1e26a70SApple OSS Distributions 	initialize_vlan_pairs(5, true);
395*a1e26a70SApple OSS Distributions 	test_traffic_for_af(AF_INET6);
396*a1e26a70SApple OSS Distributions 	test_traffic_for_af(AF_INET);
397*a1e26a70SApple OSS Distributions 	if (G_debug) {
398*a1e26a70SApple OSS Distributions 		T_LOG("Sleeping for 5 seconds\n");
399*a1e26a70SApple OSS Distributions 		sleep(5);
400*a1e26a70SApple OSS Distributions 	}
401*a1e26a70SApple OSS Distributions }
402*a1e26a70SApple OSS Distributions 
403*a1e26a70SApple OSS Distributions static void
vlan_test_bridged_traffic(bool hw_vlan)404*a1e26a70SApple OSS Distributions vlan_test_bridged_traffic(bool hw_vlan)
405*a1e26a70SApple OSS Distributions {
406*a1e26a70SApple OSS Distributions 	errno_t                         err;
407*a1e26a70SApple OSS Distributions 	network_interface_pair_t        feth_pair;
408*a1e26a70SApple OSS Distributions 	network_interface_pair_t        vlan_pair;
409*a1e26a70SApple OSS Distributions 
410*a1e26a70SApple OSS Distributions 	vlan_test_check_skip();
411*a1e26a70SApple OSS Distributions 
412*a1e26a70SApple OSS Distributions 	signal(SIGINT, sigint_handler);
413*a1e26a70SApple OSS Distributions 	T_ATEND(cleanup);
414*a1e26a70SApple OSS Distributions 	T_LOG("VLAN test bridged %s\n",
415*a1e26a70SApple OSS Distributions 	    hw_vlan ? "hardware tagging" : "software tagging");
416*a1e26a70SApple OSS Distributions 	fake_set_bsd_mode(true);
417*a1e26a70SApple OSS Distributions 	fake_set_vlan_tagging(hw_vlan);
418*a1e26a70SApple OSS Distributions 	initialize_feth_pairs(2, false);
419*a1e26a70SApple OSS Distributions 	initialize_vlan_pairs(1, false);
420*a1e26a70SApple OSS Distributions 
421*a1e26a70SApple OSS Distributions 	/* get the single VLAN pair */
422*a1e26a70SApple OSS Distributions 	vlan_pair = S_vlan_pairs->list;
423*a1e26a70SApple OSS Distributions 
424*a1e26a70SApple OSS Distributions 	/* get the second FETH pair */
425*a1e26a70SApple OSS Distributions 	feth_pair = S_feth_pairs->list + 1;
426*a1e26a70SApple OSS Distributions 
427*a1e26a70SApple OSS Distributions 	/* create a bridge */
428*a1e26a70SApple OSS Distributions 	S_bridge = BRIDGE200;
429*a1e26a70SApple OSS Distributions 	err = ifnet_create(S_bridge);
430*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ(err, 0, "ifnet_create %s", S_bridge);
431*a1e26a70SApple OSS Distributions 
432*a1e26a70SApple OSS Distributions 	/* add first VLAN to bridge */
433*a1e26a70SApple OSS Distributions 	err = bridge_add_member(S_bridge, vlan_pair->one.if_name);
434*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ(err, 0, "bridge_add_member(%s, %s)", S_bridge,
435*a1e26a70SApple OSS Distributions 	    vlan_pair->one.if_name);
436*a1e26a70SApple OSS Distributions 
437*a1e26a70SApple OSS Distributions 	/* assign address to second VLAN */
438*a1e26a70SApple OSS Distributions 	network_interface_assign_address(&vlan_pair->two, 0, 1);
439*a1e26a70SApple OSS Distributions 
440*a1e26a70SApple OSS Distributions 	/* add feth in second pair to bridge */
441*a1e26a70SApple OSS Distributions 	err = bridge_add_member(S_bridge, feth_pair->one.if_name);
442*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ(err, 0, "bridge_add_member(%s, %s)", S_bridge,
443*a1e26a70SApple OSS Distributions 	    feth_pair->one.if_name);
444*a1e26a70SApple OSS Distributions 
445*a1e26a70SApple OSS Distributions 	/* assign address to second feth in second pair */
446*a1e26a70SApple OSS Distributions 	network_interface_assign_address(&feth_pair->two, 0, 2);
447*a1e26a70SApple OSS Distributions 
448*a1e26a70SApple OSS Distributions 	test_traffic_for_network_interfaces(&vlan_pair->two, &feth_pair->two,
449*a1e26a70SApple OSS Distributions 	    AF_INET);
450*a1e26a70SApple OSS Distributions 	test_traffic_for_network_interfaces(&vlan_pair->two, &feth_pair->two,
451*a1e26a70SApple OSS Distributions 	    AF_INET6);
452*a1e26a70SApple OSS Distributions }
453*a1e26a70SApple OSS Distributions 
454*a1e26a70SApple OSS Distributions static void
vlan_test_short_packet(void)455*a1e26a70SApple OSS Distributions vlan_test_short_packet(void)
456*a1e26a70SApple OSS Distributions {
457*a1e26a70SApple OSS Distributions 	vlan_test_check_skip();
458*a1e26a70SApple OSS Distributions 
459*a1e26a70SApple OSS Distributions 	signal(SIGINT, sigint_handler);
460*a1e26a70SApple OSS Distributions 	T_ATEND(cleanup);
461*a1e26a70SApple OSS Distributions 	T_LOG("VLAN test short packet\n");
462*a1e26a70SApple OSS Distributions 	fake_set_bsd_mode(true);
463*a1e26a70SApple OSS Distributions 	fake_set_vlan_tagging(false);
464*a1e26a70SApple OSS Distributions 
465*a1e26a70SApple OSS Distributions 	initialize_feth_pairs(1, true);
466*a1e26a70SApple OSS Distributions 	initialize_vlan_pairs(1, true);
467*a1e26a70SApple OSS Distributions 	/* send VLAN packet over feth */
468*a1e26a70SApple OSS Distributions 	vlan_send_short_packet();
469*a1e26a70SApple OSS Distributions 	if (G_debug) {
470*a1e26a70SApple OSS Distributions 		T_LOG("Sleeping for 5 seconds\n");
471*a1e26a70SApple OSS Distributions 		sleep(5);
472*a1e26a70SApple OSS Distributions 	}
473*a1e26a70SApple OSS Distributions }
474*a1e26a70SApple OSS Distributions 
475*a1e26a70SApple OSS Distributions T_DECL(net_if_vlan_test_software_tagging,
476*a1e26a70SApple OSS Distributions     "vlan test traffic software tagging",
477*a1e26a70SApple OSS Distributions     T_META_ASROOT(true))
478*a1e26a70SApple OSS Distributions {
479*a1e26a70SApple OSS Distributions 	vlan_test_traffic(false);
480*a1e26a70SApple OSS Distributions }
481*a1e26a70SApple OSS Distributions 
482*a1e26a70SApple OSS Distributions T_DECL(net_if_vlan_test_hardware_tagging,
483*a1e26a70SApple OSS Distributions     "vlan test hardware tagging",
484*a1e26a70SApple OSS Distributions     T_META_ASROOT(true))
485*a1e26a70SApple OSS Distributions {
486*a1e26a70SApple OSS Distributions 	vlan_test_traffic(true);
487*a1e26a70SApple OSS Distributions }
488*a1e26a70SApple OSS Distributions 
489*a1e26a70SApple OSS Distributions T_DECL(net_if_vlan_test_software_tagging_bridged,
490*a1e26a70SApple OSS Distributions     "vlan test traffic software tagging bridged",
491*a1e26a70SApple OSS Distributions     T_META_ASROOT(true))
492*a1e26a70SApple OSS Distributions {
493*a1e26a70SApple OSS Distributions 	vlan_test_bridged_traffic(false);
494*a1e26a70SApple OSS Distributions }
495*a1e26a70SApple OSS Distributions 
496*a1e26a70SApple OSS Distributions T_DECL(net_if_vlan_test_hardware_tagging_bridged,
497*a1e26a70SApple OSS Distributions     "vlan test hardware tagging bridged",
498*a1e26a70SApple OSS Distributions     T_META_ASROOT(true))
499*a1e26a70SApple OSS Distributions {
500*a1e26a70SApple OSS Distributions 	vlan_test_bridged_traffic(true);
501*a1e26a70SApple OSS Distributions }
502*a1e26a70SApple OSS Distributions 
503*a1e26a70SApple OSS Distributions T_DECL(net_if_vlan_test_short_packet,
504*a1e26a70SApple OSS Distributions     "vlan test short packet",
505*a1e26a70SApple OSS Distributions     T_META_ASROOT(true))
506*a1e26a70SApple OSS Distributions {
507*a1e26a70SApple OSS Distributions 	vlan_test_short_packet();
508*a1e26a70SApple OSS Distributions }
509