xref: /freebsd/tests/sys/netlink/test_snl.c (revision a259b98fa211ed87bfee58c575de4e2de94ee0fa)
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 
5 #include <sys/param.h>
6 #include <sys/module.h>
7 
8 #include <net/ethernet.h>
9 
10 #include <netlink/netlink.h>
11 #include <netlink/netlink_route.h>
12 #include "netlink/netlink_snl.h"
13 #include "netlink/netlink_snl_route.h"
14 #include "netlink/netlink_snl_route_parsers.h"
15 
16 #include <atf-c.h>
17 
18 static const struct snl_hdr_parser *snl_all_core_parsers[] = {
19 	&snl_errmsg_parser, &snl_donemsg_parser,
20 	&_nla_bit_parser, &_nla_bitset_parser,
21 };
22 
23 static const struct snl_hdr_parser *snl_all_route_parsers[] = {
24 	&_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser,
25 	&_vf_driver_field_parser, &_vf_driver_parser, &_vf_parser,
26 	&_vf_status_parser,
27 	&_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple,
28 	&_neigh_fbsd_parser, &snl_rtm_neigh_parser,
29 	&_addr_fbsd_parser, &snl_rtm_addr_parser, &_nh_fbsd_parser, &snl_nhmsg_parser,
30 };
31 
32 ATF_TC(snl_verify_core_parsers);
33 ATF_TC_HEAD(snl_verify_core_parsers, tc)
34 {
35 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) core nlmsg parsers are correct");
36 }
37 
38 ATF_TC_BODY(snl_verify_core_parsers, tc)
39 {
40 	SNL_VERIFY_PARSERS(snl_all_core_parsers);
41 
42 }
43 
44 ATF_TC(snl_parse_bitset_array);
45 ATF_TC_HEAD(snl_parse_bitset_array, tc)
46 {
47 	atf_tc_set_md_var(tc, "descr",
48 	    "Tests snl(3) parsing a growing nested bit array");
49 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
50 }
51 
52 ATF_TC_BODY(snl_parse_bitset_array, tc)
53 {
54 	struct snl_attr_bit *bit;
55 	struct snl_parsed_link link = {};
56 	struct snl_state ss;
57 	struct snl_writer nw;
58 	struct nlmsghdr *hdr;
59 	uint32_t mask, value;
60 	char name[16];
61 	int bits_off, entry_off, fbsd_off, caps_off;
62 
63 	ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
64 	snl_init_writer(&ss, &nw);
65 	hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
66 	ATF_REQUIRE(hdr != NULL);
67 	ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
68 
69 	fbsd_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD);
70 	ATF_REQUIRE(fbsd_off != 0);
71 	caps_off = snl_add_msg_attr_nested(&nw, IFLAF_CAPS);
72 	ATF_REQUIRE(caps_off != 0);
73 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, NLA_BITSET_SIZE, 32));
74 	mask = 0x1ff;
75 	value = 0x155;
76 	ATF_REQUIRE(snl_add_msg_attr(&nw, NLA_BITSET_MASK, sizeof(mask),
77 	    &mask));
78 	ATF_REQUIRE(snl_add_msg_attr(&nw, NLA_BITSET_VALUE, sizeof(value),
79 	    &value));
80 	bits_off = snl_add_msg_attr_nested(&nw, NLA_BITSET_BITS);
81 	ATF_REQUIRE(bits_off != 0);
82 	for (uint32_t i = 0; i < 9; i++) {
83 		entry_off = snl_add_msg_attr_nested(&nw, i + 1);
84 		ATF_REQUIRE(entry_off != 0);
85 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw,
86 		    NLA_BITSET_BIT_INDEX, i));
87 		snprintf(name, sizeof(name), "bit-%u", i);
88 		ATF_REQUIRE(snl_add_msg_attr_string(&nw,
89 		    NLA_BITSET_BIT_NAME, name));
90 		if ((i & 1) == 0)
91 			ATF_REQUIRE(snl_add_msg_attr_flag(&nw,
92 			    NLA_BITSET_BIT_VALUE));
93 		snl_end_attr_nested(&nw, entry_off);
94 	}
95 	snl_end_attr_nested(&nw, bits_off);
96 	snl_end_attr_nested(&nw, caps_off);
97 	snl_end_attr_nested(&nw, fbsd_off);
98 	hdr = snl_finalize_msg(&nw);
99 	ATF_REQUIRE(hdr != NULL);
100 
101 	ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
102 	ATF_REQUIRE_EQ(link.iflaf_caps.bits.count, 9);
103 	bit = link.iflaf_caps.bits.items[8];
104 	ATF_CHECK_EQ(bit->bit_index, 8);
105 	ATF_CHECK_STREQ(bit->bit_name, "bit-8");
106 	ATF_CHECK_EQ(bit->bit_value, 1);
107 }
108 
109 ATF_TC(snl_parse_vf_status);
110 ATF_TC_HEAD(snl_parse_vf_status, tc)
111 {
112 	atf_tc_set_md_var(tc, "descr",
113 	    "Tests snl(3) parsing nested VF status");
114 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
115 }
116 
117 ATF_TC_BODY(snl_parse_vf_status, tc)
118 {
119 	static const uint8_t mac[] = { 0x02, 0, 0, 0, 0, 1 };
120 	static const uint8_t extension_data[] = { 1, 2, 3, 4 };
121 	struct snl_parsed_vf_driver_field *field;
122 	struct snl_parsed_vf_driver *driver;
123 	struct snl_parsed_vf_status *status;
124 	struct snl_parsed_link link = {};
125 	struct snl_parsed_vf *vf;
126 	struct snl_state ss;
127 	struct snl_writer nw;
128 	struct nlmsghdr *hdr;
129 	uint32_t i;
130 	int driver_off, entry_off, fbsd_off, field_off, status_off;
131 
132 	ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
133 	snl_init_writer(&ss, &nw);
134 	hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
135 	ATF_REQUIRE(hdr != NULL);
136 	ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
137 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLA_NUM_VF, 9));
138 
139 	fbsd_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD);
140 	ATF_REQUIRE(fbsd_off != 0);
141 	status_off = snl_add_msg_attr_nested(&nw, IFLAF_VF_STATUS);
142 	ATF_REQUIRE(status_off != 0);
143 	ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VFS_PF_LINK_STATE,
144 	    IFLAF_VF_LINK_UP));
145 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VFS_PF_LINK_SPEED,
146 	    10000000000ULL));
147 	snl_end_attr_nested(&nw, status_off);
148 	snl_end_attr_nested(&nw, fbsd_off);
149 
150 	entry_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD_VF);
151 	ATF_REQUIRE(entry_off != 0);
152 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_INDEX, 7));
153 	ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_CONFIGURED, true));
154 	ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_TRAFFIC_ALLOWED,
155 	    true));
156 	ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_FAULT_BLOCKED,
157 	    false));
158 	ATF_REQUIRE(snl_add_msg_attr_u16(&nw, IFLAF_VF_NUM_TX_QUEUES, 4));
159 	ATF_REQUIRE(snl_add_msg_attr_u16(&nw, IFLAF_VF_NUM_RX_QUEUES, 8));
160 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VF_MIN_TX_RATE,
161 	    25000000000ULL));
162 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VF_MAX_TX_RATE,
163 	    100000000000ULL));
164 	ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VF_VLAN_MODE,
165 	    IFLAF_VF_VLAN_ACCESS));
166 	ATF_REQUIRE(snl_add_msg_attr_u16(&nw, IFLAF_VF_VLAN, 0));
167 	ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VF_VLAN_PCP, 5));
168 	ATF_REQUIRE(snl_add_msg_attr_u16(&nw, IFLAF_VF_VLAN_PROTO,
169 	    ETHERTYPE_VLAN));
170 	ATF_REQUIRE(snl_add_msg_attr(&nw, IFLAF_VF_MAC, sizeof(mac), mac));
171 
172 	driver_off = snl_add_msg_attr_nested(&nw, IFLAF_VF_DRIVER);
173 	ATF_REQUIRE(driver_off != 0);
174 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFD_NAME,
175 	    "driver.test"));
176 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VFD_VERSION, 3));
177 	field_off = snl_add_msg_attr_nested(&nw, IFLAF_VFD_FIELD);
178 	ATF_REQUIRE(field_off != 0);
179 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFDF_NAME,
180 	    "ready"));
181 	ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VFDF_BOOL, false));
182 	snl_end_attr_nested(&nw, field_off);
183 	field_off = snl_add_msg_attr_nested(&nw, IFLAF_VFD_FIELD);
184 	ATF_REQUIRE(field_off != 0);
185 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFDF_NAME,
186 	    "opaque"));
187 	ATF_REQUIRE(snl_add_msg_attr(&nw, IFLAF_VFDF_BINARY,
188 	    sizeof(extension_data), extension_data));
189 	snl_end_attr_nested(&nw, field_off);
190 	field_off = snl_add_msg_attr_nested(&nw, IFLAF_VFD_FIELD);
191 	ATF_REQUIRE(field_off != 0);
192 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFDF_NAME,
193 	    "sequence"));
194 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VFDF_NUMBER,
195 	    0x100000002ULL));
196 	snl_end_attr_nested(&nw, field_off);
197 	field_off = snl_add_msg_attr_nested(&nw, IFLAF_VFD_FIELD);
198 	ATF_REQUIRE(field_off != 0);
199 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFDF_NAME,
200 	    "mode"));
201 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFDF_STRING,
202 	    "diagnostic"));
203 	snl_end_attr_nested(&nw, field_off);
204 	/* A newer field value type must not hide fields known to this parser. */
205 	field_off = snl_add_msg_attr_nested(&nw, IFLAF_VFD_FIELD);
206 	ATF_REQUIRE(field_off != 0);
207 	ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFDF_NAME,
208 	    "future-value"));
209 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VFDF_MAX + 1, 1));
210 	snl_end_attr_nested(&nw, field_off);
211 	snl_end_attr_nested(&nw, driver_off);
212 	snl_end_attr_nested(&nw, entry_off);
213 
214 	/* A second attribute of the same type is the second array member. */
215 	entry_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD_VF);
216 	ATF_REQUIRE(entry_off != 0);
217 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_INDEX, 8));
218 	ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_CONFIGURED, false));
219 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VF_MIN_TX_RATE, 0));
220 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VF_MAX_TX_RATE, 0));
221 	snl_end_attr_nested(&nw, entry_off);
222 	/* Cross the parser array's initial capacity to exercise growth. */
223 	for (i = 9; i <= 15; i++) {
224 		entry_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD_VF);
225 		ATF_REQUIRE(entry_off != 0);
226 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_INDEX, i));
227 		snl_end_attr_nested(&nw, entry_off);
228 	}
229 	hdr = snl_finalize_msg(&nw);
230 	ATF_REQUIRE(hdr != NULL);
231 
232 	ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
233 	ATF_CHECK_EQ(link.ifla_num_vf, 9);
234 	status = &link.iflaf_vf_status;
235 	ATF_CHECK(status->present);
236 	ATF_CHECK_EQ(status->pf_link_state, IFLAF_VF_LINK_UP);
237 	ATF_CHECK_EQ(status->pf_link_speed, 10000000000ULL);
238 	ATF_REQUIRE_EQ(status->vfs.count, 9);
239 	vf = status->vfs.items[0];
240 	ATF_CHECK_EQ(vf->index, 7);
241 	ATF_CHECK_EQ(vf->configured, 1);
242 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_TRAFFIC_ALLOWED)) != 0);
243 	ATF_CHECK_EQ(vf->traffic_allowed, true);
244 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_FAULT_BLOCKED)) != 0);
245 	ATF_CHECK_EQ(vf->fault_blocked, false);
246 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_NUM_TX_QUEUES)) != 0);
247 	ATF_CHECK_EQ(vf->tx_queue_count, 4);
248 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_NUM_RX_QUEUES)) != 0);
249 	ATF_CHECK_EQ(vf->rx_queue_count, 8);
250 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_MIN_TX_RATE)) != 0);
251 	ATF_CHECK_EQ(vf->min_tx_rate_bps, 25000000000ULL);
252 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_MAX_TX_RATE)) != 0);
253 	ATF_CHECK_EQ(vf->max_tx_rate_bps, 100000000000ULL);
254 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_VLAN_MODE)) != 0);
255 	ATF_CHECK_EQ(vf->vlan_mode, IFLAF_VF_VLAN_ACCESS);
256 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_VLAN)) != 0);
257 	ATF_CHECK_EQ(vf->vlan, 0);
258 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_VLAN_PCP)) != 0);
259 	ATF_CHECK_EQ(vf->vlan_pcp, 5);
260 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_VLAN_PROTO)) != 0);
261 	ATF_CHECK_EQ(vf->vlan_proto, ETHERTYPE_VLAN);
262 	ATF_REQUIRE(vf->mac != NULL);
263 	ATF_CHECK_EQ(NLA_DATA_LEN(vf->mac), sizeof(mac));
264 	ATF_CHECK(memcmp(NLA_DATA(vf->mac), mac, sizeof(mac)) == 0);
265 	ATF_REQUIRE_EQ(vf->drivers.count, 1);
266 	driver = vf->drivers.items[0];
267 	ATF_CHECK_STREQ(driver->name, "driver.test");
268 	ATF_CHECK_EQ(driver->version, 3);
269 	ATF_REQUIRE_EQ(driver->fields.count, 4);
270 	field = driver->fields.items[0];
271 	ATF_CHECK_STREQ(field->name, "ready");
272 	ATF_CHECK_EQ(field->type, SNL_VFDF_BOOL);
273 	ATF_CHECK_EQ(field->boolean, false);
274 	field = driver->fields.items[1];
275 	ATF_CHECK_STREQ(field->name, "opaque");
276 	ATF_CHECK_EQ(field->type, SNL_VFDF_BINARY);
277 	ATF_REQUIRE(field->binary != NULL);
278 	ATF_CHECK_EQ(NLA_DATA_LEN(field->binary), sizeof(extension_data));
279 	ATF_CHECK(memcmp(NLA_DATA(field->binary), extension_data,
280 	    sizeof(extension_data)) == 0);
281 	field = driver->fields.items[2];
282 	ATF_CHECK_STREQ(field->name, "sequence");
283 	ATF_CHECK_EQ(field->type, SNL_VFDF_NUMBER);
284 	ATF_CHECK_EQ(field->number, 0x100000002ULL);
285 	field = driver->fields.items[3];
286 	ATF_CHECK_STREQ(field->name, "mode");
287 	ATF_CHECK_EQ(field->type, SNL_VFDF_STRING);
288 	ATF_CHECK_STREQ(field->string, "diagnostic");
289 	vf = status->vfs.items[1];
290 	ATF_CHECK_EQ(vf->index, 8);
291 	ATF_CHECK_EQ(vf->configured, false);
292 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_MIN_TX_RATE)) != 0);
293 	ATF_CHECK_EQ(vf->min_tx_rate_bps, 0);
294 	ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_MAX_TX_RATE)) != 0);
295 	ATF_CHECK_EQ(vf->max_tx_rate_bps, 0);
296 	vf = status->vfs.items[8];
297 	ATF_CHECK_EQ(vf->index, 15);
298 }
299 
300 ATF_TC(snl_parse_vf_trunk_pcp);
301 ATF_TC_HEAD(snl_parse_vf_trunk_pcp, tc)
302 {
303 	atf_tc_set_md_var(tc, "descr",
304 	    "Tests snl(3) parsing trunk PCP values and omitted priority");
305 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
306 }
307 
308 ATF_TC_BODY(snl_parse_vf_trunk_pcp, tc)
309 {
310 	struct snl_parsed_link link = {};
311 	struct snl_parsed_vf *vf;
312 	struct snl_state ss;
313 	struct snl_writer nw;
314 	struct nlmsghdr *hdr;
315 	uint32_t i;
316 	int entry_off;
317 
318 	ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
319 	snl_init_writer(&ss, &nw);
320 	hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
321 	ATF_REQUIRE(hdr != NULL);
322 	ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
323 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLA_NUM_VF, 9));
324 	for (i = 0; i < 9; i++) {
325 		entry_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD_VF);
326 		ATF_REQUIRE(entry_off != 0);
327 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_INDEX, i));
328 		ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VF_VLAN_MODE,
329 		    IFLAF_VF_VLAN_TRUNK));
330 		/* Cover PCP 0..7 and absence, without an imposed VLAN. */
331 		if (i < 8)
332 			ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VF_VLAN_PCP,
333 			    i));
334 		snl_end_attr_nested(&nw, entry_off);
335 	}
336 	hdr = snl_finalize_msg(&nw);
337 	ATF_REQUIRE(hdr != NULL);
338 	ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
339 	ATF_CHECK_EQ(link.ifla_num_vf, 9);
340 	ATF_REQUIRE_EQ(link.iflaf_vf_status.vfs.count, 9);
341 	for (i = 0; i < 9; i++) {
342 		vf = link.iflaf_vf_status.vfs.items[i];
343 		ATF_CHECK_EQ(vf->index, i);
344 		ATF_CHECK((vf->attrs & (1ULL << IFLAF_VF_VLAN_MODE)) != 0);
345 		ATF_CHECK_EQ(vf->vlan_mode, IFLAF_VF_VLAN_TRUNK);
346 		ATF_CHECK((vf->attrs & ((1ULL << IFLAF_VF_VLAN) |
347 		    (1ULL << IFLAF_VF_VLAN_PROTO))) == 0);
348 		ATF_CHECK_EQ((vf->attrs & (1ULL << IFLAF_VF_VLAN_PCP)) != 0,
349 		    i < 8);
350 		if (i < 8)
351 			ATF_CHECK_EQ(vf->vlan_pcp, i);
352 	}
353 	snl_free(&ss);
354 }
355 
356 ATF_TC(snl_parse_large_vf_status);
357 ATF_TC_HEAD(snl_parse_large_vf_status, tc)
358 {
359 	atf_tc_set_md_var(tc, "descr",
360 	    "Tests snl(3) parsing more than 256 full VF records");
361 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
362 }
363 
364 ATF_TC_BODY(snl_parse_large_vf_status, tc)
365 {
366 	static const char *field_names[] = {
367 		"mirror-configured",
368 		"mirror-ingress-active",
369 		"mirror-egress-active",
370 	};
371 	static const uint32_t vf_count = 512;
372 	struct snl_parsed_vf_driver *driver;
373 	struct snl_parsed_vf_status *status;
374 	struct snl_parsed_link link = {};
375 	struct snl_parsed_vf *vf;
376 	struct snl_state ss;
377 	struct snl_writer nw;
378 	struct nlmsghdr *hdr;
379 	uint8_t mac[ETHER_ADDR_LEN] = { 0x02, 0, 0, 0, 0, 0 };
380 	uint32_t i, j;
381 	int driver_off, entry_off, fbsd_off, field_off, status_off;
382 
383 	ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
384 	snl_init_writer(&ss, &nw);
385 	hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
386 	ATF_REQUIRE(hdr != NULL);
387 	ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
388 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLA_NUM_VF, vf_count));
389 	fbsd_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD);
390 	ATF_REQUIRE(fbsd_off != 0);
391 	status_off = snl_add_msg_attr_nested(&nw, IFLAF_VF_STATUS);
392 	ATF_REQUIRE(status_off != 0);
393 	ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VFS_PF_LINK_STATE,
394 	    IFLAF_VF_LINK_UP));
395 	ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VFS_PF_LINK_SPEED,
396 	    100000000000ULL));
397 	snl_end_attr_nested(&nw, status_off);
398 	snl_end_attr_nested(&nw, fbsd_off);
399 
400 	for (i = 0; i < vf_count; i++) {
401 		mac[4] = i >> 8;
402 		mac[5] = i;
403 		entry_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD_VF);
404 		ATF_REQUIRE(entry_off != 0);
405 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_INDEX, i));
406 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_CONFIGURED,
407 		    true));
408 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_INITIALIZED,
409 		    true));
410 		ATF_REQUIRE(snl_add_msg_attr(&nw, IFLAF_VF_MAC, sizeof(mac),
411 		    mac));
412 		ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VF_VLAN_MODE,
413 		    IFLAF_VF_VLAN_ACCESS));
414 		ATF_REQUIRE(snl_add_msg_attr_u16(&nw, IFLAF_VF_VLAN,
415 		    i & EVL_VLID_MASK));
416 		ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VF_VLAN_PCP,
417 		    i & 7));
418 		ATF_REQUIRE(snl_add_msg_attr_u16(&nw, IFLAF_VF_VLAN_PROTO,
419 		    ETHERTYPE_VLAN));
420 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_VLAN_COUNT,
421 		    1));
422 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VF_VLAN_LIMIT,
423 		    16));
424 		ATF_REQUIRE(snl_add_msg_attr_u16(&nw,
425 		    IFLAF_VF_NUM_TX_QUEUES, 4));
426 		ATF_REQUIRE(snl_add_msg_attr_u16(&nw,
427 		    IFLAF_VF_NUM_RX_QUEUES, 4));
428 		ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VF_MIN_TX_RATE,
429 		    1000000000ULL));
430 		ATF_REQUIRE(snl_add_msg_attr_u64(&nw, IFLAF_VF_MAX_TX_RATE,
431 		    10000000000ULL));
432 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_ALLOW_SET_MAC,
433 		    true));
434 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw,
435 		    IFLAF_VF_ALLOW_SET_VLAN, true));
436 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw,
437 		    IFLAF_VF_MAC_ANTI_SPOOF, true));
438 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_ALLOW_PROMISC,
439 		    false));
440 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw,
441 		    IFLAF_VF_TRAFFIC_ALLOWED, true));
442 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw,
443 		    IFLAF_VF_FAULT_BLOCKED, false));
444 		ATF_REQUIRE(snl_add_msg_attr_bool(&nw, IFLAF_VF_QUARANTINED,
445 		    false));
446 		ATF_REQUIRE(snl_add_msg_attr_string(&nw,
447 		    IFLAF_VF_API_VERSION, "1.1"));
448 		ATF_REQUIRE(snl_add_msg_attr_u8(&nw,
449 		    IFLAF_VF_LINK_STATE_POLICY, IFLAF_VF_LINK_AUTO));
450 
451 		driver_off = snl_add_msg_attr_nested(&nw, IFLAF_VF_DRIVER);
452 		ATF_REQUIRE(driver_off != 0);
453 		ATF_REQUIRE(snl_add_msg_attr_string(&nw, IFLAF_VFD_NAME,
454 		    "driver.ice"));
455 		ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VFD_VERSION, 1));
456 		for (j = 0; j < nitems(field_names); j++) {
457 			field_off = snl_add_msg_attr_nested(&nw,
458 			    IFLAF_VFD_FIELD);
459 			ATF_REQUIRE(field_off != 0);
460 			ATF_REQUIRE(snl_add_msg_attr_string(&nw,
461 			    IFLAF_VFDF_NAME, field_names[j]));
462 			ATF_REQUIRE(snl_add_msg_attr_bool(&nw,
463 			    IFLAF_VFDF_BOOL, false));
464 			snl_end_attr_nested(&nw, field_off);
465 		}
466 		snl_end_attr_nested(&nw, driver_off);
467 		snl_end_attr_nested(&nw, entry_off);
468 	}
469 	hdr = snl_finalize_msg(&nw);
470 	ATF_REQUIRE(hdr != NULL);
471 	ATF_REQUIRE_MSG(hdr->nlmsg_len > UINT16_MAX,
472 	    "test message is only %u bytes", hdr->nlmsg_len);
473 
474 	ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
475 	ATF_CHECK_EQ(link.ifla_num_vf, vf_count);
476 	status = &link.iflaf_vf_status;
477 	ATF_CHECK(status->present);
478 	ATF_REQUIRE_EQ(status->vfs.count, vf_count);
479 	vf = status->vfs.items[0];
480 	ATF_CHECK_EQ(vf->index, 0);
481 	vf = status->vfs.items[vf_count - 1];
482 	ATF_CHECK_EQ(vf->index, vf_count - 1);
483 	ATF_CHECK_EQ(vf->tx_queue_count, 4);
484 	ATF_CHECK_EQ(vf->rx_queue_count, 4);
485 	ATF_REQUIRE_EQ(vf->drivers.count, 1);
486 	driver = vf->drivers.items[0];
487 	ATF_CHECK_STREQ(driver->name, "driver.ice");
488 	ATF_CHECK_EQ(driver->fields.count, nitems(field_names));
489 }
490 
491 ATF_TC(snl_parse_empty_vf_status);
492 ATF_TC_HEAD(snl_parse_empty_vf_status, tc)
493 {
494 	atf_tc_set_md_var(tc, "descr",
495 	    "Tests snl(3) parsing an empty VF status snapshot");
496 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
497 }
498 
499 ATF_TC_BODY(snl_parse_empty_vf_status, tc)
500 {
501 	struct snl_parsed_link link = {};
502 	struct snl_state ss;
503 	struct snl_writer nw;
504 	struct nlmsghdr *hdr;
505 	int fbsd_off, status_off;
506 
507 	ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
508 	snl_init_writer(&ss, &nw);
509 	hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
510 	ATF_REQUIRE(hdr != NULL);
511 	ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
512 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLA_NUM_VF, 0));
513 	fbsd_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD);
514 	ATF_REQUIRE(fbsd_off != 0);
515 	status_off = snl_add_msg_attr_nested(&nw, IFLAF_VF_STATUS);
516 	ATF_REQUIRE(status_off != 0);
517 	ATF_REQUIRE(snl_add_msg_attr_u8(&nw, IFLAF_VFS_PF_LINK_STATE,
518 	    IFLAF_VF_LINK_DOWN));
519 	snl_end_attr_nested(&nw, status_off);
520 	snl_end_attr_nested(&nw, fbsd_off);
521 	hdr = snl_finalize_msg(&nw);
522 	ATF_REQUIRE(hdr != NULL);
523 
524 	ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
525 	ATF_CHECK_EQ(link.ifla_num_vf, 0);
526 	ATF_CHECK(link.iflaf_vf_status.present);
527 	ATF_CHECK_EQ(link.iflaf_vf_status.pf_link_state,
528 	    IFLAF_VF_LINK_DOWN);
529 	ATF_CHECK_EQ(link.iflaf_vf_status.vfs.count, 0);
530 }
531 
532 ATF_TC(snl_parse_vf_status_error);
533 ATF_TC_HEAD(snl_parse_vf_status_error, tc)
534 {
535 	atf_tc_set_md_var(tc, "descr",
536 	    "Tests snl(3) parsing a VF status provider error");
537 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
538 }
539 
540 ATF_TC_BODY(snl_parse_vf_status_error, tc)
541 {
542 	struct snl_parsed_link link = {};
543 	struct snl_state ss;
544 	struct snl_writer nw;
545 	struct nlmsghdr *hdr;
546 	int fbsd_off, status_off;
547 
548 	ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
549 	snl_init_writer(&ss, &nw);
550 	hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
551 	ATF_REQUIRE(hdr != NULL);
552 	ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
553 	fbsd_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD);
554 	ATF_REQUIRE(fbsd_off != 0);
555 	status_off = snl_add_msg_attr_nested(&nw, IFLAF_VF_STATUS);
556 	ATF_REQUIRE(status_off != 0);
557 	ATF_REQUIRE(snl_add_msg_attr_u32(&nw, IFLAF_VFS_ERROR, EMSGSIZE));
558 	snl_end_attr_nested(&nw, status_off);
559 	snl_end_attr_nested(&nw, fbsd_off);
560 	hdr = snl_finalize_msg(&nw);
561 	ATF_REQUIRE(hdr != NULL);
562 
563 	ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
564 	ATF_CHECK(link.iflaf_vf_status.present);
565 	ATF_CHECK_EQ(link.iflaf_vf_status.error, EMSGSIZE);
566 	ATF_CHECK_EQ(link.iflaf_vf_status.vfs.count, 0);
567 }
568 
569 ATF_TC(snl_verify_route_parsers);
570 ATF_TC_HEAD(snl_verify_route_parsers, tc)
571 {
572 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) route parsers are correct");
573 }
574 
575 ATF_TC_BODY(snl_verify_route_parsers, tc)
576 {
577 	SNL_VERIFY_PARSERS(snl_all_route_parsers);
578 
579 }
580 
581 ATF_TC(snl_parse_errmsg_capped);
582 ATF_TC_HEAD(snl_parse_errmsg_capped, tc)
583 {
584 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors");
585 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
586 }
587 
588 ATF_TC_BODY(snl_parse_errmsg_capped, tc)
589 {
590 	struct snl_state ss;
591 	struct snl_writer nw;
592 
593 	if (!snl_init(&ss, NETLINK_ROUTE))
594 		atf_tc_fail("snl_init() failed");
595 
596 	int optval = 1;
597 	ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0);
598 
599 	optval = 0;
600 	ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
601 	snl_init_writer(&ss, &nw);
602 
603 	struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
604 	ATF_CHECK(hdr != NULL);
605 	ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
606 	snl_add_msg_attr_string(&nw, 143, "some random string");
607 	ATF_CHECK(snl_finalize_msg(&nw) != NULL);
608 
609 	ATF_CHECK(snl_send_message(&ss, hdr));
610 
611 	struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
612 	ATF_CHECK(rx_hdr != NULL);
613 	ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
614 
615 	struct snl_errmsg_data e = {};
616 	ATF_CHECK(rx_hdr->nlmsg_len == sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr));
617 	ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
618 	ATF_CHECK(e.error != 0);
619 	ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr)));
620 }
621 
622 ATF_TC(snl_parse_errmsg_capped_extack);
623 ATF_TC_HEAD(snl_parse_errmsg_capped_extack, tc)
624 {
625 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors with extack");
626 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
627 }
628 
629 ATF_TC_BODY(snl_parse_errmsg_capped_extack, tc)
630 {
631 	struct snl_state ss;
632 	struct snl_writer nw;
633 
634 	if (!snl_init(&ss, NETLINK_ROUTE))
635 		atf_tc_fail("snl_init() failed");
636 
637 	int optval = 1;
638 	ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0);
639 	optval = 1;
640 	ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
641 
642 	snl_init_writer(&ss, &nw);
643 
644 	struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
645 	ATF_CHECK(hdr != NULL);
646 	ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
647 	snl_add_msg_attr_string(&nw, 143, "some random string");
648 	ATF_CHECK(snl_finalize_msg(&nw) != NULL);
649 
650 	ATF_CHECK(snl_send_message(&ss, hdr));
651 
652 	struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
653 	ATF_CHECK(rx_hdr != NULL);
654 	ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
655 
656 	struct snl_errmsg_data e = {};
657 	ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
658 	ATF_CHECK(e.error != 0);
659 	ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr)));
660 
661 	ATF_CHECK(e.error_str != NULL);
662 }
663 
664 ATF_TC(snl_parse_errmsg_uncapped_extack);
665 ATF_TC_HEAD(snl_parse_errmsg_uncapped_extack, tc)
666 {
667 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing errors with extack");
668 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
669 }
670 
671 ATF_TC_BODY(snl_parse_errmsg_uncapped_extack, tc)
672 {
673 	struct snl_state ss;
674 	struct snl_writer nw;
675 
676 	ATF_CHECK(snl_init(&ss, NETLINK_ROUTE));
677 
678 	int optval = 1;
679 	ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
680 
681 	snl_init_writer(&ss, &nw);
682 
683 	struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
684 	ATF_CHECK(hdr != NULL);
685 	ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
686 	snl_add_msg_attr_string(&nw, 143, "some random string");
687 	ATF_CHECK(snl_finalize_msg(&nw) != NULL);
688 
689 	ATF_CHECK(snl_send_message(&ss, hdr));
690 
691 	struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
692 	ATF_CHECK(rx_hdr != NULL);
693 	ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
694 
695 	struct snl_errmsg_data e = {};
696 	ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
697 	ATF_CHECK(e.error != 0);
698 	ATF_CHECK(!memcmp(hdr, e.orig_hdr, hdr->nlmsg_len));
699 
700 	ATF_CHECK(e.error_str != NULL);
701 }
702 
703 ATF_TC(snl_list_ifaces);
704 ATF_TC_HEAD(snl_list_ifaces, tc)
705 {
706 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) listing interfaces");
707 	atf_tc_set_md_var(tc, "require.kmods", "netlink");
708 }
709 
710 struct nl_parsed_link {
711 	uint32_t		ifi_index;
712 	uint32_t		ifla_mtu;
713 	char			*ifla_ifname;
714 };
715 
716 #define	_IN(_field)	offsetof(struct ifinfomsg, _field)
717 #define	_OUT(_field)	offsetof(struct nl_parsed_link, _field)
718 static struct snl_attr_parser ap_link[] = {
719 	{ .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string },
720 	{ .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
721 };
722 static struct snl_field_parser fp_link[] = {
723 	{.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
724 };
725 #undef _IN
726 #undef _OUT
727 SNL_DECLARE_PARSER(link_parser, struct ifinfomsg, fp_link, ap_link);
728 
729 
730 ATF_TC_BODY(snl_list_ifaces, tc)
731 {
732 	struct snl_state ss;
733 	struct snl_writer nw;
734 
735 	if (!snl_init(&ss, NETLINK_ROUTE))
736 		atf_tc_fail("snl_init() failed");
737 
738 	snl_init_writer(&ss, &nw);
739 
740 	struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK);
741 	ATF_CHECK(hdr != NULL);
742 	ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
743 	ATF_CHECK(snl_finalize_msg(&nw) != NULL);
744 	uint32_t seq_id = hdr->nlmsg_seq;
745 
746 	ATF_CHECK(snl_send_message(&ss, hdr));
747 
748 	struct snl_errmsg_data e = {};
749 	int count = 0;
750 
751 	while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
752 		count++;
753 	}
754 	ATF_REQUIRE(e.error == 0);
755 
756 	ATF_REQUIRE_MSG(count > 0, "Empty interface list");
757 }
758 
759 ATF_TP_ADD_TCS(tp)
760 {
761 	ATF_TP_ADD_TC(tp, snl_verify_core_parsers);
762 	ATF_TP_ADD_TC(tp, snl_parse_bitset_array);
763 	ATF_TP_ADD_TC(tp, snl_verify_route_parsers);
764 	ATF_TP_ADD_TC(tp, snl_parse_vf_status);
765 	ATF_TP_ADD_TC(tp, snl_parse_vf_trunk_pcp);
766 	ATF_TP_ADD_TC(tp, snl_parse_large_vf_status);
767 	ATF_TP_ADD_TC(tp, snl_parse_empty_vf_status);
768 	ATF_TP_ADD_TC(tp, snl_parse_vf_status_error);
769 	ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped);
770 	ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped_extack);
771 	ATF_TP_ADD_TC(tp, snl_parse_errmsg_uncapped_extack);
772 	ATF_TP_ADD_TC(tp, snl_list_ifaces);
773 
774 	return (atf_no_error());
775 }
776