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