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