xref: /xnu-12377.61.12/tests/net_bridge.c (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1 /*
2  * Copyright (c) 2019-2025 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * net_bridge.c
31  * - test if_bridge.c functionality
32  */
33 
34 #include <darwintest.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <stddef.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/socket.h>
41 #include <arpa/inet.h>
42 #include <sys/event.h>
43 #include <net/if.h>
44 #include <netinet/in.h>
45 #include <netinet6/in6_var.h>
46 #include <netinet6/nd6.h>
47 #include <netinet/in.h>
48 #include <netinet/ip.h>
49 #include <netinet/udp.h>
50 #include <netinet/tcp.h>
51 #include <netinet/if_ether.h>
52 #include <netinet/ip6.h>
53 #include <netinet/icmp6.h>
54 #include <net/if_arp.h>
55 #include <net/bpf.h>
56 #include <net/if_bridgevar.h>
57 #include <net/if_fake_var.h>
58 #include <sys/ioctl.h>
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <errno.h>
62 #include <pthread.h>
63 #include <stdbool.h>
64 #include <TargetConditionals.h>
65 #include <darwintest_utils.h>
66 
67 #include "net_test_lib.h"
68 #include "inet_transfer.h"
69 #include "bpflib.h"
70 #include "in_cksum.h"
71 
72 static bool S_cleaning_up;
73 
74 #define ALL_ADDRS (uint32_t)(-1)
75 
76 typedef struct {
77 	char            ifname[IFNAMSIZ];       /* port we do I/O on */
78 	ether_addr_t    mac;
79 	char            member_ifname[IFNAMSIZ]; /* member of bridge */
80 	ether_addr_t    member_mac;
81 	int             fd;
82 	u_int           unit;
83 	u_int           num_addrs;
84 	void *          rx_buf;
85 	int             rx_buf_size;
86 	bool            mac_nat;
87 	struct in_addr  ip;
88 	struct in6_addr ip6;
89 	u_short         if_index;
90 
91 	u_int           test_count;
92 	u_int           test_address_count;
93 	uint64_t        test_address_present;
94 } switch_port, *switch_port_t;
95 
96 typedef struct {
97 	u_int           size;
98 	u_int           count;
99 	bool            mac_nat;
100 	switch_port     list[1];
101 } switch_port_list, * switch_port_list_t;
102 
103 static struct in_addr   bridge_ip_addr;
104 static struct in6_addr  bridge_ipv6_addr;
105 static u_short          bridge_if_index;
106 
107 static struct ifbareq *
108 bridge_rt_table_copy(u_int * ret_count);
109 
110 static void
111 bridge_rt_table_log(struct ifbareq *rt_table, u_int count);
112 
113 static struct ifbrmne *
114 bridge_mac_nat_entries_copy(u_int * ret_count);
115 
116 static void
117 bridge_mac_nat_entries_log(struct ifbrmne * entries, u_int count);
118 
119 #define SETUP_FLAGS_MAC_NAT             0x01
120 #define SETUP_FLAGS_CHECKSUM_OFFLOAD    0x02
121 #define SETUP_FLAGS_ATTACH_STACK        0x04
122 #define SETUP_FLAGS_TRAILERS            0x08
123 #define SETUP_FLAGS_SHARE_MEMBER_MAC    0x10
124 
125 #define s6_addr16 __u6_addr.__u6_addr16
126 
127 /**
128 ** Packet creation/display
129 **/
130 #define BOOTP_SERVER_PORT       67
131 #define BOOTP_CLIENT_PORT       68
132 
133 #define TEST_SOURCE_PORT        14
134 #define TEST_DEST_PORT          15
135 
136 #define EA_UNIT_INDEX           4
137 #define EA_ADDR_INDEX           5
138 
139 static void
set_ethernet_address(ether_addr_t * eaddr,u_int unit,u_int addr_index)140 set_ethernet_address(ether_addr_t *eaddr, u_int unit, u_int addr_index)
141 {
142 	u_char  *a = eaddr->octet;
143 
144 	a[0] = 0x02;
145 	a[2] = 0x00;
146 	a[3] = 0x00;
147 	a[1] = 0x00;
148 	a[EA_UNIT_INDEX] = (u_char)unit;
149 	a[EA_ADDR_INDEX] = (u_char)addr_index;
150 }
151 
152 #define TEN_NET                 0x0a000000
153 #define TEN_1_NET               (TEN_NET | 0x010000)
154 
155 static void
get_ipv4_address(u_int unit,u_int addr_index,struct in_addr * ip)156 get_ipv4_address(u_int unit, u_int addr_index, struct in_addr *ip)
157 {
158 	/* up to 255 units, 255 addresses */
159 	ip->s_addr = htonl(TEN_1_NET | (unit << 8) | addr_index);
160 	return;
161 }
162 
163 #define IN6ADDR_ULA_INIT \
164 	{{{ 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
165 	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
166 
167 static struct in6_addr ula_address = IN6ADDR_ULA_INIT;
168 
169 #define ULA_UNIT_INDEX  14
170 #define ULA_ADDR_INDEX  15
171 
172 static void
get_ipv6_ula_address(u_int unit,u_int addr_index,struct in6_addr * ip)173 get_ipv6_ula_address(u_int unit, u_int addr_index, struct in6_addr *ip)
174 {
175 	*ip = ula_address;
176 	/* up to 255 units, 255 addresses */
177 	ip->s6_addr[ULA_UNIT_INDEX] = (uint8_t)unit;
178 	ip->s6_addr[ULA_ADDR_INDEX] = (uint8_t)addr_index;
179 }
180 
181 #define ND6_EUI64_GBIT  0x01
182 #define ND6_EUI64_UBIT  0x02
183 
184 #define ND6_EUI64_TO_IFID(in6) \
185 	do {(in6)->s6_addr[8] ^= ND6_EUI64_UBIT; } while (0)
186 static void
get_ipv6_ll_address(const ether_addr_t * mac,struct in6_addr * in6)187 get_ipv6_ll_address(const ether_addr_t *mac, struct in6_addr * in6)
188 {
189 	const u_char *  addr = mac->octet;
190 
191 	bzero(in6, sizeof(*in6));
192 	in6->s6_addr16[0] = htons(0xfe80);
193 	in6->s6_addr[8] = addr[0];
194 	in6->s6_addr[9] = addr[1];
195 	in6->s6_addr[10] = addr[2];
196 	in6->s6_addr[11] = 0xff;
197 	in6->s6_addr[12] = 0xfe;
198 	in6->s6_addr[13] = addr[3];
199 	in6->s6_addr[14] = addr[4];
200 	in6->s6_addr[15] = addr[5];
201 	ND6_EUI64_TO_IFID(in6);
202 	return;
203 }
204 
205 static void
get_ip_address(uint8_t af,u_int unit,u_int addr_index,union ifbrip * ip)206 get_ip_address(uint8_t af, u_int unit, u_int addr_index, union ifbrip *ip)
207 {
208 	switch (af) {
209 	case AF_INET:
210 		get_ipv4_address(unit, addr_index, &ip->ifbrip_addr);
211 		break;
212 	case AF_INET6:
213 		get_ipv6_ula_address(unit, addr_index, &ip->ifbrip_addr6);
214 		break;
215 	default:
216 		T_FAIL("unrecognized address family %u", af);
217 		break;
218 	}
219 }
220 
221 static bool
ip_addresses_are_equal(uint8_t af,union ifbrip * ip1,union ifbrip * ip2)222 ip_addresses_are_equal(uint8_t af, union ifbrip * ip1, union ifbrip * ip2)
223 {
224 	bool    equal;
225 
226 	switch (af) {
227 	case AF_INET:
228 		equal = (ip1->ifbrip_addr.s_addr == ip2->ifbrip_addr.s_addr);
229 		break;
230 	case AF_INET6:
231 		equal = IN6_ARE_ADDR_EQUAL(&ip1->ifbrip_addr6,
232 		    &ip2->ifbrip_addr6);
233 		break;
234 	default:
235 		T_FAIL("unrecognized address family %u", af);
236 		equal = false;
237 		break;
238 	}
239 	return equal;
240 }
241 
242 static ether_addr_t ether_external = {
243 	{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 }
244 };
245 
246 static inline struct in_addr
get_external_ipv4_address(void)247 get_external_ipv4_address(void)
248 {
249 	struct in_addr  ip;
250 
251 	/* IP 10.1.255.1 */
252 	ip.s_addr = htonl(TEN_1_NET | 0xff01);
253 	return ip;
254 }
255 
256 static inline void
get_external_ip_address(uint8_t af,union ifbrip * ip)257 get_external_ip_address(uint8_t af, union ifbrip * ip)
258 {
259 	switch (af) {
260 	case AF_INET:
261 		/* IP 10.1.255.1 */
262 		ip->ifbrip_addr = get_external_ipv4_address();
263 		break;
264 	case AF_INET6:
265 		/* fd80::1 */
266 		ip->ifbrip_addr6 = ula_address;
267 		ip->ifbrip_addr6.s6_addr[1] = 0x80;
268 		ip->ifbrip_addr6.s6_addr[15] = 0x01;
269 		break;
270 	default:
271 		T_FAIL("unrecognized address family %u", af);
272 		break;
273 	}
274 }
275 
276 static inline void
get_broadcast_ip_address(uint8_t af,union ifbrip * ip)277 get_broadcast_ip_address(uint8_t af, union ifbrip * ip)
278 {
279 	switch (af) {
280 	case AF_INET:
281 		ip->ifbrip_addr.s_addr = INADDR_BROADCAST;
282 		break;
283 	case AF_INET6:
284 		/* 0xff0e::0 linklocal scope multicast */
285 		ip->ifbrip_addr6 = in6addr_any;
286 		ip->ifbrip_addr6.s6_addr[0] = 0xff;
287 		ip->ifbrip_addr6.s6_addr[1] = __IPV6_ADDR_SCOPE_LINKLOCAL;
288 		break;
289 	default:
290 		T_FAIL("unrecognized address family %u", af);
291 		break;
292 	}
293 }
294 
295 #define ETHER_NTOA_BUFSIZE      (ETHER_ADDR_LEN * 3)
296 static const char *
ether_ntoa_buf(const ether_addr_t * n,char * buf,int buf_size)297 ether_ntoa_buf(const ether_addr_t *n, char * buf, int buf_size)
298 {
299 	char *  str;
300 
301 	str = ether_ntoa(n);
302 	strlcpy(buf, str, buf_size);
303 	return buf;
304 }
305 
306 static const char *
inet_ptrtop(int af,const void * ptr,char * buf,socklen_t buf_size)307 inet_ptrtop(int af, const void * ptr, char * buf, socklen_t buf_size)
308 {
309 	union {
310 		struct in_addr  ip;
311 		struct in6_addr ip6;
312 	} u;
313 
314 	switch (af) {
315 	case AF_INET:
316 		bcopy(ptr, &u.ip, sizeof(u.ip));
317 		break;
318 	case AF_INET6:
319 		bcopy(ptr, &u.ip6, sizeof(u.ip6));
320 		break;
321 	default:
322 		return NULL;
323 	}
324 	return inet_ntop(af, &u, buf, buf_size);
325 }
326 
327 static __inline__ char *
arpop_name(u_int16_t op)328 arpop_name(u_int16_t op)
329 {
330 	switch (op) {
331 	case ARPOP_REQUEST:
332 		return "ARP REQUEST";
333 	case ARPOP_REPLY:
334 		return "ARP REPLY";
335 	case ARPOP_REVREQUEST:
336 		return "REVARP REQUEST";
337 	case ARPOP_REVREPLY:
338 		return "REVARP REPLY";
339 	default:
340 		break;
341 	}
342 	return "<unknown>";
343 }
344 
345 static void
arp_frame_validate(const struct ether_arp * earp,u_int len,bool dump)346 arp_frame_validate(const struct ether_arp * earp, u_int len, bool dump)
347 {
348 	const struct arphdr *   arp_p;
349 	int                     arphrd;
350 	char                    buf_sender_ether[ETHER_NTOA_BUFSIZE];
351 	char                    buf_sender_ip[INET_ADDRSTRLEN];
352 	char                    buf_target_ether[ETHER_NTOA_BUFSIZE];
353 	char                    buf_target_ip[INET_ADDRSTRLEN];
354 
355 	T_QUIET;
356 	T_ASSERT_GE(len, (u_int)sizeof(*earp),
357 	    "%s ARP packet size %u need %u",
358 	    __func__, len, (u_int)sizeof(*earp));
359 	if (!dump) {
360 		return;
361 	}
362 	arp_p = &earp->ea_hdr;
363 	arphrd = ntohs(arp_p->ar_hrd);
364 	T_LOG("%s type=0x%x proto=0x%x", arpop_name(ntohs(arp_p->ar_op)),
365 	    arphrd, ntohs(arp_p->ar_pro));
366 	if (arp_p->ar_hln == sizeof(earp->arp_sha)) {
367 		ether_ntoa_buf((const ether_addr_t *)earp->arp_sha,
368 		    buf_sender_ether,
369 		    sizeof(buf_sender_ether));
370 		ether_ntoa_buf((const ether_addr_t *)earp->arp_tha,
371 		    buf_target_ether,
372 		    sizeof(buf_target_ether));
373 		T_LOG("Sender H/W\t%s", buf_sender_ether);
374 		T_LOG("Target H/W\t%s", buf_target_ether);
375 	}
376 	inet_ptrtop(AF_INET, earp->arp_spa,
377 	    buf_sender_ip, sizeof(buf_sender_ip));
378 	inet_ptrtop(AF_INET, earp->arp_tpa,
379 	    buf_target_ip, sizeof(buf_target_ip));
380 	T_LOG("Sender IP\t%s", buf_sender_ip);
381 	T_LOG("Target IP\t%s", buf_target_ip);
382 	return;
383 }
384 
385 static void
ip_frame_validate(const void * buf,u_int buf_len,bool dump)386 ip_frame_validate(const void * buf, u_int buf_len, bool dump)
387 {
388 	char                    buf_dst[INET_ADDRSTRLEN];
389 	char                    buf_src[INET_ADDRSTRLEN];
390 	const ip_udp_header_t * ip_udp;
391 	u_int                   ip_len;
392 
393 	T_QUIET;
394 	T_ASSERT_GE(buf_len, (u_int)sizeof(struct ip), NULL);
395 	ip_udp = (const ip_udp_header_t *)buf;
396 	ip_len = ntohs(ip_udp->ip.ip_len);
397 	inet_ptrtop(AF_INET, &ip_udp->ip.ip_src,
398 	    buf_src, sizeof(buf_src));
399 	inet_ptrtop(AF_INET, &ip_udp->ip.ip_dst,
400 	    buf_dst, sizeof(buf_dst));
401 	if (dump) {
402 		T_LOG("ip src %s dst %s len %u id %d",
403 		    buf_src, buf_dst, ip_len,
404 		    ntohs(ip_udp->ip.ip_id));
405 	}
406 	T_QUIET;
407 	T_ASSERT_GE(buf_len, ip_len, NULL);
408 	T_QUIET;
409 	T_ASSERT_EQ((u_int)ip_udp->ip.ip_v, IPVERSION, NULL);
410 	T_QUIET;
411 	T_ASSERT_EQ((u_int)(ip_udp->ip.ip_hl << 2),
412 	    (u_int)sizeof(struct ip), NULL);
413 	if (ip_udp->ip.ip_p == IPPROTO_UDP) {
414 		u_int   udp_len;
415 		u_int   data_len;
416 
417 		T_QUIET;
418 		T_ASSERT_GE(buf_len, (u_int)sizeof(*ip_udp), NULL);
419 		udp_len = ntohs(ip_udp->udp.uh_ulen);
420 		T_QUIET;
421 		T_ASSERT_GE(udp_len, (u_int)sizeof(ip_udp->udp), NULL);
422 		data_len = udp_len - (u_int)sizeof(ip_udp->udp);
423 		if (dump) {
424 			T_LOG("udp src 0x%x dst 0x%x len %u"
425 			    " csum 0x%x datalen %u",
426 			    ntohs(ip_udp->udp.uh_sport),
427 			    ntohs(ip_udp->udp.uh_dport),
428 			    udp_len,
429 			    ntohs(ip_udp->udp.uh_sum),
430 			    data_len);
431 		}
432 	}
433 }
434 
435 static void
ip6_frame_validate(const void * buf,u_int buf_len,bool dump)436 ip6_frame_validate(const void * buf, u_int buf_len, bool dump)
437 {
438 	char                    buf_dst[INET6_ADDRSTRLEN];
439 	char                    buf_src[INET6_ADDRSTRLEN];
440 	const struct ip6_hdr *  ip6;
441 	u_int                   ip6_len;
442 
443 	T_QUIET;
444 	T_ASSERT_GE(buf_len, (u_int)sizeof(struct ip6_hdr), NULL);
445 	ip6 = (const struct ip6_hdr *)buf;
446 	ip6_len = ntohs(ip6->ip6_plen);
447 	inet_ptrtop(AF_INET6, &ip6->ip6_src, buf_src, sizeof(buf_src));
448 	inet_ptrtop(AF_INET6, &ip6->ip6_dst, buf_dst, sizeof(buf_dst));
449 	if (dump) {
450 		T_LOG("ip6 src %s dst %s len %u", buf_src, buf_dst, ip6_len);
451 	}
452 	T_QUIET;
453 	T_ASSERT_GE(buf_len, ip6_len + (u_int)sizeof(struct ip6_hdr), NULL);
454 	T_QUIET;
455 	T_ASSERT_EQ((ip6->ip6_vfc & IPV6_VERSION_MASK),
456 	    IPV6_VERSION, NULL);
457 	T_QUIET;
458 	switch (ip6->ip6_nxt) {
459 	case IPPROTO_UDP: {
460 		u_int                   data_len;
461 		const ip6_udp_header_t *ip6_udp;
462 		u_int                   udp_len;
463 
464 		ip6_udp = (const ip6_udp_header_t *)buf;
465 		T_QUIET;
466 		T_ASSERT_GE(buf_len, (u_int)sizeof(*ip6_udp), NULL);
467 		udp_len = ntohs(ip6_udp->udp.uh_ulen);
468 		T_QUIET;
469 		T_ASSERT_GE(udp_len, (u_int)sizeof(ip6_udp->udp), NULL);
470 		data_len = udp_len - (u_int)sizeof(ip6_udp->udp);
471 		if (dump) {
472 			T_LOG("udp src 0x%x dst 0x%x len %u"
473 			    " csum 0x%x datalen %u",
474 			    ntohs(ip6_udp->udp.uh_sport),
475 			    ntohs(ip6_udp->udp.uh_dport),
476 			    udp_len,
477 			    ntohs(ip6_udp->udp.uh_sum),
478 			    data_len);
479 		}
480 		break;
481 	}
482 	case IPPROTO_ICMPV6: {
483 		const struct icmp6_hdr *icmp6;
484 		u_int                   icmp6_len;
485 
486 		icmp6_len = buf_len - sizeof(*ip6);
487 		T_QUIET;
488 		T_ASSERT_GE(buf_len, icmp6_len, NULL);
489 		icmp6 = (const struct icmp6_hdr *)(ip6 + 1);
490 		switch (icmp6->icmp6_type) {
491 		case ND_NEIGHBOR_SOLICIT:
492 			if (dump) {
493 				T_LOG("neighbor solicit");
494 			}
495 			break;
496 		case ND_NEIGHBOR_ADVERT:
497 			if (dump) {
498 				T_LOG("neighbor advert");
499 			}
500 			break;
501 		case ND_ROUTER_SOLICIT:
502 			if (dump) {
503 				T_LOG("router solicit");
504 			}
505 			break;
506 		default:
507 			if (dump) {
508 				T_LOG("icmp6 code 0x%x", icmp6->icmp6_type);
509 			}
510 			break;
511 		}
512 		break;
513 	}
514 	default:
515 		break;
516 	}
517 }
518 
519 static void
ethernet_frame_validate(const void * buf,u_int buf_len,bool dump)520 ethernet_frame_validate(const void * buf, u_int buf_len, bool dump)
521 {
522 	char                    ether_dst[ETHER_NTOA_BUFSIZE];
523 	char                    ether_src[ETHER_NTOA_BUFSIZE];
524 	uint16_t                ether_type;
525 	const ether_header_t *  eh_p;
526 
527 	T_QUIET;
528 	T_ASSERT_GE(buf_len, (u_int)sizeof(*eh_p), NULL);
529 	eh_p = (const ether_header_t *)buf;
530 	ether_type = ntohs(eh_p->ether_type);
531 	ether_ntoa_buf((const ether_addr_t *)&eh_p->ether_dhost,
532 	    ether_dst, sizeof(ether_dst));
533 	ether_ntoa_buf((const ether_addr_t *)&eh_p->ether_shost,
534 	    ether_src, sizeof(ether_src));
535 	if (dump) {
536 		T_LOG("ether dst %s src %s type 0x%x",
537 		    ether_dst, ether_src, ether_type);
538 	}
539 	switch (ether_type) {
540 	case ETHERTYPE_IP:
541 		ip_frame_validate(eh_p + 1, (u_int)(buf_len - sizeof(*eh_p)),
542 		    dump);
543 		break;
544 	case ETHERTYPE_ARP:
545 		arp_frame_validate((const struct ether_arp *)(eh_p + 1),
546 		    (u_int)(buf_len - sizeof(*eh_p)),
547 		    dump);
548 		break;
549 	case ETHERTYPE_IPV6:
550 		ip6_frame_validate(eh_p + 1, (u_int)(buf_len - sizeof(*eh_p)),
551 		    dump);
552 		break;
553 	default:
554 		T_FAIL("unrecognized ethertype 0x%x", ether_type);
555 		break;
556 	}
557 }
558 
559 static u_int
ethernet_udp_frame_populate(void * buf,size_t buf_len,uint8_t af,const ether_addr_t * src,union ifbrip * src_ip,uint16_t src_port,const ether_addr_t * dst,union ifbrip * dst_ip,uint16_t dst_port,const void * data,u_int data_len)560 ethernet_udp_frame_populate(void * buf, size_t buf_len,
561     uint8_t af,
562     const ether_addr_t * src,
563     union ifbrip * src_ip,
564     uint16_t src_port,
565     const ether_addr_t * dst,
566     union ifbrip * dst_ip,
567     uint16_t dst_port,
568     const void * data, u_int data_len)
569 {
570 	u_int   len;
571 
572 	switch (af) {
573 	case AF_INET:
574 		len = ethernet_udp4_frame_populate(buf, buf_len,
575 		    src,
576 		    src_ip->ifbrip_addr,
577 		    src_port,
578 		    dst,
579 		    dst_ip->ifbrip_addr,
580 		    dst_port,
581 		    data, data_len);
582 		break;
583 	case AF_INET6:
584 		len = ethernet_udp6_frame_populate(buf, buf_len,
585 		    src,
586 		    &src_ip->ifbrip_addr6,
587 		    src_port,
588 		    dst,
589 		    &dst_ip->ifbrip_addr6,
590 		    dst_port,
591 		    data, data_len);
592 		break;
593 	default:
594 		T_FAIL("unrecognized address family %u", af);
595 		len = 0;
596 		break;
597 	}
598 	return len;
599 }
600 
601 static u_int
ethernet_arp_frame_populate(void * buf,u_int buf_len,uint16_t op,const ether_addr_t * sender_hw,struct in_addr sender_ip,const ether_addr_t * target_hw,struct in_addr target_ip)602 ethernet_arp_frame_populate(void * buf, u_int buf_len,
603     uint16_t op,
604     const ether_addr_t * sender_hw,
605     struct in_addr sender_ip,
606     const ether_addr_t * target_hw,
607     struct in_addr target_ip)
608 {
609 	ether_header_t *        eh_p;
610 	struct ether_arp *      earp;
611 	struct arphdr *         arp_p;
612 	u_int                   frame_length;
613 
614 	frame_length = sizeof(*earp) + sizeof(*eh_p);
615 	T_QUIET;
616 	T_ASSERT_GE(buf_len, frame_length,
617 	    "%s buffer size %u needed %u",
618 	    __func__, buf_len, frame_length);
619 
620 	/* ethernet_header */
621 	eh_p = (ether_header_t *)buf;
622 	bcopy(sender_hw, eh_p->ether_shost, ETHER_ADDR_LEN);
623 	if (target_hw != NULL) {
624 		bcopy(target_hw, eh_p->ether_dhost,
625 		    sizeof(eh_p->ether_dhost));
626 	} else {
627 		bcopy(&ether_broadcast, eh_p->ether_dhost,
628 		    sizeof(eh_p->ether_dhost));
629 	}
630 	eh_p->ether_type = htons(ETHERTYPE_ARP);
631 
632 	/* ARP payload */
633 	earp = (struct ether_arp *)(void *)(eh_p + 1);
634 	arp_p = &earp->ea_hdr;
635 	arp_p->ar_hrd = htons(ARPHRD_ETHER);
636 	arp_p->ar_pro = htons(ETHERTYPE_IP);
637 	arp_p->ar_hln = sizeof(earp->arp_sha);
638 	arp_p->ar_pln = sizeof(struct in_addr);
639 	arp_p->ar_op = htons(op);
640 	bcopy(sender_hw, earp->arp_sha, sizeof(earp->arp_sha));
641 	bcopy(&sender_ip, earp->arp_spa, sizeof(earp->arp_spa));
642 	if (target_hw != NULL) {
643 		bcopy(target_hw, earp->arp_tha, sizeof(earp->arp_tha));
644 	} else {
645 		bzero(earp->arp_tha, sizeof(earp->arp_tha));
646 	}
647 	bcopy(&target_ip, earp->arp_tpa, sizeof(earp->arp_tpa));
648 	return frame_length;
649 }
650 
651 static uint32_t G_generation;
652 
653 static uint32_t
next_generation(void)654 next_generation(void)
655 {
656 	return G_generation++;
657 }
658 
659 static const void *
ethernet_frame_get_udp4_payload(void * buf,u_int buf_len,u_int * ret_payload_length)660 ethernet_frame_get_udp4_payload(void * buf, u_int buf_len,
661     u_int * ret_payload_length)
662 {
663 	ether_header_t *        eh_p;
664 	uint16_t                ether_type;
665 	ip_udp_header_t *       ip_udp;
666 	u_int                   ip_len;
667 	u_int                   left;
668 	const void *            payload = NULL;
669 	u_int                   payload_length = 0;
670 	u_int                   udp_len;
671 
672 	T_QUIET;
673 	T_ASSERT_GE(buf_len, (u_int)(sizeof(*eh_p) + sizeof(*ip_udp)), NULL);
674 	left = buf_len;
675 	eh_p = (ether_header_t *)buf;
676 	ether_type = ntohs(eh_p->ether_type);
677 	T_QUIET;
678 	T_ASSERT_EQ((int)ether_type, ETHERTYPE_IP, NULL);
679 	ip_udp = (ip_udp_header_t *)(void *)(eh_p + 1);
680 	left -= sizeof(*eh_p);
681 	ip_len = ntohs(ip_udp->ip.ip_len);
682 	T_QUIET;
683 	T_ASSERT_GE(left, ip_len, NULL);
684 	T_QUIET;
685 	T_ASSERT_EQ((int)ip_udp->ip.ip_v, IPVERSION, NULL);
686 	T_QUIET;
687 	T_ASSERT_EQ((u_int)ip_udp->ip.ip_hl << 2, (u_int)sizeof(struct ip),
688 	        NULL);
689 	T_QUIET;
690 	T_ASSERT_EQ((int)ip_udp->ip.ip_p, IPPROTO_UDP, NULL);
691 	T_QUIET;
692 	T_ASSERT_GE(buf_len, (u_int)sizeof(*ip_udp), NULL);
693 	udp_len = ntohs(ip_udp->udp.uh_ulen);
694 	T_QUIET;
695 	T_ASSERT_GE(udp_len, (u_int)sizeof(ip_udp->udp), NULL);
696 	payload_length = udp_len - (int)sizeof(ip_udp->udp);
697 	if (payload_length > 0) {
698 		payload = (ip_udp + 1);
699 	}
700 	if (payload == NULL) {
701 		payload_length = 0;
702 	}
703 	*ret_payload_length = payload_length;
704 	return payload;
705 }
706 
707 static const void *
ethernet_frame_get_udp6_payload(void * buf,u_int buf_len,u_int * ret_payload_length)708 ethernet_frame_get_udp6_payload(void * buf, u_int buf_len,
709     u_int * ret_payload_length)
710 {
711 	ether_header_t *        eh_p;
712 	uint16_t                ether_type;
713 	ip6_udp_header_t *      ip6_udp;
714 	u_int                   ip6_len;
715 	u_int                   left;
716 	const void *            payload = NULL;
717 	u_int                   payload_length = 0;
718 	u_int                   udp_len;
719 
720 	T_QUIET;
721 	T_ASSERT_GE(buf_len, (u_int)(sizeof(*eh_p) + sizeof(*ip6_udp)), NULL);
722 	left = buf_len;
723 	eh_p = (ether_header_t *)buf;
724 	ether_type = ntohs(eh_p->ether_type);
725 	T_QUIET;
726 	T_ASSERT_EQ((int)ether_type, ETHERTYPE_IPV6, NULL);
727 	ip6_udp = (ip6_udp_header_t *)(void *)(eh_p + 1);
728 	left -= sizeof(*eh_p);
729 	ip6_len = ntohs(ip6_udp->ip6.ip6_plen);
730 	T_QUIET;
731 	T_ASSERT_GE(left, ip6_len + (u_int)sizeof(struct ip6_hdr), NULL);
732 	T_QUIET;
733 	T_ASSERT_EQ((int)(ip6_udp->ip6.ip6_vfc & IPV6_VERSION_MASK),
734 	    IPV6_VERSION, NULL);
735 	T_QUIET;
736 	T_ASSERT_EQ((int)ip6_udp->ip6.ip6_nxt, IPPROTO_UDP, NULL);
737 	T_QUIET;
738 	T_ASSERT_GE(buf_len, (u_int)sizeof(*ip6_udp), NULL);
739 	udp_len = ntohs(ip6_udp->udp.uh_ulen);
740 	T_QUIET;
741 	T_ASSERT_GE(udp_len, (u_int)sizeof(ip6_udp->udp), NULL);
742 	payload_length = udp_len - (int)sizeof(ip6_udp->udp);
743 	if (payload_length > 0) {
744 		payload = (ip6_udp + 1);
745 	}
746 	if (payload == NULL) {
747 		payload_length = 0;
748 	}
749 	*ret_payload_length = payload_length;
750 	return payload;
751 }
752 
753 static const void *
ethernet_frame_get_udp_payload(uint8_t af,void * buf,u_int buf_len,u_int * ret_payload_length)754 ethernet_frame_get_udp_payload(uint8_t af, void * buf, u_int buf_len,
755     u_int * ret_payload_length)
756 {
757 	const void *    payload;
758 
759 	switch (af) {
760 	case AF_INET:
761 		payload = ethernet_frame_get_udp4_payload(buf, buf_len,
762 		    ret_payload_length);
763 		break;
764 	case AF_INET6:
765 		payload = ethernet_frame_get_udp6_payload(buf, buf_len,
766 		    ret_payload_length);
767 		break;
768 	default:
769 		T_FAIL("unrecognized address family %u", af);
770 		payload = NULL;
771 		break;
772 	}
773 	return payload;
774 }
775 
776 #define MIN_ICMP6_LEN           ((u_int)(sizeof(ether_header_t) +       \
777 	                                 sizeof(struct ip6_hdr) +       \
778 	                                 sizeof(struct icmp6_hdr)))
779 #define ALIGNED_ND_OPT_LEN      8
780 #define SET_ND_OPT_LEN(a)       (u_int)((a) >> 3)
781 #define GET_ND_OPT_LEN(a)       (u_int)((a) << 3)
782 #define ALIGN_ND_OPT(a)         (u_int)roundup(a, ALIGNED_ND_OPT_LEN)
783 #define LINKADDR_OPT_LEN        (ALIGN_ND_OPT(sizeof(struct nd_opt_hdr) + \
784 	                                      sizeof(ether_addr_t)))
785 #define ETHER_IPV6_LEN  (sizeof(*eh_p) + sizeof(*ip6))
786 
787 
788 
789 static u_int
ethernet_nd6_frame_populate(void * buf,u_int buf_len,uint8_t type,const ether_addr_t * sender_hw,struct in6_addr * sender_ip,const ether_addr_t * dest_ether,const ether_addr_t * target_hw,struct in6_addr * target_ip)790 ethernet_nd6_frame_populate(void * buf, u_int buf_len,
791     uint8_t type,
792     const ether_addr_t * sender_hw,
793     struct in6_addr * sender_ip,
794     const ether_addr_t * dest_ether,
795     const ether_addr_t * target_hw,
796     struct in6_addr * target_ip)
797 {
798 	u_int                           data_len = 0;
799 	ether_header_t *                eh_p;
800 	u_int                           frame_length;
801 	struct icmp6_hdr *              icmp6;
802 	struct ip6_hdr *                ip6;
803 	struct nd_opt_hdr *             nd_opt;
804 
805 	switch (type) {
806 	case ND_ROUTER_SOLICIT:
807 	case ND_NEIGHBOR_ADVERT:
808 	case ND_NEIGHBOR_SOLICIT:
809 		break;
810 	default:
811 		T_FAIL("%s: unsupported type %u", __func__, type);
812 		return 0;
813 	}
814 
815 	T_QUIET;
816 	T_ASSERT_GE(buf_len, MIN_ICMP6_LEN, NULL);
817 
818 	eh_p = (ether_header_t *)buf;
819 	ip6 = (struct ip6_hdr *)(void *)(eh_p + 1);
820 	icmp6 = (struct icmp6_hdr *)(void *)(ip6 + 1);
821 	frame_length = sizeof(*eh_p) + sizeof(*ip6);
822 	switch (type) {
823 	case ND_NEIGHBOR_SOLICIT: {
824 		struct nd_neighbor_solicit *    nd_ns;
825 		bool                            sender_is_specified;
826 
827 		sender_is_specified = !IN6_IS_ADDR_UNSPECIFIED(sender_ip);
828 		data_len = sizeof(*nd_ns);
829 		if (sender_is_specified) {
830 			data_len += LINKADDR_OPT_LEN;
831 		}
832 		frame_length += data_len;
833 		T_QUIET;
834 		T_ASSERT_GE(buf_len, frame_length, NULL);
835 		nd_ns = (struct nd_neighbor_solicit *)(void *)icmp6;
836 		if (sender_is_specified) {
837 			/* add the source lladdr option */
838 			nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
839 			nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
840 			nd_opt->nd_opt_len = SET_ND_OPT_LEN(LINKADDR_OPT_LEN);
841 			bcopy(sender_hw, (nd_opt + 1), sizeof(*sender_hw));
842 		}
843 		bcopy(target_ip, &nd_ns->nd_ns_target,
844 		    sizeof(nd_ns->nd_ns_target));
845 		break;
846 	}
847 	case ND_NEIGHBOR_ADVERT: {
848 		struct nd_neighbor_advert *     nd_na;
849 
850 		data_len = sizeof(*nd_na) + LINKADDR_OPT_LEN;
851 		frame_length += data_len;
852 		T_QUIET;
853 		T_ASSERT_GE(buf_len, frame_length, NULL);
854 
855 		nd_na = (struct nd_neighbor_advert *)(void *)icmp6;
856 		bcopy(target_ip, &nd_na->nd_na_target,
857 		    sizeof(nd_na->nd_na_target));
858 		/* add the target lladdr option */
859 		nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
860 		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
861 		nd_opt->nd_opt_len = SET_ND_OPT_LEN(LINKADDR_OPT_LEN);
862 		bcopy(target_hw, (nd_opt + 1), sizeof(*target_hw));
863 		break;
864 	}
865 	case ND_ROUTER_SOLICIT: {
866 		struct nd_router_solicit *      nd_rs;
867 
868 		data_len = sizeof(*nd_rs) + LINKADDR_OPT_LEN;
869 		frame_length += data_len;
870 		T_QUIET;
871 		T_ASSERT_GE(buf_len, frame_length, NULL);
872 
873 		nd_rs = (struct nd_router_solicit *)(void *)icmp6;
874 
875 		/* add the source lladdr option */
876 		nd_opt = (struct nd_opt_hdr *)(nd_rs + 1);
877 		nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
878 		nd_opt->nd_opt_len = SET_ND_OPT_LEN(LINKADDR_OPT_LEN);
879 		bcopy(sender_hw, (nd_opt + 1), sizeof(*sender_hw));
880 		break;
881 	}
882 	default:
883 		T_FAIL("%s: unsupported type %u", __func__, type);
884 		return 0;
885 	}
886 	/* icmp6 header */
887 	icmp6->icmp6_type = type;
888 	icmp6->icmp6_code = 0;
889 	icmp6->icmp6_cksum = 0;
890 	icmp6->icmp6_data32[0] = 0;
891 
892 	/* ethernet_header */
893 	bcopy(sender_hw, eh_p->ether_shost, ETHER_ADDR_LEN);
894 	if (dest_ether != NULL) {
895 		bcopy(dest_ether, eh_p->ether_dhost,
896 		    sizeof(eh_p->ether_dhost));
897 	} else {
898 		/* XXX ether_dhost should be multicast */
899 		bcopy(&ether_broadcast, eh_p->ether_dhost,
900 		    sizeof(eh_p->ether_dhost));
901 	}
902 	eh_p->ether_type = htons(ETHERTYPE_IPV6);
903 
904 	/* IPv6 header */
905 	bzero(ip6, sizeof(*ip6));
906 	ip6->ip6_nxt = IPPROTO_ICMPV6;
907 	ip6->ip6_vfc = IPV6_VERSION;
908 	bcopy(sender_ip, &ip6->ip6_src, sizeof(ip6->ip6_src));
909 	/* XXX ip6_dst should be specific multicast */
910 	bcopy(&in6addr_linklocal_allnodes, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
911 	ip6->ip6_plen = htons(data_len);
912 
913 	return frame_length;
914 }
915 
916 /**
917 ** Switch port
918 **/
919 static void
switch_port_check_tx(switch_port_t port)920 switch_port_check_tx(switch_port_t port)
921 {
922 	int             error;
923 	struct kevent   kev;
924 	int             kq;
925 	struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000 * 1000};
926 
927 	kq = kqueue();
928 	T_QUIET;
929 	T_ASSERT_POSIX_SUCCESS(kq, "kqueue check_tx");
930 	EV_SET(&kev, port->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
931 	error = kevent(kq, &kev, 1, &kev, 1, &ts);
932 	T_QUIET;
933 	T_ASSERT_EQ(error, 1, "kevent");
934 	T_QUIET;
935 	T_ASSERT_EQ((int)kev.filter, EVFILT_WRITE, NULL);
936 	T_QUIET;
937 	T_ASSERT_EQ((int)kev.ident, port->fd, NULL);
938 	T_QUIET;
939 	T_ASSERT_NULL(kev.udata, NULL);
940 	close(kq);
941 	return;
942 }
943 
944 static void
switch_port_send_arp(switch_port_t port,uint16_t op,const ether_addr_t * sender_hw,struct in_addr sender_ip,const ether_addr_t * target_hw,struct in_addr target_ip)945 switch_port_send_arp(switch_port_t port,
946     uint16_t op,
947     const ether_addr_t * sender_hw,
948     struct in_addr sender_ip,
949     const ether_addr_t * target_hw,
950     struct in_addr target_ip)
951 {
952 	u_int           frame_length;
953 	ether_packet    pkt;
954 	ssize_t         n;
955 
956 	/* make sure we can send */
957 	switch_port_check_tx(port);
958 	frame_length = ethernet_arp_frame_populate(&pkt, sizeof(pkt),
959 	    op,
960 	    sender_hw,
961 	    sender_ip,
962 	    target_hw,
963 	    target_ip);
964 	T_QUIET;
965 	T_ASSERT_GT(frame_length, 0, "%s: frame_length %u",
966 	    __func__, frame_length);
967 	if (G_debug) {
968 		T_LOG("Port %s -> %s transmitting %u bytes",
969 		    port->ifname, port->member_ifname, frame_length);
970 	}
971 	ethernet_frame_validate(&pkt, frame_length, G_debug);
972 	n = write(port->fd, &pkt, frame_length);
973 	if (n < 0) {
974 		T_ASSERT_POSIX_SUCCESS(n, "%s write fd %d failed %ld",
975 		    port->ifname, port->fd, n);
976 	}
977 	T_QUIET;
978 	T_ASSERT_EQ((u_int)n, frame_length,
979 	    "%s fd %d wrote %ld",
980 	    port->ifname, port->fd, n);
981 }
982 
983 
984 static void
switch_port_send_nd6(switch_port_t port,uint8_t type,const ether_addr_t * sender_hw,struct in6_addr * sender_ip,const ether_addr_t * dest_ether,const ether_addr_t * target_hw,struct in6_addr * target_ip)985 switch_port_send_nd6(switch_port_t port,
986     uint8_t type,
987     const ether_addr_t * sender_hw,
988     struct in6_addr * sender_ip,
989     const ether_addr_t * dest_ether,
990     const ether_addr_t * target_hw,
991     struct in6_addr * target_ip)
992 {
993 	u_int           frame_length;
994 	ether_packet    pkt;
995 	ssize_t         n;
996 
997 	/* make sure we can send */
998 	switch_port_check_tx(port);
999 	frame_length = ethernet_nd6_frame_populate(&pkt, sizeof(pkt),
1000 	    type,
1001 	    sender_hw,
1002 	    sender_ip,
1003 	    dest_ether,
1004 	    target_hw,
1005 	    target_ip);
1006 	T_QUIET;
1007 	T_ASSERT_GT(frame_length, 0, "%s: frame_length %u",
1008 	    __func__, frame_length);
1009 	if (G_debug) {
1010 		T_LOG("Port %s -> %s transmitting %u bytes",
1011 		    port->ifname, port->member_ifname, frame_length);
1012 	}
1013 	ethernet_frame_validate(&pkt, frame_length, G_debug);
1014 	n = write(port->fd, &pkt, frame_length);
1015 	if (n < 0) {
1016 		T_ASSERT_POSIX_SUCCESS(n, "%s write fd %d failed %ld",
1017 		    port->ifname, port->fd, n);
1018 	}
1019 	T_QUIET;
1020 	T_ASSERT_EQ((u_int)n, frame_length,
1021 	    "%s fd %d wrote %ld",
1022 	    port->ifname, port->fd, n);
1023 }
1024 
1025 
1026 static void
switch_port_send_udp(switch_port_t port,uint8_t af,const ether_addr_t * src_eaddr,union ifbrip * src_ip,uint16_t src_port,const ether_addr_t * dst_eaddr,union ifbrip * dst_ip,uint16_t dst_port,const void * payload,u_int payload_length)1027 switch_port_send_udp(switch_port_t port,
1028     uint8_t af,
1029     const ether_addr_t * src_eaddr,
1030     union ifbrip * src_ip,
1031     uint16_t src_port,
1032     const ether_addr_t * dst_eaddr,
1033     union ifbrip * dst_ip,
1034     uint16_t dst_port,
1035     const void * payload, u_int payload_length)
1036 {
1037 	u_int                   frame_length;
1038 	ether_packet            pkt;
1039 	ssize_t                 n;
1040 
1041 	/* make sure we can send */
1042 	switch_port_check_tx(port);
1043 
1044 	/* generate the packet */
1045 	frame_length
1046 	        = ethernet_udp_frame_populate((void *)&pkt,
1047 	    (u_int)sizeof(pkt),
1048 	    af,
1049 	    src_eaddr,
1050 	    src_ip,
1051 	    src_port,
1052 	    dst_eaddr,
1053 	    dst_ip,
1054 	    dst_port,
1055 	    payload,
1056 	    payload_length);
1057 	T_QUIET;
1058 	T_ASSERT_GT(frame_length, 0, NULL);
1059 	if (G_debug) {
1060 		T_LOG("Port %s transmitting %u bytes",
1061 		    port->ifname, frame_length);
1062 	}
1063 	ethernet_frame_validate(&pkt, frame_length, G_debug);
1064 	n = write(port->fd, &pkt, frame_length);
1065 	if (n < 0) {
1066 		T_ASSERT_POSIX_SUCCESS(n, "%s write fd %d failed %ld",
1067 		    port->ifname, port->fd, n);
1068 	}
1069 	T_QUIET;
1070 	T_ASSERT_EQ((u_int)n, frame_length,
1071 	    "%s fd %d wrote %ld",
1072 	    port->ifname, port->fd, n);
1073 }
1074 
1075 
1076 
1077 static void
switch_port_send_udp_addr_index(switch_port_t port,uint8_t af,u_int addr_index,const ether_addr_t * dst_eaddr,union ifbrip * dst_ip,const void * payload,u_int payload_length)1078 switch_port_send_udp_addr_index(switch_port_t port,
1079     uint8_t af,
1080     u_int addr_index,
1081     const ether_addr_t * dst_eaddr,
1082     union ifbrip * dst_ip,
1083     const void * payload, u_int payload_length)
1084 {
1085 	ether_addr_t    eaddr;
1086 	union ifbrip    ip;
1087 
1088 	/* generate traffic for the unit and address */
1089 	set_ethernet_address(&eaddr, port->unit, addr_index);
1090 	get_ip_address(af, port->unit, addr_index, &ip);
1091 	switch_port_send_udp(port, af,
1092 	    &eaddr, &ip, TEST_SOURCE_PORT,
1093 	    dst_eaddr, dst_ip, TEST_DEST_PORT,
1094 	    payload, payload_length);
1095 }
1096 
1097 typedef void
1098 (packet_validator)(switch_port_t port, const ether_header_t * eh_p,
1099     u_int pkt_len, void * context);
1100 typedef packet_validator * packet_validator_t;
1101 
1102 static void
switch_port_receive(switch_port_t port,uint8_t af,const void * payload,u_int payload_length,packet_validator_t validator,void * context)1103 switch_port_receive(switch_port_t port,
1104     uint8_t af,
1105     const void * payload, u_int payload_length,
1106     packet_validator_t validator,
1107     void * context)
1108 {
1109 	ether_header_t *        eh_p;
1110 	ssize_t                 n;
1111 	char *                  offset;
1112 
1113 	n = read(port->fd, port->rx_buf, (unsigned)port->rx_buf_size);
1114 	if (n < 0) {
1115 		if (errno == EAGAIN) {
1116 			return;
1117 		}
1118 		T_QUIET;
1119 		T_ASSERT_POSIX_SUCCESS(n, "read %s port %d fd %d",
1120 		    port->ifname, port->unit, port->fd);
1121 		return;
1122 	}
1123 	for (offset = port->rx_buf; n > 0;) {
1124 		struct bpf_hdr *        bpf = (struct bpf_hdr *)(void *)offset;
1125 		u_int                   pkt_len;
1126 		char *                  pkt;
1127 		u_int                   skip;
1128 
1129 		pkt = offset + bpf->bh_hdrlen;
1130 		pkt_len = bpf->bh_caplen;
1131 
1132 		eh_p = (ether_header_t *)(void *)pkt;
1133 		T_QUIET;
1134 		T_ASSERT_GE(pkt_len, (u_int)sizeof(*eh_p),
1135 		    "short packet %ld", n);
1136 
1137 		/* source shouldn't be broadcast/multicast */
1138 		T_QUIET;
1139 		T_ASSERT_EQ(eh_p->ether_shost[0] & 0x01, 0,
1140 		    "broadcast/multicast source");
1141 
1142 		if (G_debug) {
1143 			T_LOG("Port %s [unit %d] [fd %d] Received %u bytes",
1144 			    port->ifname, port->unit, port->fd, pkt_len);
1145 		}
1146 		ethernet_frame_validate(pkt, pkt_len, G_debug);
1147 
1148 		/* call the validation function */
1149 		(*validator)(port, eh_p, pkt_len, context);
1150 
1151 		if (payload != NULL) {
1152 			const void *    p;
1153 			u_int           p_len;
1154 
1155 			p = ethernet_frame_get_udp_payload(af, pkt, pkt_len,
1156 			    &p_len);
1157 			T_QUIET;
1158 			T_ASSERT_NOTNULL(p, "ethernet_frame_get_udp_payload");
1159 			T_QUIET;
1160 			T_ASSERT_EQ(p_len, payload_length,
1161 			    "payload length %u < expected %u",
1162 			    p_len, payload_length);
1163 			T_QUIET;
1164 			T_ASSERT_EQ(bcmp(payload, p, payload_length), 0,
1165 			    "unexpected payload");
1166 		}
1167 		skip = BPF_WORDALIGN(pkt_len + bpf->bh_hdrlen);
1168 		if (skip == 0) {
1169 			break;
1170 		}
1171 		offset += skip;
1172 		n -= skip;
1173 	}
1174 	return;
1175 }
1176 
1177 static void
switch_port_log(switch_port_t port)1178 switch_port_log(switch_port_t port)
1179 {
1180 	T_LOG("%s [unit %d] [member %s]%s bpf fd %d bufsize %d\n",
1181 	    port->ifname, port->unit,
1182 	    port->member_ifname,
1183 	    port->mac_nat ? " [mac-nat]" : "",
1184 	    port->fd, port->rx_buf_size);
1185 }
1186 
1187 #define switch_port_list_size(port_count)               \
1188 	offsetof(switch_port_list, list[port_count])
1189 
1190 static switch_port_list_t
switch_port_list_alloc(u_int port_count,bool mac_nat)1191 switch_port_list_alloc(u_int port_count, bool mac_nat)
1192 {
1193 	switch_port_list_t      list;
1194 
1195 	list = (switch_port_list_t)
1196 	    calloc(1, switch_port_list_size(port_count));;
1197 	list->size = port_count;
1198 	list->mac_nat = mac_nat;
1199 	return list;
1200 }
1201 
1202 static void
switch_port_list_dealloc(switch_port_list_t list)1203 switch_port_list_dealloc(switch_port_list_t list)
1204 {
1205 	u_int           i;
1206 	switch_port_t   port;
1207 
1208 	for (i = 0, port = list->list; i < list->count; i++, port++) {
1209 		close(port->fd);
1210 		free(port->rx_buf);
1211 	}
1212 	free(list);
1213 	return;
1214 }
1215 
1216 static errno_t
switch_port_list_add_port(switch_port_list_t port_list,u_int unit,const char * ifname,u_short if_index,const char * member_ifname,u_int num_addrs,bool mac_nat,bool attach_stack,struct in_addr * ip)1217 switch_port_list_add_port(switch_port_list_t port_list, u_int unit,
1218     const char * ifname, u_short if_index, const char * member_ifname,
1219     u_int num_addrs, bool mac_nat, bool attach_stack, struct in_addr * ip)
1220 {
1221 	int             buf_size;
1222 	errno_t         err = EINVAL;
1223 	int             fd = -1;
1224 	char            ntopbuf_ip[INET6_ADDRSTRLEN];
1225 	int             opt;
1226 	switch_port_t   p;
1227 
1228 	if (port_list->count >= port_list->size) {
1229 		T_LOG("Internal error: port_list count %u >= size %u\n",
1230 		    port_list->count, port_list->size);
1231 		goto failed;
1232 	}
1233 	fd = bpf_new();
1234 	if (fd < 0) {
1235 		err = errno;
1236 		T_LOG("bpf_new");
1237 		goto failed;
1238 	}
1239 	bpf_set_traffic_class(fd, SO_TC_CTL);
1240 	opt = 1;
1241 	T_QUIET;
1242 	T_ASSERT_POSIX_SUCCESS(ioctl(fd, FIONBIO, &opt), NULL);
1243 	T_QUIET;
1244 	T_ASSERT_POSIX_SUCCESS(bpf_set_immediate(fd, 1), NULL);
1245 	T_QUIET;
1246 	T_ASSERT_POSIX_SUCCESS(bpf_setif(fd, ifname), "bpf set if %s",
1247 	    ifname);
1248 	T_QUIET;
1249 	T_ASSERT_POSIX_SUCCESS(bpf_set_see_sent(fd, 0), NULL);
1250 	T_QUIET;
1251 	T_ASSERT_POSIX_SUCCESS(bpf_set_header_complete(fd, 1), NULL);
1252 	T_QUIET;
1253 	T_ASSERT_POSIX_SUCCESS(bpf_get_blen(fd, &buf_size), NULL);
1254 	if (G_debug) {
1255 		T_LOG("%s [unit %d] [member %s] bpf fd %d bufsize %d\n",
1256 		    ifname, unit,
1257 		    member_ifname, fd, buf_size);
1258 	}
1259 	p = port_list->list + port_list->count++;
1260 	p->fd = fd;
1261 	p->unit = unit;
1262 	strlcpy(p->ifname, ifname, sizeof(p->ifname));
1263 	strlcpy(p->member_ifname, member_ifname, sizeof(p->member_ifname));
1264 	p->num_addrs = num_addrs;
1265 	p->rx_buf_size = buf_size;
1266 	p->rx_buf = malloc((unsigned)buf_size);
1267 	p->mac_nat = mac_nat;
1268 	ifnet_get_lladdr(ifname, &p->mac);
1269 	ifnet_get_lladdr(member_ifname, &p->member_mac);
1270 	p->if_index = if_index;
1271 	if (attach_stack) {
1272 		p->ip = *ip;
1273 		get_ipv6_ll_address(&p->mac, &p->ip6);
1274 		inet_ntop(AF_INET6, &p->ip6, ntopbuf_ip, sizeof(ntopbuf_ip));
1275 		T_LOG("%s %s", ifname, ntopbuf_ip);
1276 	}
1277 	return 0;
1278 
1279 failed:
1280 	if (fd >= 0) {
1281 		close(fd);
1282 	}
1283 	return err;
1284 }
1285 
1286 static switch_port_t
switch_port_list_find_fd(switch_port_list_t ports,int fd)1287 switch_port_list_find_fd(switch_port_list_t ports, int fd)
1288 {
1289 	u_int           i;
1290 	switch_port_t   port;
1291 
1292 	for (i = 0, port = ports->list; i < ports->count; i++, port++) {
1293 		if (port->fd == fd) {
1294 			return port;
1295 		}
1296 	}
1297 	return NULL;
1298 }
1299 
1300 static void
switch_port_list_log(switch_port_list_t port_list)1301 switch_port_list_log(switch_port_list_t port_list)
1302 {
1303 	u_int           i;
1304 	switch_port_t   port;
1305 
1306 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1307 		switch_port_log(port);
1308 	}
1309 	return;
1310 }
1311 
1312 static switch_port_t
switch_port_list_find_member(switch_port_list_t ports,const char * member_ifname)1313 switch_port_list_find_member(switch_port_list_t ports, const char * member_ifname)
1314 {
1315 	u_int           i;
1316 	switch_port_t   port;
1317 
1318 	for (i = 0, port = ports->list; i < ports->count; i++, port++) {
1319 		if (strcmp(port->member_ifname, member_ifname) == 0) {
1320 			return port;
1321 		}
1322 	}
1323 	return NULL;
1324 }
1325 
1326 static void
switch_port_list_check_receive(switch_port_list_t ports,uint8_t af,const void * payload,u_int payload_length,packet_validator_t validator,void * context)1327 switch_port_list_check_receive(switch_port_list_t ports, uint8_t af,
1328     const void * payload, u_int payload_length,
1329     packet_validator_t validator,
1330     void * context)
1331 {
1332 	int             i;
1333 	int             n_events;
1334 	struct kevent   kev[ports->count];
1335 	int             kq;
1336 	switch_port_t   port;
1337 	struct timespec ts = { .tv_sec = 0, .tv_nsec = 10 * 1000 * 1000};
1338 	u_int           u;
1339 
1340 	kq = kqueue();
1341 	T_QUIET;
1342 	T_ASSERT_POSIX_SUCCESS(kq, "kqueue check_receive");
1343 	for (u = 0, port = ports->list; u < ports->count; u++, port++) {
1344 		port->test_count = 0;
1345 		EV_SET(kev + u, port->fd,
1346 		    EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
1347 	}
1348 
1349 	do {
1350 		n_events = kevent(kq, kev, (int)ports->count, kev,
1351 		    (int)ports->count, &ts);
1352 		T_QUIET;
1353 		T_ASSERT_POSIX_SUCCESS(n_events, "kevent receive %d", n_events);
1354 		for (i = 0; i < n_events; i++) {
1355 			T_QUIET;
1356 			T_ASSERT_EQ((int)kev[i].filter, EVFILT_READ, NULL);
1357 			T_QUIET;
1358 			T_ASSERT_NULL(kev[i].udata, NULL);
1359 			port = switch_port_list_find_fd(ports,
1360 			    (int)kev[i].ident);
1361 			T_QUIET;
1362 			T_ASSERT_NE(port, NULL,
1363 			    "port %p fd %d", (void *)port,
1364 			    (int)kev[i].ident);
1365 			switch_port_receive(port, af, payload, payload_length,
1366 			    validator, context);
1367 		}
1368 	} while (n_events != 0);
1369 	close(kq);
1370 }
1371 
1372 static bool
switch_port_list_verify_rt_table(switch_port_list_t port_list,bool log)1373 switch_port_list_verify_rt_table(switch_port_list_t port_list, bool log)
1374 {
1375 	bool            all_present = true;
1376 	u_int           i;
1377 	u_int           count;
1378 	struct ifbareq *ifba;
1379 	struct ifbareq *rt_table;
1380 	switch_port_t   port;
1381 
1382 	/* clear out current notion of how many addresses are present */
1383 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1384 		port->test_address_count = 0;
1385 		port->test_address_present = 0;
1386 	}
1387 	rt_table = bridge_rt_table_copy(&count);
1388 	if (rt_table == NULL) {
1389 		return false;
1390 	}
1391 	if (log) {
1392 		bridge_rt_table_log(rt_table, count);
1393 	}
1394 	for (i = 0, ifba = rt_table; i < count; i++, ifba++) {
1395 		uint64_t        addr_bit;
1396 		u_int           addr_index;
1397 		u_int           unit_index;
1398 		u_char *        ea;
1399 		ether_addr_t *  eaddr;
1400 
1401 		eaddr = (ether_addr_t *)&ifba->ifba_dst;
1402 		ea = eaddr->octet;
1403 		addr_index = ea[EA_ADDR_INDEX];
1404 		unit_index = ea[EA_UNIT_INDEX];
1405 		port = switch_port_list_find_member(port_list,
1406 		    ifba->ifba_ifsname);
1407 		T_QUIET;
1408 		T_ASSERT_NOTNULL(port, "switch_port_list_find_member %s",
1409 		    ifba->ifba_ifsname);
1410 		if (!S_cleaning_up) {
1411 			T_QUIET;
1412 			T_ASSERT_EQ(unit_index, port->unit, NULL);
1413 			addr_bit = 1 << addr_index;
1414 			T_QUIET;
1415 			T_ASSERT_BITS_NOTSET(port->test_address_present,
1416 			    addr_bit, "%s address %u",
1417 			    ifba->ifba_ifsname, addr_index);
1418 			port->test_address_present |= addr_bit;
1419 			port->test_address_count++;
1420 		}
1421 	}
1422 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1423 		if (G_debug) {
1424 			T_LOG("%s unit %d [member %s] %u expect %u",
1425 			    port->ifname, port->unit, port->member_ifname,
1426 			    port->test_address_count, port->num_addrs);
1427 		}
1428 		if (port->test_address_count != port->num_addrs) {
1429 			all_present = false;
1430 		}
1431 	}
1432 
1433 	free(rt_table);
1434 	return all_present;
1435 }
1436 
1437 static bool
switch_port_list_verify_mac_nat(switch_port_list_t port_list,bool log)1438 switch_port_list_verify_mac_nat(switch_port_list_t port_list, bool log)
1439 {
1440 	bool                    all_present = true;
1441 	u_int                   i;
1442 	u_int                   count;
1443 	static struct ifbrmne * entries;
1444 	switch_port_t           port;
1445 	struct ifbrmne *        scan;
1446 
1447 
1448 	/* clear out current notion of how many addresses are present */
1449 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1450 		port->test_address_count = 0;
1451 		port->test_address_present = 0;
1452 	}
1453 	entries = bridge_mac_nat_entries_copy(&count);
1454 	if (entries == NULL) {
1455 		return false;
1456 	}
1457 	if (log) {
1458 		bridge_mac_nat_entries_log(entries, count);
1459 	}
1460 	for (i = 0, scan = entries; i < count; i++, scan++) {
1461 		uint8_t         af;
1462 		uint64_t        addr_bit;
1463 		u_int           addr_index;
1464 		char            buf_ip1[INET6_ADDRSTRLEN];
1465 		char            buf_ip2[INET6_ADDRSTRLEN];
1466 		u_char *        ea;
1467 		ether_addr_t *  eaddr;
1468 		union ifbrip    ip;
1469 		u_int           unit_index;
1470 
1471 		eaddr = (ether_addr_t *)&scan->ifbmne_mac;
1472 		ea = eaddr->octet;
1473 		addr_index = ea[EA_ADDR_INDEX];
1474 		unit_index = ea[EA_UNIT_INDEX];
1475 		port = switch_port_list_find_member(port_list,
1476 		    scan->ifbmne_ifname);
1477 		T_QUIET;
1478 		T_ASSERT_NOTNULL(port,
1479 		    "switch_port_list_find_member %s",
1480 		    scan->ifbmne_ifname);
1481 		T_QUIET;
1482 		T_ASSERT_EQ(unit_index, port->unit, NULL);
1483 		af = scan->ifbmne_af;
1484 		get_ip_address(af, port->unit, addr_index, &ip);
1485 		addr_bit = 1 << addr_index;
1486 		T_QUIET;
1487 		T_ASSERT_TRUE(ip_addresses_are_equal(af, &ip, &scan->ifbmne_ip),
1488 		    "mac nat entry IP address %s expected %s",
1489 		    inet_ntop(af, &scan->ifbmne_ip_addr,
1490 		    buf_ip1, sizeof(buf_ip1)),
1491 		    inet_ntop(af, &ip,
1492 		    buf_ip2, sizeof(buf_ip2)));
1493 		T_QUIET;
1494 		T_ASSERT_BITS_NOTSET(port->test_address_present,
1495 		    addr_bit, "%s address %u",
1496 		    scan->ifbmne_ifname, addr_index);
1497 		port->test_address_present |= addr_bit;
1498 		port->test_address_count++;
1499 	}
1500 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1501 		if (port->mac_nat) {
1502 			/* MAC-NAT interface should have no entries */
1503 			T_QUIET;
1504 			T_ASSERT_EQ(port->test_address_count, 0,
1505 			    "mac nat interface %s has %u entries",
1506 			    port->member_ifname,
1507 			    port->test_address_count);
1508 		} else {
1509 			if (G_debug) {
1510 				T_LOG("%s unit %d [member %s] %u expect %u",
1511 				    port->ifname, port->unit,
1512 				    port->member_ifname,
1513 				    port->test_address_count, port->num_addrs);
1514 			}
1515 			if (port->test_address_count != port->num_addrs) {
1516 				all_present = false;
1517 			}
1518 		}
1519 	}
1520 
1521 	free(entries);
1522 
1523 	return all_present;
1524 }
1525 
1526 /**
1527 ** Basic Bridge Tests
1528 **/
1529 static void
send_generation(switch_port_t port,uint8_t af,u_int addr_index,const ether_addr_t * dst_eaddr,union ifbrip * dst_ip,uint32_t generation)1530 send_generation(switch_port_t port, uint8_t af, u_int addr_index,
1531     const ether_addr_t * dst_eaddr, union ifbrip * dst_ip,
1532     uint32_t generation)
1533 {
1534 	uint32_t        payload;
1535 
1536 	payload = htonl(generation);
1537 	switch_port_send_udp_addr_index(port, af, addr_index, dst_eaddr, dst_ip,
1538 	    &payload, sizeof(payload));
1539 }
1540 
1541 static void
check_receive_generation(switch_port_list_t ports,uint8_t af,uint32_t generation,packet_validator_t validator,__unused void * context)1542 check_receive_generation(switch_port_list_t ports, uint8_t af,
1543     uint32_t generation, packet_validator_t validator,
1544     __unused void * context)
1545 {
1546 	uint32_t        payload;
1547 
1548 	payload = htonl(generation);
1549 	switch_port_list_check_receive(ports, af, &payload, sizeof(payload),
1550 	    validator, context);
1551 }
1552 
1553 static void
validate_source_ether_mismatch(switch_port_t port,const ether_header_t * eh_p)1554 validate_source_ether_mismatch(switch_port_t port, const ether_header_t * eh_p)
1555 {
1556 	/* source shouldn't be our own MAC addresses */
1557 	T_QUIET;
1558 	T_ASSERT_NE(eh_p->ether_shost[EA_UNIT_INDEX], port->unit,
1559 	    "ether source matches unit %d", port->unit);
1560 }
1561 
1562 static void
validate_not_present_dhost(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)1563 validate_not_present_dhost(switch_port_t port, const ether_header_t * eh_p,
1564     __unused u_int pkt_len,
1565     __unused void * context)
1566 {
1567 	validate_source_ether_mismatch(port, eh_p);
1568 	T_QUIET;
1569 	T_ASSERT_EQ(bcmp(eh_p->ether_dhost, &ether_external,
1570 	    sizeof(eh_p->ether_dhost)), 0,
1571 	    "%s", __func__);
1572 	port->test_count++;
1573 }
1574 
1575 static void
validate_broadcast_dhost(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)1576 validate_broadcast_dhost(switch_port_t port, const ether_header_t * eh_p,
1577     __unused u_int pkt_len,
1578     __unused void * context)
1579 {
1580 	validate_source_ether_mismatch(port, eh_p);
1581 	T_QUIET;
1582 	T_ASSERT_NE((eh_p->ether_dhost[0] & 0x01), 0,
1583 	    "%s", __func__);
1584 	port->test_count++;
1585 }
1586 
1587 static void
validate_port_dhost(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)1588 validate_port_dhost(switch_port_t port, const ether_header_t * eh_p,
1589     __unused u_int pkt_len,
1590     __unused void * context)
1591 {
1592 	validate_source_ether_mismatch(port, eh_p);
1593 	T_QUIET;
1594 	T_ASSERT_EQ(eh_p->ether_dhost[EA_UNIT_INDEX], port->unit,
1595 	    "wrong dhost unit %d != %d",
1596 	    eh_p->ether_dhost[EA_UNIT_INDEX], port->unit);
1597 	port->test_count++;
1598 }
1599 
1600 
1601 static void
check_received_count(switch_port_list_t port_list,switch_port_t port,uint32_t expected_packets)1602 check_received_count(switch_port_list_t port_list,
1603     switch_port_t port, uint32_t expected_packets)
1604 {
1605 	u_int           i;
1606 	switch_port_t   scan;
1607 
1608 	for (i = 0, scan = port_list->list; i < port_list->count; i++, scan++) {
1609 		if (scan == port) {
1610 			T_QUIET;
1611 			T_ASSERT_EQ(port->test_count, 0,
1612 			    "unexpected receive on port %d",
1613 			    port->unit);
1614 		} else if (expected_packets == ALL_ADDRS) {
1615 			T_QUIET;
1616 			T_ASSERT_EQ(scan->test_count, scan->num_addrs,
1617 			    "didn't receive on all addrs");
1618 		} else {
1619 			T_QUIET;
1620 			T_ASSERT_EQ(scan->test_count, expected_packets,
1621 			    "wrong receive count on port %s", scan->member_ifname);
1622 		}
1623 	}
1624 }
1625 
1626 static void
unicast_send_all(switch_port_list_t port_list,uint8_t af,switch_port_t port)1627 unicast_send_all(switch_port_list_t port_list, uint8_t af, switch_port_t port)
1628 {
1629 	u_int           i;
1630 	switch_port_t   scan;
1631 
1632 	for (i = 0, scan = port_list->list; i < port_list->count; i++, scan++) {
1633 		if (G_debug) {
1634 			T_LOG("Unicast send on %s", port->ifname);
1635 		}
1636 		for (u_int j = 0; j < scan->num_addrs; j++) {
1637 			ether_addr_t    eaddr;
1638 			union ifbrip    ip;
1639 
1640 			set_ethernet_address(&eaddr, scan->unit, j);
1641 			get_ip_address(af, scan->unit, j, &ip);
1642 			switch_port_send_udp_addr_index(port, af, 0, &eaddr, &ip,
1643 			    NULL, 0);
1644 		}
1645 	}
1646 }
1647 
1648 
1649 static void
bridge_learning_test_once(switch_port_list_t port_list,uint8_t af,packet_validator_t validator,void * context,const ether_addr_t * dst_eaddr,bool retry)1650 bridge_learning_test_once(switch_port_list_t port_list,
1651     uint8_t af,
1652     packet_validator_t validator,
1653     void * context,
1654     const ether_addr_t * dst_eaddr,
1655     bool retry)
1656 {
1657 	u_int           i;
1658 	union ifbrip    dst_ip;
1659 	switch_port_t   port;
1660 
1661 	get_broadcast_ip_address(af, &dst_ip);
1662 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1663 		if (port->test_address_count == port->num_addrs) {
1664 			/* already populated */
1665 			continue;
1666 		}
1667 		if (G_debug) {
1668 			T_LOG("Sending on %s", port->ifname);
1669 		}
1670 		for (u_int j = 0; j < port->num_addrs; j++) {
1671 			uint32_t        generation;
1672 
1673 			if (retry) {
1674 				uint64_t        addr_bit;
1675 
1676 				addr_bit = 1 << j;
1677 				if ((port->test_address_present & addr_bit)
1678 				    != 0) {
1679 					/* already present */
1680 					continue;
1681 				}
1682 				T_LOG("Retry port %s unit %u address %u",
1683 				    port->ifname, port->unit, j);
1684 			}
1685 			generation = next_generation();
1686 			send_generation(port,
1687 			    af,
1688 			    j,
1689 			    dst_eaddr,
1690 			    &dst_ip,
1691 			    generation);
1692 
1693 			/* receive across all ports */
1694 			check_receive_generation(port_list,
1695 			    af,
1696 			    generation,
1697 			    validator,
1698 			    context);
1699 
1700 			/* ensure that every port saw the packet */
1701 			check_received_count(port_list, port, 1);
1702 		}
1703 	}
1704 	return;
1705 }
1706 
1707 static void
bridge_learning_test(switch_port_list_t port_list,uint8_t af,packet_validator_t validator,void * context,const ether_addr_t * dst_eaddr)1708 bridge_learning_test(switch_port_list_t port_list,
1709     uint8_t af,
1710     packet_validator_t validator,
1711     void * context,
1712     const ether_addr_t * dst_eaddr)
1713 {
1714 	char            ntoabuf[ETHER_NTOA_BUFSIZE];
1715 	u_int           i;
1716 	switch_port_t   port;
1717 	bool            verified = false;
1718 
1719 	ether_ntoa_buf(dst_eaddr, ntoabuf, sizeof(ntoabuf));
1720 
1721 	/*
1722 	 * Send a broadcast frame from every port in the list so that the bridge
1723 	 * learns our MAC address.
1724 	 */
1725 #define BROADCAST_MAX_TRIES             20
1726 	for (int try = 1; try < BROADCAST_MAX_TRIES; try++) {
1727 		bool    retry = (try > 1);
1728 
1729 		if (!retry) {
1730 			T_LOG("%s: %s #ports %u #addrs %u dest %s",
1731 			    __func__,
1732 			    af_get_str(af),
1733 			    port_list->count, port_list->list->num_addrs,
1734 			    ntoabuf);
1735 		} else {
1736 			T_LOG("%s: %s #ports %u #addrs %u dest %s (TRY=%d)",
1737 			    __func__,
1738 			    af_get_str(af),
1739 			    port_list->count, port_list->list->num_addrs,
1740 			    ntoabuf, try);
1741 		}
1742 		bridge_learning_test_once(port_list, af, validator, context,
1743 		    dst_eaddr, retry);
1744 		/*
1745 		 * In the event of a memory allocation failure, it's possible
1746 		 * that the address was not learned. Figure out whether
1747 		 * all addresses are present, and if not, we'll retry on
1748 		 * those that are not present.
1749 		 */
1750 		verified = switch_port_list_verify_rt_table(port_list, false);
1751 		if (verified) {
1752 			break;
1753 		}
1754 		/* wait a short time to allow the system to recover */
1755 		usleep(100 * 1000);
1756 	}
1757 	T_QUIET;
1758 	T_ASSERT_TRUE(verified, "All addresses present");
1759 
1760 	/*
1761 	 * Since we just broadcast on every port in the switch, the bridge knows
1762 	 * the port's MAC addresses. The bridge should not need to broadcast the
1763 	 * packet to learn, which means the unicast traffic should only arrive
1764 	 * on the intended port.
1765 	 */
1766 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1767 		/* send unicast packets to every other port's MAC addresses */
1768 		unicast_send_all(port_list, af, port);
1769 
1770 		/* receive all of that generated traffic */
1771 		switch_port_list_check_receive(port_list, af, NULL, 0,
1772 		    validate_port_dhost, NULL);
1773 		/* check that we saw all of the unicast packets */
1774 		check_received_count(port_list, port, ALL_ADDRS);
1775 	}
1776 	T_PASS("%s", __func__);
1777 }
1778 
1779 /**
1780 ** MAC-NAT tests
1781 **/
1782 static void
mac_nat_check_received_count(switch_port_list_t port_list,switch_port_t port)1783 mac_nat_check_received_count(switch_port_list_t port_list, switch_port_t port)
1784 {
1785 	u_int           i;
1786 	switch_port_t   scan;
1787 
1788 	for (i = 0, scan = port_list->list; i < port_list->count; i++, scan++) {
1789 		u_int   expected = 0;
1790 
1791 		if (scan == port) {
1792 			expected = scan->num_addrs;
1793 		}
1794 		T_QUIET;
1795 		T_ASSERT_EQ(scan->test_count, expected,
1796 		    "%s [member %s]%s expected %u actual %u",
1797 		    scan->ifname, scan->member_ifname,
1798 		    scan->mac_nat ? " [mac-nat]" : "",
1799 		    expected, scan->test_count);
1800 	}
1801 }
1802 
1803 static void
validate_mac_nat(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)1804 validate_mac_nat(switch_port_t port, const ether_header_t * eh_p,
1805     __unused u_int pkt_len,
1806     __unused void * context)
1807 {
1808 	if (port->mac_nat) {
1809 		bool    equal;
1810 
1811 		/* source must match MAC-NAT interface */
1812 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
1813 		    sizeof(port->member_mac)) == 0);
1814 		if (!equal) {
1815 			ethernet_frame_validate(eh_p, pkt_len, true);
1816 		}
1817 		T_QUIET;
1818 		T_ASSERT_TRUE(equal, "source address match");
1819 		port->test_count++;
1820 	} else {
1821 		validate_not_present_dhost(port, eh_p, pkt_len, NULL);
1822 	}
1823 }
1824 
1825 static void
validate_mac_nat_in(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,__unused void * context)1826 validate_mac_nat_in(switch_port_t port, const ether_header_t * eh_p,
1827     u_int pkt_len, __unused void * context)
1828 {
1829 	if (G_debug) {
1830 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
1831 		ethernet_frame_validate(eh_p, pkt_len, true);
1832 	}
1833 	T_QUIET;
1834 	T_ASSERT_EQ(eh_p->ether_dhost[EA_UNIT_INDEX], port->unit,
1835 	    "dhost unit %u expected %u",
1836 	    eh_p->ether_dhost[EA_UNIT_INDEX], port->unit);
1837 	port->test_count++;
1838 }
1839 
1840 static void
validate_mac_nat_arp_out(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)1841 validate_mac_nat_arp_out(switch_port_t port, const ether_header_t * eh_p,
1842     u_int pkt_len, void * context)
1843 {
1844 	const struct ether_arp *        earp;
1845 	switch_port_t                   send_port = (switch_port_t)context;
1846 
1847 	if (G_debug) {
1848 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
1849 		ethernet_frame_validate(eh_p, pkt_len, true);
1850 	}
1851 	T_QUIET;
1852 	T_ASSERT_EQ((int)ntohs(eh_p->ether_type), (int)ETHERTYPE_ARP, NULL);
1853 	earp = (const struct ether_arp *)(const void *)(eh_p + 1);
1854 	T_QUIET;
1855 	T_ASSERT_GE(pkt_len, (u_int)(sizeof(*eh_p) + sizeof(*earp)), NULL);
1856 	if (port->mac_nat) {
1857 		bool            equal;
1858 
1859 		/* source ethernet must match MAC-NAT interface */
1860 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
1861 		    sizeof(port->member_mac)) == 0);
1862 		if (!equal) {
1863 			ethernet_frame_validate(eh_p, pkt_len, true);
1864 		}
1865 		T_QUIET;
1866 		T_ASSERT_TRUE(equal, "%s -> %s source address translated",
1867 		    send_port->member_ifname,
1868 		    port->member_ifname);
1869 		/* sender hw must match MAC-NAT interface */
1870 		equal = (bcmp(earp->arp_sha, &port->member_mac,
1871 		    sizeof(port->member_mac)) == 0);
1872 		if (!equal) {
1873 			ethernet_frame_validate(eh_p, pkt_len, true);
1874 		}
1875 		T_QUIET;
1876 		T_ASSERT_TRUE(equal, "%s -> %s sender hardware translated",
1877 		    send_port->member_ifname,
1878 		    port->member_ifname);
1879 	} else {
1880 		/* source ethernet must match the sender */
1881 		T_QUIET;
1882 		T_ASSERT_EQ(eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit,
1883 		    "%s -> %s unit %u expected %u",
1884 		    send_port->member_ifname,
1885 		    port->member_ifname,
1886 		    eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit);
1887 		/* source hw must match the sender */
1888 		T_QUIET;
1889 		T_ASSERT_EQ(earp->arp_sha[EA_UNIT_INDEX], send_port->unit,
1890 		    "%s -> %s unit %u expected %u",
1891 		    send_port->member_ifname,
1892 		    port->member_ifname,
1893 		    earp->arp_sha[EA_UNIT_INDEX], send_port->unit);
1894 	}
1895 	port->test_count++;
1896 }
1897 
1898 static void
validate_mac_nat_arp_in(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)1899 validate_mac_nat_arp_in(switch_port_t port, const ether_header_t * eh_p,
1900     u_int pkt_len, void * context)
1901 {
1902 	const struct ether_arp *        earp;
1903 	switch_port_t                   send_port = (switch_port_t)context;
1904 
1905 	if (G_debug) {
1906 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
1907 		ethernet_frame_validate(eh_p, pkt_len, true);
1908 	}
1909 	earp = (const struct ether_arp *)(const void *)(eh_p + 1);
1910 	T_QUIET;
1911 	T_ASSERT_EQ((int)ntohs(eh_p->ether_type), (int)ETHERTYPE_ARP, NULL);
1912 	T_QUIET;
1913 	T_ASSERT_GE(pkt_len, (u_int)(sizeof(*eh_p) + sizeof(*earp)), NULL);
1914 	T_QUIET;
1915 	T_ASSERT_FALSE(port->mac_nat, NULL);
1916 
1917 	/* destination ethernet must match the unit */
1918 	T_QUIET;
1919 	T_ASSERT_EQ(eh_p->ether_dhost[EA_UNIT_INDEX], port->unit,
1920 	    "%s -> %s unit %u expected %u",
1921 	    send_port->member_ifname,
1922 	    port->member_ifname,
1923 	    eh_p->ether_dhost[EA_UNIT_INDEX], port->unit);
1924 	/* source hw must match the sender */
1925 	T_QUIET;
1926 	T_ASSERT_EQ(earp->arp_tha[EA_UNIT_INDEX], port->unit,
1927 	    "%s -> %s unit %u expected %u",
1928 	    send_port->member_ifname,
1929 	    port->member_ifname,
1930 	    earp->arp_tha[EA_UNIT_INDEX], port->unit);
1931 	port->test_count++;
1932 }
1933 
1934 static void
mac_nat_test_arp_out(switch_port_list_t port_list)1935 mac_nat_test_arp_out(switch_port_list_t port_list)
1936 {
1937 	u_int           i;
1938 	struct in_addr  ip_dst;
1939 	switch_port_t   port;
1940 
1941 	ip_dst = get_external_ipv4_address();
1942 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1943 		if (port->mac_nat) {
1944 			continue;
1945 		}
1946 		for (u_int j = 0; j < port->num_addrs; j++) {
1947 			ether_addr_t    eaddr;
1948 			struct in_addr  ip_src;
1949 
1950 			set_ethernet_address(&eaddr, port->unit, j);
1951 			get_ipv4_address(port->unit, j, &ip_src);
1952 			switch_port_send_arp(port,
1953 			    ARPOP_REQUEST,
1954 			    &eaddr,
1955 			    ip_src,
1956 			    NULL,
1957 			    ip_dst);
1958 			switch_port_list_check_receive(port_list, AF_INET,
1959 			    NULL, 0,
1960 			    validate_mac_nat_arp_out,
1961 			    port);
1962 			check_received_count(port_list, port, 1);
1963 		}
1964 	}
1965 	T_PASS("%s", __func__);
1966 }
1967 
1968 static void
mac_nat_send_arp_response(switch_port_t ext_port,switch_port_t port)1969 mac_nat_send_arp_response(switch_port_t ext_port, switch_port_t port)
1970 {
1971 	struct in_addr  ip_src;
1972 
1973 	T_QUIET;
1974 	T_ASSERT_TRUE(ext_port->mac_nat, "%s is MAC-NAT interface",
1975 	    ext_port->member_ifname);
1976 	ip_src = get_external_ipv4_address();
1977 	for (u_int j = 0; j < port->num_addrs; j++) {
1978 		struct in_addr  ip_dst;
1979 
1980 		get_ipv4_address(port->unit, j, &ip_dst);
1981 		if (G_debug) {
1982 			T_LOG("Generating ARP destined to %s %s",
1983 			    port->ifname, inet_ntoa(ip_dst));
1984 		}
1985 		switch_port_send_arp(ext_port,
1986 		    ARPOP_REPLY,
1987 		    &ether_external,
1988 		    ip_src,
1989 		    &ext_port->member_mac,
1990 		    ip_dst);
1991 	}
1992 }
1993 
1994 static void
mac_nat_test_arp_in(switch_port_list_t port_list)1995 mac_nat_test_arp_in(switch_port_list_t port_list)
1996 {
1997 	u_int           i;
1998 	switch_port_t   port;
1999 
2000 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2001 		if (port->mac_nat) {
2002 			continue;
2003 		}
2004 		mac_nat_send_arp_response(port_list->list, port);
2005 
2006 		/* receive the generated traffic */
2007 		switch_port_list_check_receive(port_list, AF_INET, NULL, 0,
2008 		    validate_mac_nat_arp_in,
2009 		    port_list->list);
2010 
2011 		/* verify that only the single port got the packet */
2012 		mac_nat_check_received_count(port_list, port);
2013 	}
2014 	T_PASS("%s", __func__);
2015 }
2016 
2017 static void
validate_mac_nat_dhcp(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)2018 validate_mac_nat_dhcp(switch_port_t port, const ether_header_t * eh_p,
2019     u_int pkt_len, void * context)
2020 {
2021 	u_int                           dp_flags;
2022 	const struct bootp_packet *     pkt;
2023 	switch_port_t                   send_port = (switch_port_t)context;
2024 
2025 
2026 	T_QUIET;
2027 	T_ASSERT_GE(pkt_len, (u_int)sizeof(*pkt), NULL);
2028 	T_QUIET;
2029 	T_ASSERT_EQ((int)ntohs(eh_p->ether_type), (int)ETHERTYPE_IP, NULL);
2030 	pkt = (const struct bootp_packet *)(const void *)(eh_p + 1);
2031 
2032 	dp_flags = ntohs(pkt->bp_bootp.bp_unused);
2033 	if (port->mac_nat) {
2034 		bool            equal;
2035 
2036 		/* Broadcast bit must be set */
2037 		T_QUIET;
2038 		T_ASSERT_BITS_SET(dp_flags, (u_int)DHCP_FLAGS_BROADCAST,
2039 		    "%s -> %s: flags 0x%x must have 0x%x",
2040 		    send_port->member_ifname,
2041 		    port->member_ifname,
2042 		    dp_flags, DHCP_FLAGS_BROADCAST);
2043 
2044 		/* source must match MAC-NAT interface */
2045 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
2046 		    sizeof(port->member_mac)) == 0);
2047 		if (!equal) {
2048 			ethernet_frame_validate(eh_p, pkt_len, true);
2049 		}
2050 		T_QUIET;
2051 		T_ASSERT_TRUE(equal, "%s -> %s source address translated",
2052 		    send_port->member_ifname,
2053 		    port->member_ifname);
2054 	} else {
2055 		/* Broadcast bit must not be set */
2056 		T_QUIET;
2057 		T_ASSERT_BITS_NOTSET(dp_flags, DHCP_FLAGS_BROADCAST,
2058 		    "%s -> %s flags 0x%x must not have 0x%x",
2059 		    send_port->member_ifname,
2060 		    port->member_ifname,
2061 		    dp_flags, DHCP_FLAGS_BROADCAST);
2062 		T_QUIET;
2063 		T_ASSERT_EQ(eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit,
2064 		    "%s -> %s unit %u expected %u",
2065 		    send_port->member_ifname,
2066 		    port->member_ifname,
2067 		    eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit);
2068 	}
2069 	port->test_count++;
2070 }
2071 
2072 static void
mac_nat_test_dhcp(switch_port_list_t port_list,bool link_layer_unicast)2073 mac_nat_test_dhcp(switch_port_list_t port_list, bool link_layer_unicast)
2074 {
2075 	u_int           i;
2076 	struct in_addr  ip_dst = { INADDR_BROADCAST };
2077 	struct in_addr  ip_src = { INADDR_ANY };
2078 	switch_port_t   port;
2079 	ether_addr_t *  ether_dst;
2080 
2081 	if (link_layer_unicast) {
2082 		/* use link-layer address of MAC-NAT interface */
2083 		ether_dst = &port_list->list[0].member_mac;
2084 	} else {
2085 		/* use link-layer broadcast address */
2086 		ether_dst = &ether_broadcast;
2087 	}
2088 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2089 		ether_addr_t            eaddr;
2090 		dhcp_min_payload        payload;
2091 		u_int                   payload_len;
2092 
2093 		if (!link_layer_unicast && port->mac_nat) {
2094 			/* only send through non-MAC-NAT ports */
2095 			continue;
2096 		}
2097 		set_ethernet_address(&eaddr, port->unit, 0);
2098 		payload_len = make_dhcp_payload(&payload, &eaddr);
2099 		if (G_debug) {
2100 			T_LOG("%s: transmit DHCP packet (member %s)",
2101 			    port->ifname, port->member_ifname);
2102 		}
2103 		switch_port_send_udp(port,
2104 		    AF_INET,
2105 		    &eaddr,
2106 		    (union ifbrip *)&ip_src,
2107 		    BOOTP_CLIENT_PORT,
2108 		    ether_dst,
2109 		    (union ifbrip *)&ip_dst,
2110 		    BOOTP_SERVER_PORT,
2111 		    &payload,
2112 		    payload_len);
2113 
2114 		switch_port_list_check_receive(port_list, AF_INET, NULL, 0,
2115 		    validate_mac_nat_dhcp,
2116 		    port);
2117 
2118 		check_received_count(port_list, port, 1);
2119 		if (link_layer_unicast) {
2120 			/* send a single unicast to MAC-NAT interface */
2121 			break;
2122 		}
2123 	}
2124 	T_PASS("%s %s", __func__,
2125 	    link_layer_unicast ? "unicast" : "broadcast");
2126 }
2127 
2128 
2129 static void
validate_mac_nat_nd6(switch_port_t port,const struct icmp6_hdr * icmp6,u_int icmp6_len,uint8_t opt_type,u_int nd_hdr_size,switch_port_t send_port)2130 validate_mac_nat_nd6(switch_port_t port,
2131     const struct icmp6_hdr * icmp6,
2132     u_int icmp6_len,
2133     uint8_t opt_type,
2134     u_int nd_hdr_size,
2135     switch_port_t send_port)
2136 {
2137 	const uint8_t *                 linkaddr;
2138 	const uint8_t *                 ptr;
2139 	const struct nd_opt_hdr *       nd_opt;
2140 	u_int                           nd_size;
2141 
2142 	ptr = (const uint8_t *)icmp6;
2143 	nd_size = nd_hdr_size + LINKADDR_OPT_LEN;
2144 	if (icmp6_len < nd_size) {
2145 		/* no LINKADDR option */
2146 		return;
2147 	}
2148 	nd_opt = (const struct nd_opt_hdr *)(const void *)(ptr + nd_hdr_size);
2149 	T_QUIET;
2150 	T_ASSERT_EQ(nd_opt->nd_opt_type, opt_type,
2151 	    "nd_opt->nd_opt_type 0x%x, opt_type 0x%x",
2152 	    nd_opt->nd_opt_type, opt_type);
2153 	T_QUIET;
2154 	T_ASSERT_EQ(GET_ND_OPT_LEN(nd_opt->nd_opt_len), LINKADDR_OPT_LEN, NULL);
2155 	linkaddr = (const uint8_t *)(nd_opt + 1);
2156 	if (port->mac_nat) {
2157 		bool    equal;
2158 
2159 		equal = (bcmp(linkaddr, &port->member_mac,
2160 		    sizeof(port->member_mac)) == 0);
2161 		T_QUIET;
2162 		T_ASSERT_TRUE(equal, "%s -> %s sender hardware translated",
2163 		    send_port->member_ifname,
2164 		    port->member_ifname);
2165 	} else {
2166 		/* source hw must match the sender */
2167 		T_QUIET;
2168 		T_ASSERT_EQ(linkaddr[EA_UNIT_INDEX], send_port->unit,
2169 		    "%s -> %s unit %u expected %u",
2170 		    send_port->member_ifname,
2171 		    port->member_ifname,
2172 		    linkaddr[EA_UNIT_INDEX], send_port->unit);
2173 	}
2174 }
2175 
2176 static void
validate_mac_nat_icmp6_out(switch_port_t port,const struct icmp6_hdr * icmp6,u_int icmp6_len,switch_port_t send_port)2177 validate_mac_nat_icmp6_out(switch_port_t port, const struct icmp6_hdr * icmp6,
2178     u_int icmp6_len, switch_port_t send_port)
2179 {
2180 	switch (icmp6->icmp6_type) {
2181 	case ND_NEIGHBOR_ADVERT:
2182 		validate_mac_nat_nd6(port, icmp6, icmp6_len,
2183 		    ND_OPT_TARGET_LINKADDR,
2184 		    sizeof(struct nd_neighbor_advert),
2185 		    send_port);
2186 		break;
2187 	case ND_NEIGHBOR_SOLICIT:
2188 		validate_mac_nat_nd6(port, icmp6, icmp6_len,
2189 		    ND_OPT_SOURCE_LINKADDR,
2190 		    sizeof(struct nd_neighbor_solicit),
2191 		    send_port);
2192 		break;
2193 	case ND_ROUTER_SOLICIT:
2194 		validate_mac_nat_nd6(port, icmp6, icmp6_len,
2195 		    ND_OPT_SOURCE_LINKADDR,
2196 		    sizeof(struct nd_router_solicit),
2197 		    send_port);
2198 		break;
2199 	default:
2200 		T_FAIL("Unsupported icmp6 type %d", icmp6->icmp6_type);
2201 		break;
2202 	}
2203 }
2204 
2205 static void
validate_mac_nat_nd6_out(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)2206 validate_mac_nat_nd6_out(switch_port_t port, const ether_header_t * eh_p,
2207     u_int pkt_len, void * context)
2208 {
2209 	const struct icmp6_hdr *        icmp6;
2210 	const struct ip6_hdr *          ip6;
2211 	unsigned int                    payload_length;
2212 	switch_port_t                   send_port = (switch_port_t)context;
2213 
2214 	if (G_debug) {
2215 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
2216 		ethernet_frame_validate(eh_p, pkt_len, true);
2217 	}
2218 	T_QUIET;
2219 	T_ASSERT_EQ(ntohs(eh_p->ether_type), (u_short)ETHERTYPE_IPV6, NULL);
2220 	ip6 = (const struct ip6_hdr *)(const void *)(eh_p + 1);
2221 	icmp6 = (const struct icmp6_hdr *)(const void *)(ip6 + 1);
2222 	T_QUIET;
2223 	T_ASSERT_GE(pkt_len, (u_int)MIN_ICMP6_LEN, NULL);
2224 	T_QUIET;
2225 	T_ASSERT_EQ(ip6->ip6_nxt, IPPROTO_ICMPV6, NULL);
2226 
2227 	/* validate the ethernet header */
2228 	if (port->mac_nat) {
2229 		bool            equal;
2230 
2231 		/* source ethernet must match MAC-NAT interface */
2232 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
2233 		    sizeof(port->member_mac)) == 0);
2234 		if (!equal) {
2235 			ethernet_frame_validate(eh_p, pkt_len, true);
2236 		}
2237 		T_QUIET;
2238 		T_ASSERT_TRUE(equal, "%s -> %s source address translated",
2239 		    send_port->member_ifname,
2240 		    port->member_ifname);
2241 	} else {
2242 		/* source ethernet must match the sender */
2243 		T_QUIET;
2244 		T_ASSERT_EQ(eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit,
2245 		    "%s -> %s unit %u expected %u",
2246 		    send_port->member_ifname,
2247 		    port->member_ifname,
2248 		    eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit);
2249 	}
2250 	/* validate the icmp6 payload */
2251 	payload_length = ntohs(ip6->ip6_plen);
2252 	validate_mac_nat_icmp6_out(port, icmp6, payload_length, send_port);
2253 	port->test_count++;
2254 }
2255 
2256 static void
mac_nat_test_nd6_out(switch_port_list_t port_list)2257 mac_nat_test_nd6_out(switch_port_list_t port_list)
2258 {
2259 	switch_port_t   ext_port;
2260 	u_int           i;
2261 	union ifbrip    ip_dst;
2262 	switch_port_t   port;
2263 
2264 	get_external_ip_address(AF_INET6, &ip_dst);
2265 	ext_port = port_list->list;
2266 	T_QUIET;
2267 	T_ASSERT_TRUE(ext_port->mac_nat, NULL);
2268 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2269 		if (port->mac_nat) {
2270 			continue;
2271 		}
2272 		/* neighbor solicit */
2273 		for (u_int j = 0; j < port->num_addrs; j++) {
2274 			ether_addr_t    eaddr;
2275 			union ifbrip    ip_src;
2276 
2277 			set_ethernet_address(&eaddr, port->unit, j);
2278 			get_ip_address(AF_INET6, port->unit, j, &ip_src);
2279 			switch_port_send_nd6(port,
2280 			    ND_NEIGHBOR_SOLICIT,
2281 			    &eaddr,
2282 			    &ip_src.ifbrip_addr6,
2283 			    NULL,
2284 			    NULL,
2285 			    &ip_dst.ifbrip_addr6);
2286 			switch_port_list_check_receive(port_list, AF_INET,
2287 			    NULL, 0,
2288 			    validate_mac_nat_nd6_out,
2289 			    port);
2290 			check_received_count(port_list, port, 1);
2291 		}
2292 		/* neighbor advert */
2293 		for (u_int j = 0; j < port->num_addrs; j++) {
2294 			ether_addr_t    eaddr;
2295 			union ifbrip    ip_src;
2296 
2297 			set_ethernet_address(&eaddr, port->unit, j);
2298 			get_ip_address(AF_INET6, port->unit, j, &ip_src);
2299 			switch_port_send_nd6(port,
2300 			    ND_NEIGHBOR_ADVERT,
2301 			    &eaddr,
2302 			    &ip_src.ifbrip_addr6,
2303 			    NULL,
2304 			    &eaddr,
2305 			    &ip_src.ifbrip_addr6);
2306 			switch_port_list_check_receive(port_list, AF_INET,
2307 			    NULL, 0,
2308 			    validate_mac_nat_nd6_out,
2309 			    port);
2310 			check_received_count(port_list, port, 1);
2311 		}
2312 		/* router solicit */
2313 		for (u_int j = 0; j < port->num_addrs; j++) {
2314 			ether_addr_t    eaddr;
2315 			union ifbrip    ip_src;
2316 
2317 			set_ethernet_address(&eaddr, port->unit, j);
2318 			get_ip_address(AF_INET6, port->unit, j, &ip_src);
2319 			//get_ipv6ll_address(port->unit, j, &ip_src.ifbrip_addr6);
2320 			switch_port_send_nd6(port,
2321 			    ND_ROUTER_SOLICIT,
2322 			    &eaddr,
2323 			    &ip_src.ifbrip_addr6,
2324 			    NULL,
2325 			    NULL,
2326 			    NULL);
2327 			switch_port_list_check_receive(port_list, AF_INET,
2328 			    NULL, 0,
2329 			    validate_mac_nat_nd6_out,
2330 			    port);
2331 			check_received_count(port_list, port, 1);
2332 		}
2333 	}
2334 	T_PASS("%s", __func__);
2335 }
2336 
2337 static void
mac_nat_send_response(switch_port_t ext_port,uint8_t af,switch_port_t port)2338 mac_nat_send_response(switch_port_t ext_port, uint8_t af, switch_port_t port)
2339 {
2340 	union ifbrip    src_ip;
2341 
2342 	T_QUIET;
2343 	T_ASSERT_TRUE(ext_port->mac_nat, "%s is MAC-NAT interface",
2344 	    ext_port->member_ifname);
2345 	if (G_debug) {
2346 		T_LOG("Generating UDP traffic destined to %s", port->ifname);
2347 	}
2348 	get_external_ip_address(af, &src_ip);
2349 	for (u_int j = 0; j < port->num_addrs; j++) {
2350 		union ifbrip    ip;
2351 
2352 		get_ip_address(af, port->unit, j, &ip);
2353 		switch_port_send_udp(ext_port,
2354 		    af,
2355 		    &ether_external,
2356 		    &src_ip,
2357 		    TEST_DEST_PORT,
2358 		    &ext_port->member_mac,
2359 		    &ip,
2360 		    TEST_SOURCE_PORT,
2361 		    NULL, 0);
2362 	}
2363 }
2364 
2365 
2366 static void
mac_nat_test_ip_once(switch_port_list_t port_list,uint8_t af,bool retry)2367 mac_nat_test_ip_once(switch_port_list_t port_list, uint8_t af, bool retry)
2368 {
2369 	union ifbrip    dst_ip;
2370 	u_int           i;
2371 	switch_port_t   port;
2372 
2373 	get_external_ip_address(af, &dst_ip);
2374 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2375 		if (port->test_address_count == port->num_addrs) {
2376 			/* already populated */
2377 			continue;
2378 		}
2379 		if (G_debug) {
2380 			T_LOG("Sending on %s", port->ifname);
2381 		}
2382 		for (u_int j = 0; j < port->num_addrs; j++) {
2383 			uint32_t        generation;
2384 
2385 			if (retry) {
2386 				uint64_t        addr_bit;
2387 
2388 				addr_bit = 1 << j;
2389 				if ((port->test_address_present & addr_bit)
2390 				    != 0) {
2391 					/* already present */
2392 					continue;
2393 				}
2394 				T_LOG("Retry port %s unit %u address %u",
2395 				    port->ifname, port->unit, j);
2396 			}
2397 
2398 			generation = next_generation();
2399 			send_generation(port,
2400 			    af,
2401 			    j,
2402 			    &ether_external,
2403 			    &dst_ip,
2404 			    generation);
2405 
2406 			/* receive across all ports */
2407 			check_receive_generation(port_list,
2408 			    af,
2409 			    generation,
2410 			    validate_mac_nat,
2411 			    NULL);
2412 
2413 			/* ensure that every port saw the packet */
2414 			check_received_count(port_list, port, 1);
2415 		}
2416 	}
2417 	return;
2418 }
2419 
2420 static void
mac_nat_test_ip(switch_port_list_t port_list,uint8_t af)2421 mac_nat_test_ip(switch_port_list_t port_list, uint8_t af)
2422 {
2423 	u_int           i;
2424 	switch_port_t   port;
2425 	bool            verified = false;
2426 
2427 	/*
2428 	 * Send a packet from every port in the list so that the bridge
2429 	 * learns the MAC addresses and IP addresses.
2430 	 */
2431 #define MAC_NAT_MAX_TRIES               20
2432 	for (int try = 1; try < BROADCAST_MAX_TRIES; try++) {
2433 		bool    retry = (try > 1);
2434 
2435 		if (!retry) {
2436 			T_LOG("%s: #ports %u #addrs %u",
2437 			    __func__,
2438 			    port_list->count, port_list->list->num_addrs);
2439 		} else {
2440 			T_LOG("%s: #ports %u #addrs %u destination (TRY=%d)",
2441 			    __func__,
2442 			    port_list->count, port_list->list->num_addrs,
2443 			    try);
2444 		}
2445 		mac_nat_test_ip_once(port_list, af, retry);
2446 		/*
2447 		 * In the event of a memory allocation failure, it's possible
2448 		 * that the address was not learned. Figure out whether
2449 		 * all addresses are present, and if not, we'll retry on
2450 		 * those that are not present.
2451 		 */
2452 		verified = switch_port_list_verify_mac_nat(port_list, false);
2453 		if (verified) {
2454 			break;
2455 		}
2456 		/* wait a short time to allow the system to recover */
2457 		usleep(100 * 1000);
2458 	}
2459 	T_QUIET;
2460 	T_ASSERT_TRUE(verified, "All addresses present");
2461 
2462 	/*
2463 	 * The bridge now has an IP address <-> MAC address binding for every
2464 	 * address on each internal interface.
2465 	 *
2466 	 * Generate an inbound packet on the MAC-NAT interface targeting
2467 	 * each interface address. Verify that the packet appears on
2468 	 * the appropriate internal address with appropriate translation.
2469 	 */
2470 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2471 		if (port->mac_nat) {
2472 			continue;
2473 		}
2474 		mac_nat_send_response(port_list->list, af, port);
2475 
2476 		/* receive the generated traffic */
2477 		switch_port_list_check_receive(port_list, AF_INET, NULL, 0,
2478 		    validate_mac_nat_in,
2479 		    NULL);
2480 
2481 		/* verify that only the single port got the packet */
2482 		mac_nat_check_received_count(port_list, port);
2483 	}
2484 	T_PASS("%s", __func__);
2485 }
2486 
2487 /**
2488 ** interface management
2489 **/
2490 
2491 static int
bridge_delete_member(const char * bridge,const char * member)2492 bridge_delete_member(const char * bridge, const char * member)
2493 {
2494 	struct ifbreq           req;
2495 	int                     ret;
2496 
2497 	memset(&req, 0, sizeof(req));
2498 	strlcpy(req.ifbr_ifsname, member, sizeof(req.ifbr_ifsname));
2499 	ret = siocdrvspec(bridge, BRDGDEL, &req, sizeof(req), true);
2500 	T_QUIET;
2501 	T_ASSERT_POSIX_SUCCESS(ret, "%s %s %s", __func__, bridge, member);
2502 	return ret;
2503 }
2504 
2505 
2506 static int
bridge_member_modify_ifflags(const char * bridge,const char * member,uint32_t flags_to_modify,bool set)2507 bridge_member_modify_ifflags(const char * bridge, const char * member,
2508     uint32_t flags_to_modify, bool set)
2509 {
2510 	uint32_t        flags;
2511 	bool            need_set = false;
2512 	struct ifbreq   req;
2513 	int             ret;
2514 
2515 	memset(&req, 0, sizeof(req));
2516 	strlcpy(req.ifbr_ifsname, member, sizeof(req.ifbr_ifsname));
2517 	ret = siocdrvspec(bridge, BRDGGIFFLGS, &req, sizeof(req), false);
2518 	T_QUIET;
2519 	T_ASSERT_POSIX_SUCCESS(ret, "BRDGGIFFLGS %s %s", bridge, member);
2520 	flags = req.ifbr_ifsflags;
2521 	if (set) {
2522 		if ((flags & flags_to_modify) != flags_to_modify) {
2523 			need_set = true;
2524 			req.ifbr_ifsflags |= flags_to_modify;
2525 		}
2526 		/* need to set it */
2527 	} else if ((flags & flags_to_modify) != 0) {
2528 		/* need to clear it */
2529 		need_set = true;
2530 		req.ifbr_ifsflags &= ~flags_to_modify;
2531 	}
2532 	if (need_set) {
2533 		ret = siocdrvspec(bridge, BRDGSIFFLGS,
2534 		    &req, sizeof(req), true);
2535 		T_QUIET;
2536 		T_ASSERT_POSIX_SUCCESS(ret, "BRDGSIFFLGS %s %s 0x%x => 0x%x",
2537 		    bridge, member,
2538 		    flags, req.ifbr_ifsflags);
2539 	}
2540 	return ret;
2541 }
2542 
2543 static int
bridge_member_modify_mac_nat(const char * bridge,const char * member,bool enable)2544 bridge_member_modify_mac_nat(const char * bridge,
2545     const char * member, bool enable)
2546 {
2547 	return bridge_member_modify_ifflags(bridge, member,
2548 	           IFBIF_MAC_NAT,
2549 	           enable);
2550 }
2551 
2552 static int
bridge_member_modify_checksum_offload(const char * bridge,const char * member,bool enable)2553 bridge_member_modify_checksum_offload(const char * bridge,
2554     const char * member, bool enable)
2555 {
2556 #ifndef IFBIF_CHECKSUM_OFFLOAD
2557 #define IFBIF_CHECKSUM_OFFLOAD  0x10000 /* checksum inbound packets,
2558 	                                 * drop outbound packets with
2559 	                                 * bad checksum
2560 	                                 */
2561 #endif
2562 	return bridge_member_modify_ifflags(bridge, member,
2563 	           IFBIF_CHECKSUM_OFFLOAD,
2564 	           enable);
2565 }
2566 
2567 static struct ifbareq *
bridge_rt_table_copy_common(const char * bridge,u_int * ret_count)2568 bridge_rt_table_copy_common(const char * bridge, u_int * ret_count)
2569 {
2570 	struct ifbaconf         ifbac;
2571 	u_int                   len = 8 * 1024;
2572 	char *                  inbuf = NULL;
2573 	char *                  ninbuf;
2574 	int                     ret;
2575 	struct ifbareq *        rt_table = NULL;
2576 
2577 	/*
2578 	 * BRDGRTS should work like other ioctl's where passing in NULL
2579 	 * for the buffer says "tell me how many there are". Unfortunately,
2580 	 * it doesn't so we have to pass in a buffer, then check that it
2581 	 * was too big.
2582 	 */
2583 	for (;;) {
2584 		ninbuf = realloc(inbuf, len);
2585 		T_QUIET;
2586 		T_ASSERT_NOTNULL((void *)ninbuf, "realloc %u", len);
2587 		ifbac.ifbac_len = len;
2588 		ifbac.ifbac_buf = inbuf = ninbuf;
2589 		ret = siocdrvspec(bridge, BRDGRTS,
2590 		    &ifbac, sizeof(ifbac), false);
2591 		T_QUIET;
2592 		T_ASSERT_POSIX_SUCCESS(ret, "%s %s", __func__, bridge);
2593 		if ((ifbac.ifbac_len + sizeof(*rt_table)) < len) {
2594 			/* we passed a buffer larger than what was required */
2595 			break;
2596 		}
2597 		len *= 2;
2598 	}
2599 	if (ifbac.ifbac_len == 0) {
2600 		free(ninbuf);
2601 		T_LOG("No bridge routing entries");
2602 		goto done;
2603 	}
2604 	*ret_count = ifbac.ifbac_len / sizeof(*rt_table);
2605 	rt_table = (struct ifbareq *)(void *)ninbuf;
2606 done:
2607 	if (rt_table == NULL) {
2608 		*ret_count = 0;
2609 	}
2610 	return rt_table;
2611 }
2612 
2613 static struct ifbareq *
bridge_rt_table_copy(u_int * ret_count)2614 bridge_rt_table_copy(u_int * ret_count)
2615 {
2616 	return bridge_rt_table_copy_common(BRIDGE200, ret_count);
2617 }
2618 
2619 static void
bridge_rt_table_log(struct ifbareq * rt_table,u_int count)2620 bridge_rt_table_log(struct ifbareq *rt_table, u_int count)
2621 {
2622 	u_int                   i;
2623 	char                    ntoabuf[ETHER_NTOA_BUFSIZE];
2624 	struct ifbareq *        ifba;
2625 
2626 	for (i = 0, ifba = rt_table; i < count; i++, ifba++) {
2627 		ether_ntoa_buf((const ether_addr_t *)&ifba->ifba_dst,
2628 		    ntoabuf, sizeof(ntoabuf));
2629 		T_LOG("%s %s %lu", ifba->ifba_ifsname, ntoabuf,
2630 		    ifba->ifba_expire);
2631 	}
2632 	return;
2633 }
2634 
2635 static struct ifbrmne *
bridge_mac_nat_entries_copy_common(const char * bridge,u_int * ret_count)2636 bridge_mac_nat_entries_copy_common(const char * bridge, u_int * ret_count)
2637 {
2638 	char *                  buf = NULL;
2639 	u_int                   count = 0;
2640 	int                     err;
2641 	u_int                   i;
2642 	struct ifbrmnelist      mnl;
2643 	struct ifbrmne *        ret_list = NULL;
2644 	char *                  scan;
2645 
2646 	/* find out how many there are */
2647 	bzero(&mnl, sizeof(mnl));
2648 	err = siocdrvspec(bridge, BRDGGMACNATLIST, &mnl, sizeof(mnl), false);
2649 	if (err != 0 && S_cleaning_up) {
2650 		T_LOG("BRDGGMACNATLIST %s failed %d", bridge, errno);
2651 		goto done;
2652 	}
2653 	T_QUIET;
2654 	T_ASSERT_POSIX_SUCCESS(err, "BRDGGMACNATLIST %s", bridge);
2655 	T_QUIET;
2656 	T_ASSERT_GE(mnl.ifbml_elsize, (uint16_t)sizeof(struct ifbrmne),
2657 	    "mac nat entry size %u minsize %u",
2658 	    mnl.ifbml_elsize, (u_int)sizeof(struct ifbrmne));
2659 	if (mnl.ifbml_len == 0) {
2660 		goto done;
2661 	}
2662 
2663 	/* call again with a buffer large enough to hold them */
2664 	buf = malloc(mnl.ifbml_len);
2665 	T_QUIET;
2666 	T_ASSERT_NOTNULL(buf, "mac nat entries buffer");
2667 	mnl.ifbml_buf = buf;
2668 	err = siocdrvspec(bridge, BRDGGMACNATLIST, &mnl, sizeof(mnl), false);
2669 	T_QUIET;
2670 	T_ASSERT_POSIX_SUCCESS(err, "BRDGGMACNATLIST %s", bridge);
2671 	count = mnl.ifbml_len / mnl.ifbml_elsize;
2672 	if (count == 0) {
2673 		goto done;
2674 	}
2675 	if (mnl.ifbml_elsize == sizeof(struct ifbrmne)) {
2676 		/* element size is expected size, no need to "right-size" it */
2677 		ret_list = (struct ifbrmne *)(void *)buf;
2678 		buf = NULL;
2679 		goto done;
2680 	}
2681 	/* element size is larger than we expect, create a "right-sized" array */
2682 	ret_list = malloc(count * sizeof(*ret_list));
2683 	T_QUIET;
2684 	T_ASSERT_NOTNULL(ret_list, "mac nat entries list");
2685 	for (i = 0, scan = buf; i < count; i++, scan += mnl.ifbml_elsize) {
2686 		struct ifbrmne *        ifbmne;
2687 
2688 		ifbmne = (struct ifbrmne *)(void *)scan;
2689 		ret_list[i] = *ifbmne;
2690 	}
2691 done:
2692 	if (buf != NULL) {
2693 		free(buf);
2694 	}
2695 	*ret_count = count;
2696 	return ret_list;
2697 }
2698 
2699 static struct ifbrmne *
bridge_mac_nat_entries_copy(u_int * ret_count)2700 bridge_mac_nat_entries_copy(u_int * ret_count)
2701 {
2702 	return bridge_mac_nat_entries_copy_common(BRIDGE200, ret_count);
2703 }
2704 
2705 static void
bridge_mac_nat_entries_log(struct ifbrmne * entries,u_int count)2706 bridge_mac_nat_entries_log(struct ifbrmne * entries, u_int count)
2707 {
2708 	u_int                   i;
2709 	char                    ntoabuf[ETHER_NTOA_BUFSIZE];
2710 	char                    ntopbuf[INET6_ADDRSTRLEN];
2711 	struct ifbrmne *        scan;
2712 
2713 	for (i = 0, scan = entries; i < count; i++, scan++) {
2714 		ether_ntoa_buf((const ether_addr_t *)&scan->ifbmne_mac,
2715 		    ntoabuf, sizeof(ntoabuf));
2716 		inet_ntop(scan->ifbmne_af, &scan->ifbmne_ip,
2717 		    ntopbuf, sizeof(ntopbuf));
2718 		printf("%s %s %s %lu\n",
2719 		    scan->ifbmne_ifname, ntopbuf, ntoabuf,
2720 		    (unsigned long)scan->ifbmne_expire);
2721 	}
2722 	return;
2723 }
2724 
2725 /**
2726 ** Test Main
2727 **/
2728 static u_int                    S_n_ports;
2729 static switch_port_list_t       S_port_list;
2730 
2731 static void
2732 bridge_cleanup(const char * bridge, u_int n_ports, bool fail_on_error);
2733 
2734 static int fake_bsd_mode;
2735 static int fake_fcs;
2736 static int fake_trailer_length;
2737 static int fake_nxattach;
2738 
2739 static void
fake_set_trailers_fcs(bool enable)2740 fake_set_trailers_fcs(bool enable)
2741 {
2742 	int     error;
2743 	int     fcs;
2744 	size_t  len;
2745 	int     trailer_length;
2746 
2747 	if (enable) {
2748 		fcs = 1;
2749 		trailer_length = 28;
2750 	} else {
2751 		fcs = 0;
2752 		trailer_length = 0;
2753 	}
2754 
2755 	/* set fcs */
2756 	len = sizeof(fake_fcs);
2757 	error = sysctlbyname("net.link.fake.fcs",
2758 	    &fake_fcs, &len,
2759 	    &fcs, sizeof(fcs));
2760 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.fcs %d", fcs);
2761 
2762 	/* set trailer_length */
2763 	len = sizeof(fake_trailer_length);
2764 	error = sysctlbyname("net.link.fake.trailer_length",
2765 	    &fake_trailer_length, &len,
2766 	    &trailer_length, sizeof(trailer_length));
2767 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.trailer_length %d",
2768 	    trailer_length);
2769 }
2770 
2771 static void
fake_restore_trailers_fcs(void)2772 fake_restore_trailers_fcs(void)
2773 {
2774 	int     error;
2775 
2776 	error = sysctlbyname("net.link.fake.fcs",
2777 	    NULL, 0, &fake_fcs, sizeof(fake_fcs));
2778 	T_LOG("sysctl net.link.fake.fcs=%d returned %d", fake_fcs, error);
2779 	error = sysctlbyname("net.link.fake.trailer_length",
2780 	    NULL, 0, &fake_trailer_length, sizeof(fake_trailer_length));
2781 	T_LOG("sysctl net.link.fake.trailer_length=%d returned %d",
2782 	    fake_trailer_length, error);
2783 }
2784 
2785 static void
fake_set_bsd_mode(bool enable)2786 fake_set_bsd_mode(bool enable)
2787 {
2788 	int     error;
2789 	int     bsd_mode;
2790 	size_t  len;
2791 
2792 	bsd_mode = (enable) ? 1 : 0;
2793 	len = sizeof(fake_bsd_mode);
2794 	error = sysctlbyname("net.link.fake.bsd_mode",
2795 	    &fake_bsd_mode, &len,
2796 	    &bsd_mode, sizeof(bsd_mode));
2797 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.bsd_mode %d", bsd_mode);
2798 }
2799 
2800 static void
fake_restore_bsd_mode(void)2801 fake_restore_bsd_mode(void)
2802 {
2803 	int     error;
2804 
2805 	error = sysctlbyname("net.link.fake.bsd_mode",
2806 	    NULL, 0, &fake_bsd_mode, sizeof(fake_bsd_mode));
2807 	T_LOG("sysctl net.link.fake.bsd_mode=%d returned %d",
2808 	    fake_bsd_mode, error);
2809 }
2810 
2811 static void
fake_set_nxattach(bool enable)2812 fake_set_nxattach(bool enable)
2813 {
2814 	int     error;
2815 	int     nxattach;
2816 	size_t  len;
2817 
2818 	nxattach = (enable) ? 1 : 0;
2819 	len = sizeof(fake_nxattach);
2820 	error = sysctlbyname("net.link.fake.nxattach",
2821 	    &fake_nxattach, &len,
2822 	    &nxattach, sizeof(nxattach));
2823 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.nxattach %d", nxattach);
2824 }
2825 
2826 static void
fake_restore_nxattach(void)2827 fake_restore_nxattach(void)
2828 {
2829 	int     error;
2830 
2831 	error = sysctlbyname("net.link.fake.nxattach",
2832 	    NULL, 0, &fake_nxattach, sizeof(fake_nxattach));
2833 	T_LOG("sysctl net.link.fake.nxatach=%d returned %d",
2834 	    fake_nxattach, error);
2835 }
2836 
2837 static void
fake_set_lro(bool enable)2838 fake_set_lro(bool enable)
2839 {
2840 	int     error;
2841 	int     lro;
2842 
2843 	lro = (enable) ? 1 : 0;
2844 	error = sysctlbyname("net.link.fake.lro", NULL, 0,
2845 	    &lro, sizeof(lro));
2846 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.lro %d", lro);
2847 }
2848 
2849 static void
cleanup_common(bool dump_table)2850 cleanup_common(bool dump_table)
2851 {
2852 	if (S_n_ports == 0) {
2853 		return;
2854 	}
2855 	S_cleaning_up = true;
2856 	if (S_port_list != NULL &&
2857 	    (S_port_list->mac_nat || dump_table)) {
2858 		switch_port_list_log(S_port_list);
2859 		if (S_port_list->mac_nat) {
2860 			switch_port_list_verify_mac_nat(S_port_list, true);
2861 		}
2862 		(void)switch_port_list_verify_rt_table(S_port_list, true);
2863 	}
2864 	if (G_debug) {
2865 		T_LOG("sleeping for 5 seconds\n");
2866 		sleep(5);
2867 	}
2868 	bridge_cleanup(BRIDGE200, S_n_ports, false);
2869 	return;
2870 }
2871 
2872 static void
cleanup(void)2873 cleanup(void)
2874 {
2875 	cleanup_common(true);
2876 	return;
2877 }
2878 
2879 static void
sigint_handler(__unused int sig)2880 sigint_handler(__unused int sig)
2881 {
2882 	cleanup_common(false);
2883 	signal(SIGINT, SIG_DFL);
2884 }
2885 
2886 static switch_port_list_t
bridge_setup(char * bridge,u_int n_ports,u_int num_addrs,uint8_t setup_flags)2887 bridge_setup(char * bridge, u_int n_ports, u_int num_addrs,
2888     uint8_t setup_flags)
2889 {
2890 	u_int                   addr_index = 1;
2891 	bool                    attach_stack;
2892 	ether_addr_t            bridge_mac;
2893 	bool                    checksum_offload;
2894 	errno_t                 err;
2895 	struct in_addr          ip;
2896 	switch_port_list_t      list = NULL;
2897 	bool                    mac_nat;
2898 	bool                    share_member_mac = false;
2899 	uint8_t                 trailers;
2900 
2901 	attach_stack = (setup_flags & SETUP_FLAGS_ATTACH_STACK) != 0;
2902 	checksum_offload = (setup_flags & SETUP_FLAGS_CHECKSUM_OFFLOAD) != 0;
2903 	mac_nat = (setup_flags & SETUP_FLAGS_MAC_NAT) != 0;
2904 	trailers = (setup_flags & SETUP_FLAGS_TRAILERS) != 0;
2905 	share_member_mac = (setup_flags & SETUP_FLAGS_SHARE_MEMBER_MAC) != 0;
2906 
2907 	S_n_ports = n_ports;
2908 	T_ATEND(cleanup);
2909 	T_SETUPBEGIN;
2910 	err = ifnet_create(bridge);
2911 	if (err != 0) {
2912 		goto done;
2913 	}
2914 	ifnet_get_lladdr(bridge, &bridge_mac);
2915 	bridge_if_index = (u_short)if_nametoindex(bridge);
2916 	if (attach_stack) {
2917 		char            ntopbuf_ip[INET6_ADDRSTRLEN];
2918 
2919 		/* bridge gets .1 */
2920 		get_ipv4_address(0, addr_index, &bridge_ip_addr);
2921 		addr_index++;
2922 		ifnet_add_ip_address(bridge, bridge_ip_addr,
2923 		    inet_class_c_subnet_mask);
2924 		ifnet_start_ipv6(bridge);
2925 		get_ipv6_ll_address(&bridge_mac, &bridge_ipv6_addr);
2926 		inet_ntop(AF_INET6, &bridge_ipv6_addr, ntopbuf_ip,
2927 		    sizeof(ntopbuf_ip));
2928 		T_LOG("%s %s", bridge, ntopbuf_ip);
2929 	}
2930 	list = switch_port_list_alloc(n_ports, mac_nat);
2931 	fake_set_bsd_mode(true);
2932 	fake_set_nxattach(false);
2933 	fake_set_trailers_fcs(trailers);
2934 	for (u_int i = 0; i < n_ports; i++) {
2935 		bool    do_mac_nat;
2936 		char    ifname[IFNAMSIZ];
2937 		u_short if_index = 0;
2938 		char    member_ifname[IFNAMSIZ];
2939 
2940 		snprintf(ifname, sizeof(ifname), "%s%d",
2941 		    FETH_NAME, i);
2942 		snprintf(member_ifname, sizeof(member_ifname), "%s%d",
2943 		    FETH_NAME, i + n_ports);
2944 		err = ifnet_create(ifname);
2945 		if (err != 0) {
2946 			goto done;
2947 		}
2948 		ifnet_attach_ip(ifname);
2949 		err = ifnet_create(member_ifname);
2950 		if (err != 0) {
2951 			goto done;
2952 		}
2953 		if (i == 0 && share_member_mac) {
2954 			err = ifnet_set_lladdr(member_ifname, &bridge_mac);
2955 			if (err != 0) {
2956 				goto done;
2957 			}
2958 		}
2959 		fake_set_peer(ifname, member_ifname);
2960 		if (attach_stack) {
2961 			/* members get .2, .3, etc. */
2962 			if_index = (u_short)if_nametoindex(ifname);
2963 			get_ipv4_address(0, addr_index, &ip);
2964 			ifnet_add_ip_address(ifname, ip,
2965 			    inet_class_c_subnet_mask);
2966 			route_add_inet_scoped_subnet(ifname, if_index,
2967 			    ip, inet_class_c_subnet_mask);
2968 			addr_index++;
2969 			ifnet_start_ipv6(ifname);
2970 		}
2971 		/* add the interface's peer to the bridge */
2972 		err = bridge_add_member(bridge, member_ifname);
2973 		if (err != 0) {
2974 			goto done;
2975 		}
2976 
2977 		do_mac_nat = (i == 0 && mac_nat);
2978 		if (do_mac_nat) {
2979 			/* enable MAC NAT on unit 0 */
2980 			err = bridge_member_modify_mac_nat(bridge,
2981 			    member_ifname,
2982 			    true);
2983 			if (err != 0) {
2984 				goto done;
2985 			}
2986 		} else if (checksum_offload) {
2987 			err = bridge_member_modify_checksum_offload(bridge,
2988 			    member_ifname,
2989 			    true);
2990 			if (err != 0) {
2991 				goto done;
2992 			}
2993 		}
2994 		/* we'll send/receive on the interface */
2995 		err = switch_port_list_add_port(list, i, ifname, if_index,
2996 		    member_ifname, num_addrs, do_mac_nat, attach_stack, &ip);
2997 		if (err != 0) {
2998 			goto done;
2999 		}
3000 	}
3001 done:
3002 	if (err != 0 && list != NULL) {
3003 		switch_port_list_dealloc(list);
3004 		list = NULL;
3005 	}
3006 	T_SETUPEND;
3007 	return list;
3008 }
3009 
3010 static void
bridge_cleanup(const char * bridge,u_int n_ports,bool fail_on_error)3011 bridge_cleanup(const char * bridge, u_int n_ports, bool fail_on_error)
3012 {
3013 	ifnet_destroy(bridge, fail_on_error);
3014 	for (u_int i = 0; i < n_ports; i++) {
3015 		char    ifname[IFNAMSIZ];
3016 		char    member_ifname[IFNAMSIZ];
3017 
3018 		snprintf(ifname, sizeof(ifname), "%s%d",
3019 		    FETH_NAME, i);
3020 		snprintf(member_ifname, sizeof(member_ifname), "%s%d",
3021 		    FETH_NAME, i + n_ports);
3022 		ifnet_destroy(ifname, fail_on_error);
3023 		ifnet_destroy(member_ifname, fail_on_error);
3024 	}
3025 	S_n_ports = 0;
3026 	fake_restore_trailers_fcs();
3027 	fake_restore_bsd_mode();
3028 	fake_restore_nxattach();
3029 	return;
3030 }
3031 
3032 /*
3033  *  Basic Bridge Tests
3034  *
3035  *  Broadcast
3036  *  - two cases: actual broadcast, unknown ethernet
3037  *  - send broadcast packets
3038  *  - verify all received
3039  *  - check bridge rt list contains all expected MAC addresses
3040  *  - send unicast ARP packets
3041  *  - verify packets received only on expected port
3042  *
3043  *  MAC-NAT
3044  *  - verify ARP translation
3045  *  - verify IPv4 translation
3046  *  - verify DHCP broadcast bit conversion
3047  *  - verify IPv6 translation
3048  *  - verify ND6 translation (Neighbor, Router)
3049  *  - verify IPv4 subnet-local broadcast to MAC-NAT interface link-layer
3050  *    address arrives on all member links
3051  */
3052 
3053 static void
bridge_test(packet_validator_t validator,void * context,const ether_addr_t * dst_eaddr,uint8_t af,u_int n_ports,u_int num_addrs)3054 bridge_test(packet_validator_t validator,
3055     void * context,
3056     const ether_addr_t * dst_eaddr,
3057     uint8_t af, u_int n_ports, u_int num_addrs)
3058 {
3059 #if TARGET_OS_BRIDGE
3060 	T_SKIP("Test uses too much memory");
3061 #else /* TARGET_OS_BRIDGE */
3062 	switch_port_list_t port_list;
3063 
3064 	signal(SIGINT, sigint_handler);
3065 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs, 0);
3066 	if (port_list == NULL) {
3067 		T_FAIL("bridge_setup");
3068 		return;
3069 	}
3070 	S_port_list = port_list;
3071 	bridge_learning_test(port_list, af, validator, context, dst_eaddr);
3072 
3073 	//T_LOG("Sleeping for 5 seconds");
3074 	//sleep(5);
3075 	bridge_cleanup(BRIDGE200, n_ports, true);
3076 	switch_port_list_dealloc(port_list);
3077 	return;
3078 #endif /* TARGET_OS_BRIDGE */
3079 }
3080 
3081 static void
bridge_test_mac_nat_ipv4(u_int n_ports,u_int num_addrs)3082 bridge_test_mac_nat_ipv4(u_int n_ports, u_int num_addrs)
3083 {
3084 #if TARGET_OS_BRIDGE
3085 	T_SKIP("Test uses too much memory");
3086 #else /* TARGET_OS_BRIDGE */
3087 	switch_port_list_t port_list;
3088 
3089 	signal(SIGINT, sigint_handler);
3090 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs,
3091 	    SETUP_FLAGS_MAC_NAT);
3092 	if (port_list == NULL) {
3093 		T_FAIL("bridge_setup");
3094 		return;
3095 	}
3096 	S_port_list = port_list;
3097 
3098 	/* verify that IPv4 packets get translated when necessary */
3099 	mac_nat_test_ip(port_list, AF_INET);
3100 
3101 	/* verify the DHCP broadcast bit gets set appropriately */
3102 	mac_nat_test_dhcp(port_list, false);
3103 
3104 	/* verify that ARP packet gets translated when necessary */
3105 	mac_nat_test_arp_out(port_list);
3106 	mac_nat_test_arp_in(port_list);
3107 
3108 	/* verify IP broadcast to MAC-NAT interface link layer address */
3109 	mac_nat_test_dhcp(port_list, true);
3110 
3111 	if (G_debug) {
3112 		T_LOG("Sleeping for 5 seconds");
3113 		sleep(5);
3114 	}
3115 	bridge_cleanup(BRIDGE200, n_ports, true);
3116 	switch_port_list_dealloc(port_list);
3117 	return;
3118 #endif /* TARGET_OS_BRIDGE */
3119 }
3120 
3121 static void
bridge_test_mac_nat_ipv6(u_int n_ports,u_int num_addrs,uint8_t flags)3122 bridge_test_mac_nat_ipv6(u_int n_ports, u_int num_addrs, uint8_t flags)
3123 {
3124 #if TARGET_OS_BRIDGE
3125 	T_SKIP("Test uses too much memory");
3126 #else /* TARGET_OS_BRIDGE */
3127 	switch_port_list_t port_list;
3128 
3129 	signal(SIGINT, sigint_handler);
3130 	flags |= SETUP_FLAGS_MAC_NAT;
3131 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs, flags);
3132 	if (port_list == NULL) {
3133 		T_FAIL("bridge_setup");
3134 		return;
3135 	}
3136 	S_port_list = port_list;
3137 
3138 	/* verify that IPv6 packets get translated when necessary */
3139 	mac_nat_test_ip(port_list, AF_INET6);
3140 
3141 	/* verify that ND6 packet gets translated when necessary */
3142 	mac_nat_test_nd6_out(port_list);
3143 	if (G_debug) {
3144 		T_LOG("Sleeping for 5 seconds");
3145 		sleep(5);
3146 	}
3147 	bridge_cleanup(BRIDGE200, n_ports, true);
3148 	switch_port_list_dealloc(port_list);
3149 	return;
3150 #endif /* TARGET_OS_BRIDGE */
3151 }
3152 
3153 /*
3154  * Filter test utilities
3155  */
3156 static void
system_cmd(const char * cmd,bool fail_on_error)3157 system_cmd(const char *cmd, bool fail_on_error)
3158 {
3159 	pid_t pid = -1;
3160 	int exit_status = 0;
3161 	const char *argv[] = {
3162 		"/usr/local/bin/bash",
3163 		"-c",
3164 		cmd,
3165 		NULL
3166 	};
3167 
3168 	int rc = dt_launch_tool(&pid, (char **)(void *)argv, false, NULL, NULL);
3169 	T_QUIET;
3170 	T_ASSERT_EQ(rc, 0, "dt_launch_tool(%s) failed", cmd);
3171 
3172 	if (dt_waitpid(pid, &exit_status, NULL, 30)) {
3173 		T_QUIET;
3174 		T_ASSERT_MACH_SUCCESS(exit_status, "command(%s)", cmd);
3175 	} else {
3176 		if (fail_on_error) {
3177 			T_FAIL("dt_waitpid(%s) failed", cmd);
3178 		}
3179 	}
3180 }
3181 
3182 static bool
executable_is_present(const char * path)3183 executable_is_present(const char * path)
3184 {
3185 	struct stat statb = { 0 };
3186 
3187 	return stat(path, &statb) == 0 && (statb.st_mode & S_IXUSR) != 0;
3188 }
3189 
3190 static void
cleanup_pf(void)3191 cleanup_pf(void)
3192 {
3193 	struct ifbrparam param;
3194 
3195 	system_cmd("pfctl -d", false);
3196 	system_cmd("pfctl -F all", false);
3197 
3198 	param.ifbrp_filter = 0;
3199 	siocdrvspec(BRIDGE200, BRDGSFILT,
3200 	    &param, sizeof(param), true);
3201 	return;
3202 }
3203 
3204 static void
block_all_traffic(bool input,const char * infname1,const char * infname2)3205 block_all_traffic(bool input, const char* infname1, const char* infname2)
3206 {
3207 	int ret;
3208 	struct ifbrparam param;
3209 	char command[512];
3210 	char *dir = input ? "in" : "out";
3211 
3212 	snprintf(command, sizeof(command),
3213 	    "echo \"block %s log on %s all\n"
3214 	    "block %s log on %s all\n\" | pfctl -vvv -f -",
3215 	    dir, infname1, dir, infname2);
3216 	/* enable block all filter */
3217 	param.ifbrp_filter = IFBF_FILT_MEMBER | IFBF_FILT_ONLYIP;
3218 	ret = siocdrvspec(BRIDGE200, BRDGSFILT,
3219 	    &param, sizeof(param), true);
3220 	T_ASSERT_POSIX_SUCCESS(ret,
3221 	    "SIOCDRVSPEC(BRDGSFILT %s, 0x%x)",
3222 	    BRIDGE200, param.ifbrp_filter);
3223 	// ignore errors such that not having pf.os doesn't raise any issues
3224 	system_cmd(command, false);
3225 	system_cmd("pfctl -e", true);
3226 	system_cmd("pfctl -s all", true);
3227 }
3228 
3229 /*
3230  *  Basic bridge filter test
3231  *
3232  *  For both broadcast and unicast transfers ensure that data can
3233  *  be blocked using pf on the bridge
3234  */
3235 
3236 static void
filter_test(uint8_t af)3237 filter_test(uint8_t af)
3238 {
3239 #if TARGET_OS_BRIDGE
3240 	T_SKIP("pfctl isn't valid on this platform");
3241 #else /* TARGET_OS_BRIDGE */
3242 	switch_port_list_t port_list;
3243 	switch_port_t   port;
3244 	const u_int n_ports = 2;
3245 	u_int num_addrs = 1;
3246 	u_int i;
3247 	char ntoabuf[ETHER_NTOA_BUFSIZE];
3248 	union ifbrip dst_ip;
3249 	bool blocked = true;
3250 	bool input = true;
3251 	const char* ifnames[2];
3252 
3253 #define PFCTL_PATH      "/sbin/pfctl"
3254 	if (!executable_is_present(PFCTL_PATH)) {
3255 		T_SKIP("%s not present", PFCTL_PATH);
3256 		return;
3257 	}
3258 	signal(SIGINT, sigint_handler);
3259 
3260 	T_ATEND(cleanup);
3261 	T_ATEND(cleanup_pf);
3262 
3263 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs, 0);
3264 	if (port_list == NULL) {
3265 		T_FAIL("bridge_setup");
3266 		return;
3267 	}
3268 
3269 	ether_ntoa_buf(&ether_broadcast, ntoabuf, sizeof(ntoabuf));
3270 
3271 	S_port_list = port_list;
3272 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
3273 		ifnames[i] = port->member_ifname;
3274 	}
3275 
3276 	get_broadcast_ip_address(af, &dst_ip);
3277 	do {
3278 		do {
3279 			if (blocked) {
3280 				block_all_traffic(input, ifnames[0], ifnames[1]);
3281 			}
3282 			for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
3283 				if (G_debug) {
3284 					T_LOG("Sending on %s", port->ifname);
3285 				}
3286 				for (u_int j = 0; j < port->num_addrs; j++) {
3287 					uint32_t        generation;
3288 
3289 					generation = next_generation();
3290 					send_generation(port,
3291 					    af,
3292 					    j,
3293 					    &ether_broadcast,
3294 					    &dst_ip,
3295 					    generation);
3296 
3297 					/* receive across all ports */
3298 					check_receive_generation(port_list,
3299 					    af,
3300 					    generation,
3301 					    validate_broadcast_dhost,
3302 					    NULL);
3303 
3304 					/* ensure that every port saw the right amount of packets*/
3305 					if (blocked) {
3306 						check_received_count(port_list, port, 0);
3307 					} else {
3308 						check_received_count(port_list, port, 1);
3309 					}
3310 				}
3311 			}
3312 			T_PASS("%s broadcast %s %s", __func__, blocked ? "blocked" : "not blocked", input ? "input" : "output");
3313 			input = !input;
3314 			cleanup_pf();
3315 		} while (input == false && blocked);
3316 		blocked = !blocked;
3317 	} while (blocked == false);
3318 
3319 	do {
3320 		do {
3321 			if (blocked) {
3322 				block_all_traffic(input, ifnames[0], ifnames[1]);
3323 			}
3324 			for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
3325 				/* send unicast packets to every other port's MAC addresses */
3326 				unicast_send_all(port_list, af, port);
3327 
3328 				/* receive all of that generated traffic */
3329 				switch_port_list_check_receive(port_list, af, NULL, 0,
3330 				    validate_port_dhost, NULL);
3331 
3332 				/* ensure that every port saw the right amount of packets*/
3333 				if (blocked) {
3334 					check_received_count(port_list, port, 0);
3335 				} else {
3336 					check_received_count(port_list, port, 1);
3337 				}
3338 			}
3339 			T_PASS("%s unicast %s %s", __func__, blocked ? "blocked" : "not blocked", input ? "input" : "output");
3340 			input = !input;
3341 			cleanup_pf();
3342 		} while (input == false && blocked);
3343 		blocked = !blocked;
3344 	} while (blocked == false);
3345 
3346 	bridge_cleanup(BRIDGE200, n_ports, true);
3347 	switch_port_list_dealloc(port_list);
3348 	return;
3349 #endif /* TARGET_OS_BRIDGE */
3350 }
3351 
3352 /*
3353  * Bridge checksum offload tests
3354  */
3355 
3356 static void
test_traffic_for_af(switch_port_list_t ports,uint8_t af)3357 test_traffic_for_af(switch_port_list_t ports, uint8_t af)
3358 {
3359 	u_int           i;
3360 	inet_address    server;
3361 	int             server_if_index;
3362 	const char *    server_name;
3363 	switch_port_t   server_port;
3364 	switch_port_t   port;
3365 
3366 	/* bridge as server, each peer as client */
3367 	server_if_index = bridge_if_index;
3368 	server_name = BRIDGE200;
3369 	if (af == AF_INET) {
3370 		server.v4 = bridge_ip_addr;
3371 	} else {
3372 		server.v6 = bridge_ipv6_addr;
3373 	}
3374 	for (i = 0, port = ports->list; i < ports->count; i++, port++) {
3375 		inet_test_traffic(af, &server, server_name,
3376 		    server_if_index, port->ifname, port->if_index);
3377 	}
3378 
3379 	/* peer 0 as server, other peers as client */
3380 	assert(ports->count > 0);
3381 	server_port = ports->list;
3382 	server_name = server_port->ifname;
3383 	server_if_index = server_port->if_index;
3384 	if (af == AF_INET) {
3385 		server.v4 = server_port->ip;
3386 	} else {
3387 		server.v6 = server_port->ip6;
3388 	}
3389 	for (i = 1, port = ports->list + 1; i < ports->count; i++, port++) {
3390 		inet_test_traffic(af, &server, server_name,
3391 		    server_if_index, port->ifname, port->if_index);
3392 	}
3393 }
3394 
3395 static void
bridge_test_transfer(u_int n_ports,uint8_t setup_flags)3396 bridge_test_transfer(u_int n_ports, uint8_t setup_flags)
3397 {
3398 #if TARGET_OS_BRIDGE
3399 	T_SKIP("Test uses too much memory");
3400 #else /* TARGET_OS_BRIDGE */
3401 	switch_port_list_t port_list;
3402 
3403 	signal(SIGINT, sigint_handler);
3404 	port_list = bridge_setup(BRIDGE200, n_ports, 0,
3405 	    SETUP_FLAGS_ATTACH_STACK | setup_flags);
3406 	if (port_list == NULL) {
3407 		T_FAIL("bridge_setup");
3408 		return;
3409 	}
3410 	test_traffic_for_af(port_list, AF_INET);
3411 	test_traffic_for_af(port_list, AF_INET6);
3412 	if (G_debug) {
3413 		T_LOG("Sleeping for 5 seconds");
3414 		sleep(5);
3415 	}
3416 	bridge_cleanup(BRIDGE200, n_ports, true);
3417 	switch_port_list_dealloc(port_list);
3418 	return;
3419 #endif /* TARGET_OS_BRIDGE */
3420 }
3421 
3422 static void
lro_test_cleanup(void)3423 lro_test_cleanup(void)
3424 {
3425 	ifnet_destroy(BRIDGE200, false);
3426 	ifnet_destroy(FETH0, false);
3427 	fake_set_lro(false);
3428 }
3429 
3430 static void
sigint_lro_cleanup(__unused int sig)3431 sigint_lro_cleanup(__unused int sig)
3432 {
3433 	signal(SIGINT, SIG_DFL);
3434 	lro_test_cleanup();
3435 }
3436 
3437 static void
verify_lro_capability(const char * if_name,bool expected)3438 verify_lro_capability(const char * if_name, bool expected)
3439 {
3440 	struct ifreq    ifr;
3441 	int             result;
3442 	bool            lro_enabled;
3443 	int             s = inet_dgram_socket_get();
3444 
3445 	memset(&ifr, 0, sizeof(ifr));
3446 	strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
3447 	result = ioctl(s, SIOCGIFCAP, &ifr);
3448 	T_ASSERT_POSIX_SUCCESS(result, "SIOCGIFCAP(%s)", if_name);
3449 	lro_enabled = (ifr.ifr_curcap & IFCAP_LRO) != 0;
3450 	T_ASSERT_EQ(expected, lro_enabled, "%s %s expected %s",
3451 	    __func__, if_name, expected ? "enabled" : "disabled");
3452 }
3453 
3454 static void
bridge_test_lro_disable(void)3455 bridge_test_lro_disable(void)
3456 {
3457 	int             err;
3458 
3459 	signal(SIGINT, sigint_lro_cleanup);
3460 
3461 	T_ATEND(lro_test_cleanup);
3462 
3463 	err = ifnet_create(BRIDGE200);
3464 	T_ASSERT_EQ(err, 0, "ifnet_create(%s)", BRIDGE200);
3465 	fake_set_lro(true);
3466 	err = ifnet_create(FETH0);
3467 	T_ASSERT_EQ(err, 0, "ifnet_create(%s)", FETH0);
3468 	fake_set_lro(false);
3469 	verify_lro_capability(FETH0, true);
3470 	bridge_add_member(BRIDGE200, FETH0);
3471 	verify_lro_capability(FETH0, false);
3472 	bridge_delete_member(BRIDGE200, FETH0);
3473 	verify_lro_capability(FETH0, true);
3474 }
3475 
3476 T_DECL(net_if_bridge_bcast,
3477     "bridge broadcast IPv4",
3478     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3479 {
3480 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
3481 	    AF_INET, 5, 1);
3482 }
3483 
3484 T_DECL(net_if_bridge_bcast_many,
3485     "bridge broadcast many IPv4",
3486     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3487 {
3488 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
3489 	    AF_INET, 5, 20);
3490 }
3491 
3492 T_DECL(net_if_bridge_unknown,
3493     "bridge unknown host IPv4",
3494     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3495 {
3496 	bridge_test(validate_not_present_dhost, NULL, &ether_external,
3497 	    AF_INET, 5, 1);
3498 }
3499 
3500 T_DECL(net_if_bridge_bcast_v6,
3501     "bridge broadcast IPv6",
3502     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3503 {
3504 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
3505 	    AF_INET6, 5, 1);
3506 }
3507 
3508 T_DECL(net_if_bridge_bcast_many_v6,
3509     "bridge broadcast many IPv6",
3510     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3511 {
3512 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
3513 	    AF_INET6, 5, 20);
3514 }
3515 
3516 T_DECL(net_if_bridge_unknown_v6,
3517     "bridge unknown host IPv6",
3518     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3519 {
3520 	bridge_test(validate_not_present_dhost, NULL, &ether_external,
3521 	    AF_INET6, 5, 1);
3522 }
3523 
3524 T_DECL(net_if_bridge_mac_nat_ipv4,
3525     "bridge mac nat ipv4",
3526     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3527 {
3528 	bridge_test_mac_nat_ipv4(5, 10);
3529 }
3530 
3531 T_DECL(net_if_bridge_mac_nat_ipv6,
3532     "bridge mac nat ipv6",
3533     T_META_ASROOT(true),
3534     T_META_TAG_VM_PREFERRED,
3535     T_META_ENABLED(false /* rdar://133955717 */))
3536 {
3537 	bridge_test_mac_nat_ipv6(5, 10, 0);
3538 }
3539 
3540 T_DECL(net_if_bridge_mac_nat_ipv6_trailers,
3541     "bridge mac nat ipv6 trailers",
3542     T_META_ASROOT(true),
3543     T_META_TAG_VM_PREFERRED,
3544     T_META_ENABLED(false /* rdar://133955717 */))
3545 {
3546 	bridge_test_mac_nat_ipv6(5, 10, SETUP_FLAGS_TRAILERS);
3547 }
3548 
3549 T_DECL(net_if_bridge_filter_ipv4,
3550     "bridge filter ipv4",
3551     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3552 {
3553 	filter_test(AF_INET);
3554 }
3555 
3556 T_DECL(net_if_bridge_filter_ipv6,
3557     "bridge filter ipv6",
3558     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3559 {
3560 	filter_test(AF_INET6);
3561 }
3562 
3563 T_DECL(net_if_bridge_checksum_offload,
3564     "bridge checksum offload",
3565     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3566 {
3567 	bridge_test_transfer(2, SETUP_FLAGS_CHECKSUM_OFFLOAD);
3568 }
3569 
3570 T_DECL(net_if_bridge_checksum_offload_trailers,
3571     "bridge checksum offload with trailers+fcs",
3572     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3573 {
3574 	bridge_test_transfer(2, SETUP_FLAGS_CHECKSUM_OFFLOAD |
3575 	    SETUP_FLAGS_TRAILERS);
3576 }
3577 
3578 T_DECL(net_if_bridge_transfer,
3579     "bridge transfer",
3580     T_META_ASROOT(true))
3581 {
3582 	bridge_test_transfer(2, 0);
3583 }
3584 
3585 T_DECL(net_if_bridge_transfer_share_mac,
3586     "bridge transfer share member's MAC",
3587     T_META_ASROOT(true))
3588 {
3589 	bridge_test_transfer(2, SETUP_FLAGS_SHARE_MEMBER_MAC);
3590 }
3591 
3592 T_DECL(net_if_bridge_lro_disable,
3593     "bridge LRO disable",
3594     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
3595 {
3596 	bridge_test_lro_disable();
3597 }
3598