xref: /freebsd/sbin/ifconfig/ifvfstatus.c (revision 41418a7cd00c4a20eb72bc8c315c0e364d4e4ad2)
1*41418a7cSKevin Bowling /*
2*41418a7cSKevin Bowling  * SPDX-License-Identifier: BSD-2-Clause
3*41418a7cSKevin Bowling  *
4*41418a7cSKevin Bowling  * Copyright (c) 2019 Intel Corporation
5*41418a7cSKevin Bowling  * Copyright (c) 2026 Kevin Bowling <kbowling@FreeBSD.org>
6*41418a7cSKevin Bowling  */
7*41418a7cSKevin Bowling 
8*41418a7cSKevin Bowling #include <sys/types.h>
9*41418a7cSKevin Bowling 
10*41418a7cSKevin Bowling #include <net/ethernet.h>
11*41418a7cSKevin Bowling #include <net/if.h>
12*41418a7cSKevin Bowling 
13*41418a7cSKevin Bowling #include <err.h>
14*41418a7cSKevin Bowling #include <errno.h>
15*41418a7cSKevin Bowling #include <inttypes.h>
16*41418a7cSKevin Bowling #include <stdio.h>
17*41418a7cSKevin Bowling 
18*41418a7cSKevin Bowling #include "ifconfig.h"
19*41418a7cSKevin Bowling 
20*41418a7cSKevin Bowling static void
vf_group_begin(bool * printed,const char * name)21*41418a7cSKevin Bowling vf_group_begin(bool *printed, const char *name)
22*41418a7cSKevin Bowling {
23*41418a7cSKevin Bowling 
24*41418a7cSKevin Bowling 	if (!*printed) {
25*41418a7cSKevin Bowling 		printf("\t\t\t%s:", name);
26*41418a7cSKevin Bowling 		*printed = true;
27*41418a7cSKevin Bowling 	}
28*41418a7cSKevin Bowling }
29*41418a7cSKevin Bowling 
30*41418a7cSKevin Bowling static void
vf_group_end(bool printed)31*41418a7cSKevin Bowling vf_group_end(bool printed)
32*41418a7cSKevin Bowling {
33*41418a7cSKevin Bowling 
34*41418a7cSKevin Bowling 	if (printed)
35*41418a7cSKevin Bowling 		putchar('\n');
36*41418a7cSKevin Bowling }
37*41418a7cSKevin Bowling 
38*41418a7cSKevin Bowling static void
vf_print_rate(const char * name,uint64_t rate,const char * zero)39*41418a7cSKevin Bowling vf_print_rate(const char *name, uint64_t rate, const char *zero)
40*41418a7cSKevin Bowling {
41*41418a7cSKevin Bowling 
42*41418a7cSKevin Bowling 	if (rate == 0)
43*41418a7cSKevin Bowling 		printf(" %s=%s", name, zero);
44*41418a7cSKevin Bowling 	else if (rate % IF_Mbps(1) == 0)
45*41418a7cSKevin Bowling 		printf(" %s=%" PRIu64 "Mbps", name, rate / IF_Mbps(1));
46*41418a7cSKevin Bowling 	else
47*41418a7cSKevin Bowling 		printf(" %s=%" PRIu64 "bps", name, rate);
48*41418a7cSKevin Bowling }
49*41418a7cSKevin Bowling 
50*41418a7cSKevin Bowling static const char *
vf_link_state_name(enum ifconfig_vf_link_state state)51*41418a7cSKevin Bowling vf_link_state_name(enum ifconfig_vf_link_state state)
52*41418a7cSKevin Bowling {
53*41418a7cSKevin Bowling 
54*41418a7cSKevin Bowling 	switch (state) {
55*41418a7cSKevin Bowling 	case IFCONFIG_VF_LINK_DOWN:
56*41418a7cSKevin Bowling 		return ("down");
57*41418a7cSKevin Bowling 	case IFCONFIG_VF_LINK_UP:
58*41418a7cSKevin Bowling 		return ("up");
59*41418a7cSKevin Bowling 	case IFCONFIG_VF_LINK_AUTO:
60*41418a7cSKevin Bowling 		return ("auto");
61*41418a7cSKevin Bowling 	default:
62*41418a7cSKevin Bowling 		return ("unknown");
63*41418a7cSKevin Bowling 	}
64*41418a7cSKevin Bowling }
65*41418a7cSKevin Bowling 
66*41418a7cSKevin Bowling static const char *
vf_vlan_mode_name(enum ifconfig_vf_vlan_mode mode)67*41418a7cSKevin Bowling vf_vlan_mode_name(enum ifconfig_vf_vlan_mode mode)
68*41418a7cSKevin Bowling {
69*41418a7cSKevin Bowling 
70*41418a7cSKevin Bowling 	switch (mode) {
71*41418a7cSKevin Bowling 	case IFCONFIG_VF_VLAN_ACCESS:
72*41418a7cSKevin Bowling 		return ("access");
73*41418a7cSKevin Bowling 	case IFCONFIG_VF_VLAN_TRUNK:
74*41418a7cSKevin Bowling 		return ("trunk");
75*41418a7cSKevin Bowling 	default:
76*41418a7cSKevin Bowling 		return ("unknown");
77*41418a7cSKevin Bowling 	}
78*41418a7cSKevin Bowling }
79*41418a7cSKevin Bowling 
80*41418a7cSKevin Bowling static void
vf_print_vlan_proto(uint16_t proto)81*41418a7cSKevin Bowling vf_print_vlan_proto(uint16_t proto)
82*41418a7cSKevin Bowling {
83*41418a7cSKevin Bowling 
84*41418a7cSKevin Bowling 	switch (proto) {
85*41418a7cSKevin Bowling 	case ETHERTYPE_VLAN:
86*41418a7cSKevin Bowling 		printf("802.1q");
87*41418a7cSKevin Bowling 		break;
88*41418a7cSKevin Bowling 	case ETHERTYPE_QINQ:
89*41418a7cSKevin Bowling 		printf("802.1ad");
90*41418a7cSKevin Bowling 		break;
91*41418a7cSKevin Bowling 	default:
92*41418a7cSKevin Bowling 		printf("0x%04x", proto);
93*41418a7cSKevin Bowling 		break;
94*41418a7cSKevin Bowling 	}
95*41418a7cSKevin Bowling }
96*41418a7cSKevin Bowling 
97*41418a7cSKevin Bowling static void
vf_driver_field(const struct ifconfig_vf_extension_field * field)98*41418a7cSKevin Bowling vf_driver_field(const struct ifconfig_vf_extension_field *field)
99*41418a7cSKevin Bowling {
100*41418a7cSKevin Bowling 	const uint8_t *data;
101*41418a7cSKevin Bowling 	size_t i, length;
102*41418a7cSKevin Bowling 
103*41418a7cSKevin Bowling 	printf(" %s=", field->name);
104*41418a7cSKevin Bowling 	switch (field->type) {
105*41418a7cSKevin Bowling 	case IFCONFIG_VF_EXT_BOOL:
106*41418a7cSKevin Bowling 		printf("%s", field->value.boolean ? "yes" : "no");
107*41418a7cSKevin Bowling 		break;
108*41418a7cSKevin Bowling 	case IFCONFIG_VF_EXT_NUMBER:
109*41418a7cSKevin Bowling 		printf("%" PRIu64, field->value.number);
110*41418a7cSKevin Bowling 		break;
111*41418a7cSKevin Bowling 	case IFCONFIG_VF_EXT_STRING:
112*41418a7cSKevin Bowling 		printf("%s", field->value.string);
113*41418a7cSKevin Bowling 		break;
114*41418a7cSKevin Bowling 	case IFCONFIG_VF_EXT_BINARY:
115*41418a7cSKevin Bowling 		data = field->value.binary.data;
116*41418a7cSKevin Bowling 		length = field->value.binary.length;
117*41418a7cSKevin Bowling 		printf("0x");
118*41418a7cSKevin Bowling 		for (i = 0; i < length; i++)
119*41418a7cSKevin Bowling 			printf("%02x", data[i]);
120*41418a7cSKevin Bowling 		break;
121*41418a7cSKevin Bowling 	default:
122*41418a7cSKevin Bowling 		break;
123*41418a7cSKevin Bowling 	}
124*41418a7cSKevin Bowling }
125*41418a7cSKevin Bowling 
126*41418a7cSKevin Bowling static void
vf_driver_status(const struct ifconfig_vf_info * vf)127*41418a7cSKevin Bowling vf_driver_status(const struct ifconfig_vf_info *vf)
128*41418a7cSKevin Bowling {
129*41418a7cSKevin Bowling 	const struct ifconfig_vf_extension *driver;
130*41418a7cSKevin Bowling 	const struct ifconfig_vf_extension_field *field;
131*41418a7cSKevin Bowling 	size_t i, j;
132*41418a7cSKevin Bowling 
133*41418a7cSKevin Bowling 	for (i = 0; i < vf->num_extensions; i++) {
134*41418a7cSKevin Bowling 		driver = &vf->extensions[i];
135*41418a7cSKevin Bowling 		printf("\t\t\t%s: version=%u", driver->name,
136*41418a7cSKevin Bowling 		    driver->version);
137*41418a7cSKevin Bowling 		for (j = 0; j < driver->num_fields; j++) {
138*41418a7cSKevin Bowling 			field = &driver->fields[j];
139*41418a7cSKevin Bowling 			vf_driver_field(field);
140*41418a7cSKevin Bowling 		}
141*41418a7cSKevin Bowling 		putchar('\n');
142*41418a7cSKevin Bowling 	}
143*41418a7cSKevin Bowling }
144*41418a7cSKevin Bowling 
145*41418a7cSKevin Bowling void
vf_status(if_ctx * ctx)146*41418a7cSKevin Bowling vf_status(if_ctx *ctx)
147*41418a7cSKevin Bowling {
148*41418a7cSKevin Bowling 	struct ifconfig_vf_status *status;
149*41418a7cSKevin Bowling 	const struct ifconfig_vf_info *vf;
150*41418a7cSKevin Bowling 	const struct ether_addr *mac;
151*41418a7cSKevin Bowling 	const char *mode;
152*41418a7cSKevin Bowling 	uint64_t speed;
153*41418a7cSKevin Bowling 	bool printed;
154*41418a7cSKevin Bowling 	size_t i;
155*41418a7cSKevin Bowling 	int error;
156*41418a7cSKevin Bowling 
157*41418a7cSKevin Bowling 	if (ifconfig_get_vf_status(lifh, ctx->ifname, &status) != 0) {
158*41418a7cSKevin Bowling 		error = ifconfig_err_errno(lifh);
159*41418a7cSKevin Bowling 		if (error != EOPNOTSUPP)
160*41418a7cSKevin Bowling 			warnc(error, "%s: VF status", ctx->ifname);
161*41418a7cSKevin Bowling 		return;
162*41418a7cSKevin Bowling 	}
163*41418a7cSKevin Bowling 
164*41418a7cSKevin Bowling 	if (status->pf_link_state_present) {
165*41418a7cSKevin Bowling 		printf("\tVF-visible PF link: state=%s",
166*41418a7cSKevin Bowling 		    vf_link_state_name(status->pf_link_state));
167*41418a7cSKevin Bowling 	}
168*41418a7cSKevin Bowling 	speed = status->pf_link_speed;
169*41418a7cSKevin Bowling 	if (status->pf_link_speed_present) {
170*41418a7cSKevin Bowling 		if (speed % IF_Mbps(1) == 0)
171*41418a7cSKevin Bowling 			printf(" speed=%" PRIu64 "Mbps", speed / IF_Mbps(1));
172*41418a7cSKevin Bowling 		else
173*41418a7cSKevin Bowling 			printf(" speed=%" PRIu64 "bps", speed);
174*41418a7cSKevin Bowling 	}
175*41418a7cSKevin Bowling 	if (status->pf_link_state_present || status->pf_link_speed_present)
176*41418a7cSKevin Bowling 		putchar('\n');
177*41418a7cSKevin Bowling 
178*41418a7cSKevin Bowling 	printf("\tvirtual functions: %zu\n", status->num_vfs);
179*41418a7cSKevin Bowling 	for (i = 0; i < status->num_vfs; i++) {
180*41418a7cSKevin Bowling 		vf = status->vfs[i];
181*41418a7cSKevin Bowling 		printf("\t\tvf %3u:\n", vf->index);
182*41418a7cSKevin Bowling 
183*41418a7cSKevin Bowling 		printed = false;
184*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_MAC)) != 0) {
185*41418a7cSKevin Bowling 			mac = (const struct ether_addr *)(const void *)vf->mac;
186*41418a7cSKevin Bowling 			vf_group_begin(&printed, "identity");
187*41418a7cSKevin Bowling 			printf(" mac=%s", ether_ntoa(mac));
188*41418a7cSKevin Bowling 		}
189*41418a7cSKevin Bowling 		vf_group_end(printed);
190*41418a7cSKevin Bowling 
191*41418a7cSKevin Bowling 		printed = false;
192*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_CONFIGURED)) != 0) {
193*41418a7cSKevin Bowling 			vf_group_begin(&printed, "state");
194*41418a7cSKevin Bowling 			printf(" configured=%s", vf->configured ? "yes" : "no");
195*41418a7cSKevin Bowling 		}
196*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_INITIALIZED)) != 0) {
197*41418a7cSKevin Bowling 			vf_group_begin(&printed, "state");
198*41418a7cSKevin Bowling 			printf(" initialized=%s", vf->initialized ? "yes" : "no");
199*41418a7cSKevin Bowling 		}
200*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_TRAFFIC_ALLOWED)) != 0) {
201*41418a7cSKevin Bowling 			vf_group_begin(&printed, "state");
202*41418a7cSKevin Bowling 			printf(" traffic=%s", vf->traffic_allowed ?
203*41418a7cSKevin Bowling 			    "allowed" : "denied");
204*41418a7cSKevin Bowling 		}
205*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_FAULT_BLOCKED)) != 0) {
206*41418a7cSKevin Bowling 			vf_group_begin(&printed, "state");
207*41418a7cSKevin Bowling 			printf(" fault-blocked=%s", vf->fault_blocked ?
208*41418a7cSKevin Bowling 			    "yes" : "no");
209*41418a7cSKevin Bowling 		}
210*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_QUARANTINED)) != 0) {
211*41418a7cSKevin Bowling 			vf_group_begin(&printed, "state");
212*41418a7cSKevin Bowling 			printf(" quarantined=%s", vf->quarantined ? "yes" : "no");
213*41418a7cSKevin Bowling 		}
214*41418a7cSKevin Bowling 		vf_group_end(printed);
215*41418a7cSKevin Bowling 
216*41418a7cSKevin Bowling 		printed = false;
217*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_NUM_TX_QUEUES)) != 0) {
218*41418a7cSKevin Bowling 			vf_group_begin(&printed, "resources");
219*41418a7cSKevin Bowling 			printf(" tx-queues=%u", vf->tx_queue_count);
220*41418a7cSKevin Bowling 		}
221*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_NUM_RX_QUEUES)) != 0) {
222*41418a7cSKevin Bowling 			vf_group_begin(&printed, "resources");
223*41418a7cSKevin Bowling 			printf(" rx-queues=%u", vf->rx_queue_count);
224*41418a7cSKevin Bowling 		}
225*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_MIN_TX_RATE)) != 0) {
226*41418a7cSKevin Bowling 			vf_group_begin(&printed, "resources");
227*41418a7cSKevin Bowling 			vf_print_rate("min-tx-rate", vf->min_tx_rate_bps, "none");
228*41418a7cSKevin Bowling 		}
229*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_MAX_TX_RATE)) != 0) {
230*41418a7cSKevin Bowling 			vf_group_begin(&printed, "resources");
231*41418a7cSKevin Bowling 			vf_print_rate("max-tx-rate", vf->max_tx_rate_bps,
232*41418a7cSKevin Bowling 			    "unlimited");
233*41418a7cSKevin Bowling 		}
234*41418a7cSKevin Bowling 		vf_group_end(printed);
235*41418a7cSKevin Bowling 
236*41418a7cSKevin Bowling 		printed = false;
237*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_VLAN_MODE)) != 0) {
238*41418a7cSKevin Bowling 			mode = vf_vlan_mode_name(vf->vlan_mode);
239*41418a7cSKevin Bowling 			vf_group_begin(&printed, "vlan");
240*41418a7cSKevin Bowling 			printf(" mode=%s", mode);
241*41418a7cSKevin Bowling 			if (vf->vlan_mode == IFCONFIG_VF_VLAN_ACCESS &&
242*41418a7cSKevin Bowling 			    (vf->fields & (1ULL << IFLAF_VF_VLAN)) != 0)
243*41418a7cSKevin Bowling 				printf(" vid=%u", vf->vlan);
244*41418a7cSKevin Bowling 			if (vf->vlan_mode == IFCONFIG_VF_VLAN_ACCESS &&
245*41418a7cSKevin Bowling 			    (vf->fields & (1ULL << IFLAF_VF_VLAN_PCP)) != 0)
246*41418a7cSKevin Bowling 				printf(" pcp=%u", vf->vlan_pcp);
247*41418a7cSKevin Bowling 			if (vf->vlan_mode == IFCONFIG_VF_VLAN_ACCESS &&
248*41418a7cSKevin Bowling 			    (vf->fields & (1ULL << IFLAF_VF_VLAN_PROTO)) != 0) {
249*41418a7cSKevin Bowling 				printf(" proto=");
250*41418a7cSKevin Bowling 				vf_print_vlan_proto(vf->vlan_proto);
251*41418a7cSKevin Bowling 			}
252*41418a7cSKevin Bowling 		}
253*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_VLAN_COUNT)) != 0) {
254*41418a7cSKevin Bowling 			vf_group_begin(&printed, "vlan");
255*41418a7cSKevin Bowling 			printf(" filters=%u", vf->vlan_count);
256*41418a7cSKevin Bowling 		}
257*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_VLAN_LIMIT)) != 0) {
258*41418a7cSKevin Bowling 			vf_group_begin(&printed, "vlan");
259*41418a7cSKevin Bowling 			printf(" limit=%u", vf->vlan_limit);
260*41418a7cSKevin Bowling 		}
261*41418a7cSKevin Bowling 		vf_group_end(printed);
262*41418a7cSKevin Bowling 
263*41418a7cSKevin Bowling 		printed = false;
264*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_ALLOW_SET_MAC)) != 0) {
265*41418a7cSKevin Bowling 			vf_group_begin(&printed, "policy");
266*41418a7cSKevin Bowling 			printf(" set-mac=%s", vf->allow_set_mac ?
267*41418a7cSKevin Bowling 			    "allowed" : "denied");
268*41418a7cSKevin Bowling 		}
269*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_ALLOW_SET_VLAN)) != 0) {
270*41418a7cSKevin Bowling 			vf_group_begin(&printed, "policy");
271*41418a7cSKevin Bowling 			printf(" set-vlan=%s", vf->allow_set_vlan ?
272*41418a7cSKevin Bowling 			    "allowed" : "denied");
273*41418a7cSKevin Bowling 		}
274*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_MAC_ANTI_SPOOF)) != 0) {
275*41418a7cSKevin Bowling 			vf_group_begin(&printed, "policy");
276*41418a7cSKevin Bowling 			printf(" anti-spoof=%s", vf->mac_anti_spoof ? "on" : "off");
277*41418a7cSKevin Bowling 		}
278*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_ALLOW_PROMISC)) != 0) {
279*41418a7cSKevin Bowling 			vf_group_begin(&printed, "policy");
280*41418a7cSKevin Bowling 			printf(" promisc=%s", vf->allow_promisc ?
281*41418a7cSKevin Bowling 			    "allowed" : "denied");
282*41418a7cSKevin Bowling 		}
283*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_LINK_STATE_POLICY)) != 0) {
284*41418a7cSKevin Bowling 			vf_group_begin(&printed, "policy");
285*41418a7cSKevin Bowling 			printf(" link-state=%s",
286*41418a7cSKevin Bowling 			    vf_link_state_name(vf->link_state_policy));
287*41418a7cSKevin Bowling 		}
288*41418a7cSKevin Bowling 		vf_group_end(printed);
289*41418a7cSKevin Bowling 
290*41418a7cSKevin Bowling 		printed = false;
291*41418a7cSKevin Bowling 		if ((vf->fields & (1ULL << IFLAF_VF_API_VERSION)) != 0) {
292*41418a7cSKevin Bowling 			vf_group_begin(&printed, "protocol");
293*41418a7cSKevin Bowling 			printf(" api=%s", vf->api_version);
294*41418a7cSKevin Bowling 		}
295*41418a7cSKevin Bowling 		vf_group_end(printed);
296*41418a7cSKevin Bowling 
297*41418a7cSKevin Bowling 		vf_driver_status(vf);
298*41418a7cSKevin Bowling 	}
299*41418a7cSKevin Bowling 	ifconfig_free_vf_status(status);
300*41418a7cSKevin Bowling }
301