Line data Source code
1 : /*
2 : * vr_dpdk_info.c - DPDK specific callback functions for vr_info .
3 : *
4 : * Copyright (c) 2020 Juniper Networks, Inc. All rights reserved.
5 : * Copyright Contributors to the OpenSDN project
6 : */
7 : #include <vr_os.h>
8 : #include <vr_types.h>
9 : #include <string.h>
10 : #include <sys/types.h>
11 : #include <sys/stat.h>
12 : #include <fcntl.h>
13 :
14 : #include <vr_packet.h>
15 : #include <rte_eth_bond.h>
16 : #include <rte_ethdev.h>
17 : #include <rte_port_ethdev.h>
18 : #include <rte_eth_bond_8023ad.h>
19 : #include <rte_pmd_i40e.h>
20 : #include <rte_malloc.h>
21 : #include <rte_mempool.h>
22 : #include "vr_message.h"
23 : #include "vr_btable.h"
24 : #include "vr_dpdk.h"
25 : #include "vrouter.h"
26 :
27 : #define SEPERATOR 70
28 : #define LINE 200
29 : #define MAXBITS 8
30 : #define I40E_MAX_PROFILE_NUM 16
31 :
32 : enum segments {
33 : RX_PACKETS,
34 : RX_BYTES,
35 : TX_PACKETS,
36 : TX_BYTES,
37 : ERRORS,
38 : OTHERS
39 : };
40 :
41 : /* NOTE: Callback API's need to be registered in vrouter/include/vr_info.h
42 : * under VR_INFO_REG(X) macro.
43 : * All callback API's should start with "dpdk_<fn.name>"
44 : * Register Format: X(MSG, <fn.name>) \
45 : * eg: X(INFO_BOND, info_get_bond)
46 : */
47 :
48 : int
49 0 : dpdk_info_get_dpdk_version(VR_INFO_ARGS)
50 : {
51 : extern const char *ContrailBuildInfo;
52 :
53 0 : VR_INFO_BUF_INIT();
54 :
55 0 : VI_PRINTF("DPDK Version: %s\n",
56 : rte_version());
57 0 : VI_PRINTF("vRouter version: %s\n\n", ContrailBuildInfo);
58 0 : return 0;
59 : }
60 :
61 : int
62 0 : get_port_states(VR_INFO_ARGS, uint8_t state)
63 : {
64 0 : VR_INFO_DEC();
65 0 : int i = 0, cur = 0;
66 0 : char *states[] = {"ACT", "TIMEOUT", "AGG", "SYNC", "COL", "DIST",
67 : "DEF", "EXP"};
68 0 : uint8_t orig_state = state;
69 0 : char port_states[LINE] = "";
70 :
71 : /* Iterating through each bit */
72 0 : while (i <= MAXBITS){
73 0 : if ((1 & state) && (cur < LINE)){
74 0 : cur += snprintf(port_states + cur, LINE - cur, "%s ", states[i]);
75 : }
76 0 : state = state >> 1;
77 0 : i++;
78 : }
79 0 : VI_PRINTF("\tport state: %d (%s) \n\n", orig_state, port_states);
80 0 : return 0;
81 : }
82 :
83 : /* dpdk_info_get_bond provide the bond master & slave information */
84 : static int
85 0 : dpdk_bond_mode_8023ad(VR_INFO_ARGS, uint16_t port_id)
86 : {
87 0 : VR_INFO_DEC();
88 : int ret;
89 0 : char *lacp_rate[] = {"slow", "fast"};
90 :
91 0 : VI_PRINTF("802.3ad info :\n");
92 :
93 0 : VI_PRINTF("LACP Rate: %s\n",
94 : lacp_rate[rte_eth_bond_lacp_rate_get(port_id)]);
95 :
96 0 : ret = rte_eth_bond_8023ad_agg_selection_get(port_id);
97 0 : switch(ret) {
98 0 : case AGG_COUNT:
99 0 : VI_PRINTF("Aggregator selection policy (ad_select): Count\n");
100 0 : break;
101 0 : case AGG_BANDWIDTH:
102 0 : VI_PRINTF("Aggregator selection policy (ad_select): Bandwidth\n");
103 0 : break;
104 0 : case AGG_STABLE:
105 0 : VI_PRINTF("Aggregator selection policy (ad_select): Stable\n");
106 0 : break;
107 0 : default:
108 0 : VI_PRINTF("Aggregator selection policy (ad_select): Null\n");
109 : }
110 :
111 0 : return 0;
112 : }
113 :
114 : static int
115 0 : dpdk_bond_info_mii_status(VR_INFO_ARGS, uint16_t port_id,
116 : struct rte_eth_link *link)
117 : {
118 0 : VR_INFO_DEC();
119 0 : char *status[] = {"DOWN", "UP"};
120 :
121 0 : VI_PRINTF("MII status: %s\n", status[link->link_status]);
122 0 : VI_PRINTF("MII Link Speed: %d Mbps\n", link->link_speed);
123 0 : if(rte_eth_bond_mode_get(port_id) == BONDING_MODE_8023AD) {
124 0 : VI_PRINTF("MII Polling Interval (ms): %d\n",
125 : rte_eth_bond_link_monitoring_get(port_id));
126 : }
127 0 : return 0;
128 : }
129 :
130 : static int
131 0 : dpdk_bond_info_show_slave(VR_INFO_ARGS, uint16_t port_id,
132 : struct vr_dpdk_ethdev *ethdev)
133 : {
134 0 : VR_INFO_DEC();
135 : int i, ret;
136 : uint16_t slave_id;
137 0 : char *duplex[] = {"half", "full"};
138 : struct rte_ether_addr mac_addr;
139 : struct rte_eth_link link;
140 : char name[VR_INTERFACE_NAME_LEN];
141 : struct rte_eth_bond_8023ad_slave_info info;
142 :
143 : /* Display bond slave inforamtion */
144 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
145 0 : slave_id = ethdev->ethdev_slaves[i];
146 :
147 0 : ret = rte_eth_dev_get_name_by_port(slave_id, name);
148 0 : if (ret != 0) {
149 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting slave interface name "
150 : "slave_id:%d \n", __func__, slave_id);
151 0 : return VR_INFO_FAILED;
152 : }
153 :
154 :
155 0 : VI_PRINTF("Slave Interface(%d): %s \n", i, name);
156 0 : VI_PRINTF("Slave Interface Driver: %s\n",
157 : rte_eth_devices[slave_id].device->driver->name);
158 :
159 0 : rte_eth_link_get_nowait(slave_id, &link);
160 0 : ret = dpdk_bond_info_mii_status(msg_req, slave_id, &link);
161 0 : if (ret < 0) {
162 0 : return VR_INFO_FAILED;
163 : }
164 :
165 0 : ret = rte_eth_bond_8023ad_slave_info(port_id, slave_id, &info);
166 0 : if (ret == 0) {
167 0 : VI_PRINTF("Permanent HW addr:"MAC_FORMAT "\n",
168 : MAC_VALUE(info.actor.system.addr_bytes));
169 0 : VI_PRINTF("Aggregator ID: %d\n", info.agg_port_id);
170 :
171 0 : VI_PRINTF("Duplex: %s\n", duplex[link.link_duplex]);
172 :
173 0 : rte_eth_macaddr_get(slave_id, &mac_addr);
174 0 : VI_PRINTF("Bond MAC addr:"MAC_FORMAT "\n",
175 : MAC_VALUE(mac_addr.addr_bytes));
176 :
177 0 : VI_PRINTF("Details actor lacp pdu: \n");
178 0 : VI_PRINTF("\tsystem priority: %"PRIu16"\n",
179 : htons(info.actor.system_priority));
180 0 : VI_PRINTF("\tsystem mac address:"MAC_FORMAT "\n",
181 : MAC_VALUE(info.actor.system.addr_bytes));
182 0 : VI_PRINTF("\tport key: %"PRIu16"\n", htons(info.actor.key));
183 0 : VI_PRINTF("\tport priority: %"PRIu16 "\n",
184 : htons(info.actor.port_priority));
185 0 : VI_PRINTF("\tport number: %"PRIu16"\n",
186 : htons(info.actor.port_number));
187 0 : get_port_states(msg_req, info.actor_state);
188 :
189 0 : VI_PRINTF("Details partner lacp pdu: \n");
190 0 : VI_PRINTF("\tsystem priority: %"PRIu16"\n",
191 : htons(info.partner.system_priority));
192 0 : VI_PRINTF("\tsystem mac address:"MAC_FORMAT "\n",
193 : MAC_VALUE(info.partner.system.addr_bytes));
194 0 : VI_PRINTF("\tport key: %"PRIu16"\n", htons(info.partner.key));
195 0 : VI_PRINTF("\tport priority: %"PRIu16"\n",
196 : htons(info.partner.port_priority));
197 0 : VI_PRINTF("\tport number: %"PRIu16"\n",
198 : htons(info.partner.port_number));
199 0 : get_port_states(msg_req, info.partner_state);
200 : } else {
201 0 : VI_PRINTF("\n");
202 : }
203 : }
204 0 : return 0;
205 : }
206 :
207 : static int
208 0 : dpdk_bond_info_show_master(VR_INFO_ARGS, uint16_t port_id,
209 : struct vr_dpdk_ethdev *ethdev)
210 : {
211 0 : VR_INFO_DEC();
212 : int ret, bond_mode;
213 : uint16_t slave_id;
214 : struct rte_eth_link link;
215 : struct rte_eth_bond_8023ad_slave_info info;
216 :
217 : /* Get bond mode */
218 0 : bond_mode = rte_eth_bond_mode_get(port_id);
219 0 : switch (bond_mode) {
220 0 : case BONDING_MODE_ROUND_ROBIN:
221 0 : VI_PRINTF("Bonding Mode: Round Robin\n");
222 0 : break;
223 0 : case BONDING_MODE_ACTIVE_BACKUP:
224 0 : VI_PRINTF("Bonding Mode: Active Backup\n");
225 0 : break;
226 0 : case BONDING_MODE_BALANCE:
227 0 : VI_PRINTF("Bonding Mode: Balance\n");
228 0 : break;
229 0 : case BONDING_MODE_BROADCAST:
230 0 : VI_PRINTF("Bonding Mode: Broadcast\n");
231 0 : break;
232 0 : case BONDING_MODE_8023AD:
233 0 : VI_PRINTF("Bonding Mode: 802.3AD Dynamic Link Aggregation\n");
234 0 : break;
235 0 : case BONDING_MODE_TLB:
236 0 : VI_PRINTF("Bonding Mode: Adaptive TLB(Trnasmit Load Balancing)\n");
237 0 : break;
238 0 : case BONDING_MODE_ALB:
239 0 : VI_PRINTF("Bonding Mode: Adaptive Load Balancing(Tx/Rx)\n");
240 0 : break;
241 0 : default:
242 0 : VI_PRINTF("Bonding Mode: None\n");
243 : }
244 :
245 : /* Transmit Hash Policy */
246 0 : ret = rte_eth_bond_xmit_policy_get(port_id);
247 0 : switch (ret) {
248 0 : case BALANCE_XMIT_POLICY_LAYER2:
249 0 : VI_PRINTF("Transmit Hash Policy: Layer 2 (Ethernet MAC)\n");
250 0 : break;
251 0 : case BALANCE_XMIT_POLICY_LAYER23:
252 0 : VI_PRINTF("Transmit Hash Policy: Layer 2+3 (Ethernet MAC + "
253 : "IP Addresses) transmit load balancing\n");
254 0 : break;
255 0 : case BALANCE_XMIT_POLICY_LAYER34:
256 0 : VI_PRINTF("Transmit Hash Policy: Layer 3+4 (IP Addresses + "
257 : "UDP Ports) transmit load balancing\n");
258 0 : break;
259 0 : default:
260 0 : VI_PRINTF("Transmit Hash Policy: None\n");
261 : }
262 :
263 0 : rte_eth_link_get_nowait(port_id, &link);
264 0 : ret = dpdk_bond_info_mii_status(msg_req, port_id, &link);
265 0 : if (ret < 0) {
266 0 : return VR_INFO_FAILED;
267 : }
268 :
269 0 : VI_PRINTF("Up Delay (ms): %d\n",
270 : rte_eth_bond_link_up_prop_delay_get(port_id));
271 0 : VI_PRINTF("Down Delay (ms): %d\n",
272 : rte_eth_bond_link_down_prop_delay_get(port_id));
273 0 : if(rte_eth_devices[port_id].device &&
274 0 : rte_eth_devices[port_id].device->driver) {
275 0 : VI_PRINTF("Driver: %s\n\n",
276 : rte_eth_devices[port_id].device->driver->name);
277 : }
278 :
279 0 : if (bond_mode == BONDING_MODE_8023AD) {
280 0 : ret = dpdk_bond_mode_8023ad(msg_req, port_id);
281 0 : if (ret < 0) {
282 0 : return VR_INFO_FAILED;
283 : }
284 : }
285 :
286 0 : slave_id = ethdev->ethdev_slaves[0];
287 :
288 0 : ret = rte_eth_bond_8023ad_slave_info(port_id, slave_id, &info);
289 0 : if (ret != 0) {
290 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting slave info bond:%d slave:%d\n",
291 : __func__, port_id, slave_id);
292 0 : return VR_INFO_FAILED;
293 : }
294 :
295 0 : VI_PRINTF("System priority: %"PRIu16"\n", htons(info.actor.system_priority));
296 0 : VI_PRINTF("System MAC address:"MAC_FORMAT "\n",
297 : MAC_VALUE(info.actor.system.addr_bytes));
298 0 : VI_PRINTF("Active Aggregator Info: \n");
299 0 : VI_PRINTF("\tAggregator ID: %"PRIu16"\n", htons(info.agg_port_id));
300 0 : VI_PRINTF("\tNumber of ports: %d \n", ethdev->ethdev_nb_slaves);
301 0 : VI_PRINTF("\tActor Key: %"PRIu16"\n", htons(info.actor.key));
302 0 : VI_PRINTF("\tPartner Key: %"PRIu16"\n", htons(info.partner.key));
303 0 : VI_PRINTF("\tPartner Mac Address: "MAC_FORMAT "\n\n",
304 : MAC_VALUE(info.partner.system.addr_bytes));
305 0 : return 0;
306 : }
307 :
308 : /* dpdk_info_get_bond provide the bond master & slave information */
309 : int
310 0 : dpdk_info_get_bond(VR_INFO_ARGS)
311 : {
312 : uint16_t port_id;
313 : struct vr_dpdk_bond_port_list port_list;
314 : struct vr_dpdk_ethdev *ethdev;
315 0 : char name[VR_INTERFACE_NAME_LEN] = "";
316 : int ret, i;
317 :
318 : /* If output buffer size(--buffsz) is sent from CLI, then allocate with
319 : that size else allocate with default size */
320 0 : VR_INFO_BUF_INIT();
321 : /* Get the port_id list for master, Incase of non-bond devices, it return here */
322 0 : if (!dpdk_find_bond_port_id_list(&port_list)) {
323 0 : RTE_LOG(ERR, VROUTER, "%s: Port Id list is invalid\n", __func__);
324 0 : return -1;
325 : }
326 :
327 0 : VI_PRINTF("No. of bond id available: %d\n", port_list.intf_count);
328 0 : for (i = 0; i < port_list.intf_count ; i++) {
329 0 : port_id = port_list.intf_list[i];
330 : /* Get the ethdev for master port. */
331 0 : ethdev = &vr_dpdk.ethdevs[port_id];
332 0 : if (ethdev == NULL ||
333 0 : ethdev->ethdev_ptr == NULL) {
334 0 : RTE_LOG(ERR, VROUTER, "%s: Ethdev not available port: %d\n",
335 : __func__, port_id);
336 0 : continue;
337 : }
338 :
339 0 : rte_eth_dev_get_name_by_port(port_id, name);
340 0 : VI_PRINTF("=================================================\n");
341 0 : VI_PRINTF("|| Bond : %s No. of bond slaves: %d ||\n",
342 : name, ethdev->ethdev_nb_slaves);
343 0 : VI_PRINTF("=================================================\n");
344 :
345 0 : ret = dpdk_bond_info_show_master(msg_req, port_id, ethdev);
346 0 : if (ret < 0) {
347 0 : RTE_LOG(ERR, VROUTER, "%s failed to show master info port_id:%d(ret:%d)\n",
348 : __func__, port_id, ret);
349 : }
350 :
351 0 : ret = dpdk_bond_info_show_slave(msg_req, port_id, ethdev);
352 0 : if (ret < 0) {
353 0 : RTE_LOG(ERR, VROUTER, "%s failed to show slave info port_id:%d(ret:%d)\n",
354 : __func__, port_id, ret);
355 : }
356 : }
357 0 : return 0;
358 : }
359 :
360 : static int
361 0 : display_lacp_conf(VR_INFO_ARGS, uint16_t port_id)
362 : {
363 :
364 0 : VR_INFO_DEC();
365 0 : char *lacp_rate[] = {"slow","fast"};
366 : struct rte_eth_bond_8023ad_conf conf;
367 :
368 : /* Check LACP protocol is configured for the bond interface. */
369 0 : VI_PRINTF("LACP Rate: %s\n\n",
370 : lacp_rate[rte_eth_bond_lacp_rate_get(port_id)]);
371 :
372 0 : rte_eth_bond_8023ad_conf_get(port_id, &conf);
373 :
374 0 : VI_PRINTF("Fast periodic (ms): %d\n", conf.fast_periodic_ms);
375 0 : VI_PRINTF("Slow periodic (ms): %d\n", conf.slow_periodic_ms);
376 0 : VI_PRINTF("Short timeout (ms): %d\n", conf.short_timeout_ms);
377 0 : VI_PRINTF("Long timeout (ms): %d\n", conf.long_timeout_ms);
378 0 : VI_PRINTF("Aggregate wait timeout (ms): %d\n",
379 : conf.aggregate_wait_timeout_ms);
380 0 : VI_PRINTF("Tx period (ms): %d\n", conf.tx_period_ms);
381 0 : VI_PRINTF("Update timeout (ms): %d\n", conf.update_timeout_ms);
382 0 : VI_PRINTF("Rx marker period (ms): %d\n\n", conf.rx_marker_period_ms);
383 0 : return 0;
384 :
385 : }
386 :
387 : int
388 0 : dpdk_info_get_lacp(VR_INFO_ARGS)
389 : {
390 :
391 0 : uint16_t port_id, slave_id = 0;
392 : struct vr_dpdk_ethdev *ethdev;
393 : struct vr_dpdk_bond_port_list port_list;
394 0 : int i, j, ret = 0;
395 0 : char name[VR_INTERFACE_NAME_LEN] = "";
396 : struct rte_eth_bond_8023ad_slave_info info;
397 : uint64_t lacp_rx_cnt, lacp_tx_cnt;
398 :
399 :
400 0 : VR_INFO_BUF_INIT();
401 :
402 : /* expecting buf string to be either all or conf */
403 0 : if ((strcmp(msg_req->inbuf, "all") &&
404 0 : (strcmp(msg_req->inbuf, "conf")))) {
405 0 : RTE_LOG(ERR, VROUTER, "Invalid argument.\n");
406 0 : return -1;
407 : }
408 :
409 : /* Get the port_id list for master, Incase of non-bond devices,
410 : it return here. */
411 0 : if (!dpdk_find_bond_port_id_list(&port_list)) {
412 0 : RTE_LOG(ERR, VROUTER, "%s: Port Id is invalid\n", __func__);
413 0 : return -1;
414 : }
415 :
416 0 : VI_PRINTF("No. of bond ids: %d\n", port_list.intf_count);
417 0 : for (j = 0; j < port_list.intf_count; j++) {
418 0 : port_id = port_list.intf_list[j];
419 :
420 0 : rte_eth_dev_get_name_by_port(port_id, name);
421 0 : VI_PRINTF("=======================================\n");
422 0 : VI_PRINTF("|| Bond Interface(%d): %s ||\n", port_id, name);
423 0 : VI_PRINTF("=======================================\n");
424 :
425 0 : if (strcmp(msg_req->inbuf, "all") == 0) {
426 0 : ret = display_lacp_conf(msg_req, port_id);
427 :
428 0 : ethdev = &vr_dpdk.ethdevs[port_id];
429 0 : if (ethdev == NULL ||
430 0 : ethdev->ethdev_ptr == NULL) {
431 0 : RTE_LOG(ERR, VROUTER, "%s: Ethdev not available port id: %d\n",
432 : __func__, port_id);
433 0 : continue;
434 : }
435 :
436 : /* Displaying bond slave inforamtion */
437 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
438 0 : slave_id = ethdev->ethdev_slaves[i];
439 :
440 0 : ret = rte_eth_dev_get_name_by_port(slave_id, name);
441 0 : if (ret != 0) {
442 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting dev name "
443 : "port: %d slave: %d \n", __func__, port_id, slave_id);
444 0 : continue;
445 : }
446 :
447 0 : VI_PRINTF("Slave Interface(%d): %s \n", i, name);
448 :
449 0 : ret = rte_eth_bond_8023ad_slave_info(port_id, slave_id, &info);
450 0 : if (ret == 0) {
451 0 : VI_PRINTF("Details actor lacp pdu: \n");
452 0 : ret = get_port_states(msg_req, info.actor_state);
453 0 : if (ret < 0)
454 0 : RTE_LOG(ERR, VROUTER, "Failed to get stats for actor port: %d\n",
455 : port_id);
456 :
457 0 : VI_PRINTF("Details partner lacp pdu: \n");
458 0 : ret = get_port_states(msg_req, info.partner_state);
459 0 : if (ret < 0)
460 0 : RTE_LOG(ERR, VROUTER, "Failed to get stats for partner port=%d\n",
461 : port_id);
462 : } else {
463 0 : VI_PRINTF("Port id: %d slave id: %d Link status: DOWN\n\n", port_id, slave_id);
464 : }
465 : }
466 :
467 0 : VI_PRINTF("LACP Packet Statistics:\n");
468 0 : VI_PRINTF("\t\t Tx \t Rx\n");
469 :
470 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
471 0 : slave_id = ethdev->ethdev_slaves[i];
472 :
473 0 : ret = rte_eth_dev_get_name_by_port(slave_id, name);
474 0 : if (ret != 0) {
475 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting dev name id:%d\n",
476 : __func__, slave_id);
477 : }
478 :
479 0 : lacp_tx_cnt = rte_eth_bond_8023ad_lacp_tx_count(slave_id, 0);
480 : if (lacp_tx_cnt < 0) {
481 : RTE_LOG(ERR, VROUTER, "Failed to get lacp tx count port=%d\n",
482 : port_id);
483 : continue;
484 : }
485 :
486 0 : lacp_rx_cnt = rte_eth_bond_8023ad_lacp_rx_count(slave_id, 0);
487 : if (lacp_rx_cnt < 0) {
488 : RTE_LOG(ERR, VROUTER, "Failed to get lacp rx count port=%d\n",
489 : port_id);
490 : continue;
491 : }
492 :
493 0 : VI_PRINTF("%s\t%"PRId64"\t%"PRId64"\n", name, lacp_tx_cnt, lacp_rx_cnt);
494 : }
495 0 : VI_PRINTF("\n");
496 0 : } else if (strcmp(msg_req->inbuf, "conf") == 0) {
497 0 : ret = display_lacp_conf(msg_req, port_id);
498 : }
499 : }
500 0 : return 0;
501 : }
502 :
503 : static void
504 3 : walk_cb(struct rte_mempool *mp, void *arg __rte_unused)
505 : {
506 3 : vr_info_t *msg_req = (vr_info_t * ) arg;
507 3 : VR_INFO_DEC();
508 :
509 : /* redefining VR_INFO_FAILED to prevent VI_PRINTF
510 : to return non-void value */
511 : #undef VR_INFO_FAILED
512 : #define VR_INFO_FAILED
513 :
514 : /* redefining VR_INFO_MSG_TRUNC to prevent VI_PRINTF
515 : to return non-void value */
516 : #undef VR_INFO_MSG_TRUNC
517 : #define VR_INFO_MSG_TRUNC
518 :
519 3 : VI_PRINTF("%-20s\t", mp->name);
520 3 : VI_PRINTF("%d\t", mp->size);
521 3 : VI_PRINTF("%d\t", rte_mempool_in_use_count(mp));
522 3 : VI_PRINTF("%d\t\n", rte_mempool_avail_count(mp));
523 :
524 : #undef VR_INFO_FAILED
525 : #define VR_INFO_FAILED - 1
526 :
527 : #undef VR_INFO_MSG_TRUNC
528 : #define VR_INFO_MSG_TRUNC - 2
529 3 : return;
530 : }
531 :
532 : int
533 1 : dpdk_info_get_mempool(VR_INFO_ARGS)
534 1 : {
535 1 : int reqd_mempool = 0;
536 1 : struct rte_mempool *mp = NULL;
537 : struct rte_mempool_memhdr *memhdr;
538 1 : unsigned lcore_id = 0, common_count = 0, cache_count = 0, count = 0;
539 1 : size_t mem_len = 0;
540 1 : char col_names[] = "Name\t\t\tSize\tUsed\tAvailable";
541 : /* Adding 25 to extend the seperator a bit */
542 1 : int col_size = (sizeof(col_names) / sizeof(col_names[0])) + 25;
543 1 : char seperator[col_size];
544 :
545 1 : VR_INFO_BUF_INIT();
546 :
547 1 : if (strcmp(msg_req->inbuf, "all") == 0) {
548 1 : reqd_mempool = 1;
549 : }
550 1 : switch (reqd_mempool) {
551 0 : case 0:
552 0 : mp = rte_mempool_lookup(msg_req->inbuf);
553 0 : if (mp == NULL) {
554 0 : RTE_LOG(ERR, VROUTER, "Mempool name does not exists.\n");
555 0 : return -1;
556 : }
557 :
558 0 : VI_PRINTF("%s\n", mp->name);
559 0 : VI_PRINTF("flags = %x\n", mp->flags);
560 0 : VI_PRINTF("nb_mem_chunks = %u\n", mp->nb_mem_chunks);
561 0 : VI_PRINTF("size = %"
562 : PRIu32 "\n", mp->size);
563 0 : VI_PRINTF("populated_size = %"
564 : PRIu32 "\n", mp->populated_size);
565 0 : VI_PRINTF("header_size = %"
566 : PRIu32 "\n", mp->header_size);
567 0 : VI_PRINTF("elt_size = %"
568 : PRIu32 "\n", mp->elt_size);
569 0 : VI_PRINTF("trailer_size = %"
570 : PRIu32 "\n", mp->trailer_size);
571 0 : VI_PRINTF("total_obj_size = %"
572 : PRIu32 "\n",
573 : mp->header_size + mp->elt_size + mp->trailer_size);
574 0 : VI_PRINTF("private_data_size = %"
575 : PRIu32 "\n", mp->private_data_size);
576 :
577 0 : STAILQ_FOREACH(memhdr, &mp->mem_list, next)
578 0 : mem_len += memhdr->len;
579 0 : if (mem_len != 0) {
580 0 : VI_PRINTF("avg bytes/object = %#Lf\n",
581 : (long double) mem_len / mp->size);
582 : }
583 :
584 0 : VI_PRINTF("Internal cache infos:\n");
585 0 : VI_PRINTF("\tcache_size=%"
586 : PRIu32 "\n", mp->cache_size);
587 :
588 0 : if (mp->cache_size == 0) {
589 0 : count = 0;
590 : } else {
591 0 : for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
592 0 : cache_count = mp->local_cache[lcore_id].len;
593 0 : if (cache_count != 0) {
594 0 : VI_PRINTF("\tcache_count[%u]=%"
595 : PRIu32 "\n", lcore_id, cache_count);
596 : }
597 0 : count += cache_count;
598 : }
599 : }
600 0 : VI_PRINTF("total_cache_count=%u\n", count);
601 0 : common_count = rte_mempool_ops_get_count(mp);
602 0 : if ((cache_count + common_count) > mp->size) {
603 0 : common_count = mp->size - cache_count;
604 : }
605 0 : VI_PRINTF("common_pool_count=%u\n\n", common_count);
606 0 : break;
607 :
608 1 : case 1:
609 1 : memset(seperator, '-', col_size);
610 1 : seperator[col_size-1] = '\0';
611 1 : VI_PRINTF("%s\n", seperator);
612 1 : VI_PRINTF("%s\n", col_names);
613 1 : VI_PRINTF("%s\n", seperator);
614 1 : rte_mempool_walk(walk_cb, msg_req);
615 1 : VI_PRINTF("\n\n");
616 1 : break;
617 :
618 : }
619 1 : return 0;
620 : }
621 :
622 : static int
623 0 : display_eth_stats(VR_INFO_ARGS, struct rte_eth_stats eth_stats)
624 : {
625 :
626 0 : VR_INFO_DEC();
627 : int i, queue_size;
628 : char seperator[SEPERATOR];
629 :
630 0 : VI_PRINTF("RX Device Packets:%"
631 : PRId64 ", Bytes:%"
632 : PRId64 ", Errors:%"
633 : PRId64 ", Nombufs:%"
634 : PRId64 "\n", eth_stats.ipackets,
635 : eth_stats.ibytes, eth_stats.ierrors, eth_stats.rx_nombuf);
636 0 : VI_PRINTF("Dropped RX Packets:%"
637 : PRId64 "\n", eth_stats.imissed);
638 0 : VI_PRINTF("TX Device Packets:%"
639 : PRId64 ", Bytes:%"
640 : PRId64 ", Errors:%"
641 : PRId64 "\n", eth_stats.opackets, eth_stats.obytes, eth_stats.oerrors);
642 :
643 0 : queue_size = sizeof(eth_stats.q_ipackets) / sizeof(eth_stats.q_ipackets[0]);
644 0 : memset(seperator, '-', SEPERATOR);
645 0 : seperator[SEPERATOR-1] = '\0';
646 :
647 0 : VI_PRINTF("%s", "Queue Rx:");
648 0 : for (i = 0; i < queue_size; i++) {
649 0 : if (eth_stats.q_ipackets[i] != 0) {
650 0 : VI_PRINTF(" [%d]", i);
651 0 : VI_PRINTF("%"
652 : PRId64 " ", eth_stats.q_ipackets[i]);
653 : }
654 : }
655 0 : VI_PRINTF("\n");
656 :
657 0 : VI_PRINTF("%s", " Tx:");
658 0 : for (i = 0; i < queue_size; i++) {
659 0 : if (eth_stats.q_opackets[i] != 0) {
660 0 : VI_PRINTF(" [%d]", i);
661 0 : VI_PRINTF("%"
662 : PRId64 " ", eth_stats.q_opackets[i]);
663 : }
664 : }
665 0 : VI_PRINTF("\n");
666 :
667 0 : VI_PRINTF("%s", " Rx Bytes:");
668 0 : for (i = 0; i < queue_size; i++) {
669 0 : if (eth_stats.q_ibytes[i] != 0) {
670 0 : VI_PRINTF(" [%d]", i);
671 0 : VI_PRINTF("%"
672 : PRId64 " ", eth_stats.q_ibytes[i]);
673 : }
674 : }
675 0 : VI_PRINTF("\n");
676 :
677 0 : VI_PRINTF("%s", " Tx Bytes:");
678 0 : for (i = 0; i < queue_size; i++) {
679 0 : if (eth_stats.q_obytes[i] != 0) {
680 0 : VI_PRINTF(" [%d]", i);
681 0 : VI_PRINTF("%"
682 : PRId64 " ", eth_stats.q_obytes[i]);
683 : }
684 : }
685 0 : VI_PRINTF("\n");
686 :
687 0 : VI_PRINTF("%s", " Errors:");
688 0 : for (i = 0; i < queue_size; i++) {
689 0 : if (eth_stats.q_errors[i] != 0) {
690 0 : VI_PRINTF(" [%d]", i);
691 0 : VI_PRINTF("%"
692 : PRId64 " ", eth_stats.q_errors[i]);
693 : }
694 : }
695 0 : VI_PRINTF("\n");
696 0 : VI_PRINTF("%s\n\n", seperator);
697 0 : return 0;
698 : }
699 :
700 : int
701 0 : dpdk_info_get_stats(VR_INFO_ARGS)
702 : {
703 :
704 0 : uint16_t port_id, slave_id = 0;
705 0 : int i, j, ret = 0;
706 : struct rte_eth_stats eth_stats;
707 : struct vr_dpdk_ethdev *ethdev;
708 : struct vr_dpdk_bond_port_list port_list;
709 0 : char name[VR_INTERFACE_NAME_LEN] = "";
710 :
711 0 : VR_INFO_BUF_INIT();
712 :
713 : /* msg req buf is not eth, return */
714 0 : if (strcmp(msg_req->inbuf, "eth")) {
715 0 : RTE_LOG(ERR, VROUTER, "Invalid argument.\n");
716 0 : return -1;
717 : }
718 :
719 : /* Get the port_id list for master, Incase of non-bond devices,
720 : it return here.
721 : */
722 0 : if (!dpdk_find_bond_port_id_list(&port_list)) {
723 0 : RTE_LOG(ERR, VROUTER, "%s: Port Id is invalid\n", __func__);
724 0 : return -1;
725 : }
726 :
727 0 : VI_PRINTF("No. of bond ids: %d\n", port_list.intf_count);
728 0 : for (j = 0; j < port_list.intf_count; j++) {
729 0 : port_id = port_list.intf_list[j];
730 : /* Get the ethdev for master port. */
731 0 : ethdev = &vr_dpdk.ethdevs[port_id];
732 0 : if (ethdev == NULL ||
733 0 : ethdev->ethdev_ptr == NULL) {
734 0 : RTE_LOG(ERR, VROUTER, "%s: Ethdev not available port id: %d\n",
735 : __func__, port_id);
736 0 : continue;
737 : }
738 :
739 0 : if (rte_eth_stats_get(port_id, ð_stats) != 0) {
740 0 : continue;
741 : }
742 :
743 0 : rte_eth_dev_get_name_by_port(port_id, name);
744 0 : if (strcmp(msg_req->inbuf, "eth") == 0) {
745 0 : VI_PRINTF("Master %s Info: No. of slaves: %d\n",
746 : name, ethdev->ethdev_nb_slaves);
747 0 : VI_PRINTF("============================================\n");
748 0 : ret = display_eth_stats(msg_req, eth_stats);
749 :
750 : /* Displaying slave stats */
751 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
752 0 : slave_id = ethdev->ethdev_slaves[i];
753 0 : ret = rte_eth_dev_get_name_by_port(slave_id, name);
754 0 : if (ret != 0) {
755 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting dev name "
756 : "port: %d slave: %d\n", __func__, port_id, slave_id);
757 0 : continue;
758 : }
759 0 : VI_PRINTF("Slave Info(%s): \n", name);
760 0 : if (rte_eth_stats_get(slave_id, ð_stats) != 0) {
761 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting interface stats "
762 : "port: %d slave: %d\n", __func__, port_id, slave_id);
763 0 : continue;
764 : }
765 0 : ret = display_eth_stats(msg_req, eth_stats);
766 : }
767 : }
768 : }
769 :
770 0 : return 0;
771 : }
772 :
773 : static int
774 0 : __display_xstats(VR_INFO_ARGS, uint16_t port_id, int xstats_count, bool is_all,
775 : uint64_t *values, struct rte_eth_xstat_name *xstats_names)
776 0 : {
777 :
778 0 : VR_INFO_DEC();
779 0 : int ret, i, segment_lookup[VR_DPDK_BOND_MAX_SLAVES][xstats_count],
780 0 : rpi = 0, rbi = 0, tpi = 0, tbi = 0, ei = 0, oth = 0;
781 : char seperator[SEPERATOR];
782 0 : memset(seperator, '-', SEPERATOR);
783 0 : seperator[SEPERATOR-1] = '\0';
784 :
785 0 : if (xstats_count != rte_eth_xstats_get_names_by_id(port_id, xstats_names,
786 : xstats_count, NULL)) {
787 0 : RTE_LOG(ERR, VROUTER, "Cannot get xstat names\n");
788 0 : return VR_INFO_FAILED;
789 : }
790 :
791 0 : ret = rte_eth_xstats_get_by_id(port_id, NULL, values, xstats_count);
792 0 : if (ret < 0 || ret > xstats_count) {
793 0 : RTE_LOG(ERR, VROUTER, "Cannot get xstats\n");
794 0 : return VR_INFO_FAILED;
795 : }
796 : /* Adding the indices of respective segments in segment_lookup array */
797 0 : for (i = 0; i < xstats_count; i++) {
798 0 : if (strstr(xstats_names[i].name, "rx") &&
799 0 : strstr(xstats_names[i].name, "packets")) {
800 0 : segment_lookup[RX_PACKETS][rpi++] = i;
801 0 : } else if (strstr(xstats_names[i].name, "tx") &&
802 0 : strstr(xstats_names[i].name, "packets")) {
803 0 : segment_lookup[TX_PACKETS][tpi++] = i;
804 0 : } else if (strstr(xstats_names[i].name, "rx") &&
805 0 : strstr(xstats_names[i].name, "bytes")) {
806 0 : segment_lookup[RX_BYTES][rbi++] = i;
807 0 : } else if (strstr(xstats_names[i].name, "tx") &&
808 0 : strstr(xstats_names[i].name, "bytes")) {
809 0 : segment_lookup[TX_BYTES][tbi++] = i;
810 0 : } else if (strstr(xstats_names[i].name, "errors")) {
811 0 : segment_lookup[ERRORS][ei++] = i;
812 : } else {
813 0 : segment_lookup[OTHERS][oth++] = i;
814 : }
815 : }
816 :
817 : /* Printing xstats name and value segment-wise */
818 0 : VI_PRINTF("Rx Packets: \n");
819 0 : for (i = 0; i < rpi - 1; i++) {
820 0 : if (values[segment_lookup[RX_PACKETS][i]] != 0 || is_all) {
821 0 : VI_PRINTF("\t%s: %"PRIu64 "\n",
822 : xstats_names[segment_lookup[RX_PACKETS][i]].name,
823 : values[segment_lookup[RX_PACKETS][i]]);
824 : }
825 : }
826 0 : VI_PRINTF("Tx Packets: \n");
827 0 : for (i = 0; i < tpi - 1; i++) {
828 0 : if (values[segment_lookup[TX_PACKETS][i]] != 0 || is_all) {
829 0 : VI_PRINTF("\t%s: %"PRIu64 "\n",
830 : xstats_names[segment_lookup[TX_PACKETS][i]].name,
831 : values[segment_lookup[TX_PACKETS][i]]);
832 : }
833 : }
834 0 : VI_PRINTF("Rx Bytes: \n");
835 0 : for (i = 0; i < rbi - 1; i++) {
836 0 : if (values[segment_lookup[RX_BYTES][i]] != 0 || is_all) {
837 0 : VI_PRINTF("\t%s: %"PRIu64 "\n",
838 : xstats_names[segment_lookup[RX_BYTES][i]].name,
839 : values[segment_lookup[RX_BYTES][i]]);
840 : }
841 : }
842 0 : VI_PRINTF("Tx Bytes: \n");
843 0 : for (i = 0; i < tbi - 1; i++) {
844 0 : if (values[segment_lookup[TX_BYTES][i]] != 0 || is_all) {
845 0 : VI_PRINTF("\t%s: %"PRIu64 "\n",
846 : xstats_names[segment_lookup[TX_BYTES][i]].name,
847 : values[segment_lookup[TX_BYTES][i]]);
848 : }
849 : }
850 0 : VI_PRINTF("Errors: \n");
851 0 : for (i = 0; i < ei - 1; i++) {
852 0 : if (values[segment_lookup[ERRORS][i]] != 0 || is_all) {
853 0 : VI_PRINTF("\t%s: %"PRIu64 "\n",
854 : xstats_names[segment_lookup[ERRORS][i]].name,
855 : values[segment_lookup[ERRORS][i]]);
856 : }
857 : }
858 0 : VI_PRINTF("Others: \n");
859 0 : for (i = 0; i < oth - 1; i++) {
860 0 : if (values[segment_lookup[OTHERS][i]] != 0 || is_all) {
861 0 : VI_PRINTF("\t%s: %"PRIu64 "\n",
862 : xstats_names[segment_lookup[OTHERS][i]].name,
863 : values[segment_lookup[OTHERS][i]]);
864 : }
865 : }
866 :
867 0 : VI_PRINTF("%s\n\n", seperator);
868 0 : return 0;
869 : }
870 :
871 : static int
872 0 : display_xstats(VR_INFO_ARGS, uint16_t port_id, int xstats_count, bool is_all)
873 : {
874 0 : struct rte_eth_xstat_name *xstats_names = NULL;
875 0 : uint64_t *values = NULL;
876 0 : int ret = 0;
877 :
878 0 : values = (uint64_t *)vr_zalloc(
879 : sizeof( *values) * xstats_count, VR_INFO_REQ_OBJECT);
880 0 : if (values == NULL) {
881 0 : RTE_LOG(ERR, VROUTER, "Cannot allocate memory for xstats\n");
882 0 : ret = VR_INFO_FAILED;
883 0 : goto exit;
884 : }
885 :
886 0 : xstats_names = (struct rte_eth_xstat_name *)vr_zalloc(
887 : sizeof(struct rte_eth_xstat_name) * xstats_count, VR_INFO_REQ_OBJECT);
888 0 : if (xstats_names == NULL) {
889 0 : RTE_LOG(ERR, VROUTER, "Cannot allocate memory for xstat names\n");
890 0 : ret = VR_INFO_FAILED;
891 0 : goto exit;
892 : }
893 :
894 0 : ret = __display_xstats(msg_req, port_id, xstats_count, is_all, values,
895 : xstats_names);
896 :
897 0 : exit:
898 0 : if (values) {
899 0 : vr_free(values, VR_INFO_REQ_OBJECT);
900 0 : values = NULL;
901 : }
902 0 : if (xstats_names) {
903 0 : vr_free(xstats_names, VR_INFO_REQ_OBJECT);
904 0 : xstats_names = NULL;
905 : }
906 :
907 0 : return ret;
908 : }
909 :
910 : int
911 0 : dpdk_info_get_xstats(VR_INFO_ARGS)
912 : {
913 :
914 0 : uint16_t port_id, slave_id = 0;
915 0 : int i, j, reqd_interface, ret = 0, slave = 0, xstats_count = -1;
916 0 : char name[VR_INTERFACE_NAME_LEN] = "";
917 0 : struct vrouter *router = vrouter_get(0);
918 0 : struct vr_dpdk_ethdev *ethdev = NULL;
919 : struct vr_dpdk_bond_port_list port_list;
920 0 : bool is_all = false;
921 :
922 0 : VR_INFO_BUF_INIT();
923 :
924 0 : is_all = !strcmp(msg_req->inbuf, "all");
925 :
926 : /* Get the port_id list for master, Incase of non-bond devices,
927 : it return here. */
928 0 : if (dpdk_find_bond_port_id_list(&port_list)) {
929 0 : VI_PRINTF("No. of bond ids: %d\n", port_list.intf_count);
930 0 : for (j = 0; j < port_list.intf_count; j++) {
931 0 : port_id = port_list.intf_list[j];
932 : /* Get the ethdev for master port. */
933 0 : ethdev = &vr_dpdk.ethdevs[port_id];
934 0 : if (ethdev->ethdev_ptr == NULL) {
935 0 : RTE_LOG(ERR, VROUTER, "Ethdev not available for port=%d\n", port_id);
936 0 : continue;
937 : }
938 :
939 0 : rte_eth_dev_get_name_by_port(port_id, name);
940 0 : VI_PRINTF("=======================================\n");
941 0 : VI_PRINTF("|| Bond Interface(%d): %s ||\n", port_id, name);
942 0 : VI_PRINTF("=======================================\n");
943 :
944 0 : if (!strcmp(msg_req->inbuf, "") || is_all) {
945 0 : reqd_interface = 0;
946 0 : } else if (!strcmp(msg_req->inbuf, "0") ||
947 0 : (atoi(msg_req->inbuf) > 0 &&
948 0 : atoi(msg_req->inbuf) <= ethdev->ethdev_nb_slaves)) {
949 0 : reqd_interface = 1;
950 : } else {
951 0 : VI_PRINTF("There are only %d slaves available.\n\n",
952 : ethdev->ethdev_nb_slaves);
953 0 : continue;
954 : }
955 :
956 0 : xstats_count = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
957 0 : if (xstats_count < 0) {
958 0 : RTE_LOG(ERR, VROUTER, "Cannot get xstats count port=%d\n", port_id);
959 0 : continue;
960 : }
961 :
962 0 : switch (reqd_interface) {
963 0 : case 0:
964 0 : VI_PRINTF("Master Info: \n");
965 0 : ret = display_xstats(msg_req, port_id, xstats_count, is_all);
966 0 : if (ret < 0) {
967 0 : RTE_LOG(ERR, VROUTER, "Failed to display xstats port=%d\n", port_id);
968 0 : continue;
969 : }
970 :
971 : /* Displaying slave stats */
972 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
973 0 : slave_id = ethdev->ethdev_slaves[i];
974 0 : ret = rte_eth_dev_get_name_by_port(slave_id, name);
975 0 : if (ret != 0) {
976 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting dev name "
977 : "port=%d slave=%d\n", __func__, port_id, slave_id);
978 0 : continue;
979 : }
980 0 : VI_PRINTF("Slave Info(%d):%s \n", i, name);
981 :
982 0 : xstats_count = rte_eth_xstats_get_names_by_id(slave_id, NULL,
983 : 0, NULL);
984 0 : if (xstats_count < 0) {
985 0 : RTE_LOG(ERR, VROUTER, "Cannot get xstats count "
986 : "port=%d slave=%d\n", port_id, slave_id);
987 0 : continue;
988 : }
989 0 : ret = display_xstats(msg_req, slave_id, xstats_count, is_all);
990 0 : if (ret < 0) {
991 0 : RTE_LOG(ERR, VROUTER, "Failed to display xstats "
992 : "port=%d slave=%d\n", port_id, slave_id);
993 0 : continue;
994 : }
995 : }
996 0 : break;
997 0 : case 1:
998 0 : if (!strcmp(msg_req->inbuf, "0")) {
999 0 : VI_PRINTF("Master Info: \n");
1000 0 : ret = display_xstats(msg_req, port_id, xstats_count, is_all);
1001 0 : if (ret < 0)
1002 0 : continue;
1003 :
1004 : } else {
1005 0 : slave = atoi(msg_req->inbuf) - 1;
1006 0 : slave_id = ethdev->ethdev_slaves[slave];
1007 0 : ret = rte_eth_dev_get_name_by_port(slave_id, name);
1008 0 : if (ret != 0) {
1009 0 : RTE_LOG(ERR, VROUTER, "%s: Error getting bond interface namei "
1010 : "port=%d slave=%d\n", __func__, port_id, slave_id);
1011 0 : continue;
1012 : }
1013 0 : VI_PRINTF("Slave Info(%d):%s \n", slave, name);
1014 0 : xstats_count = rte_eth_xstats_get_names_by_id(slave_id, NULL,
1015 : 0, NULL);
1016 0 : if (xstats_count < 0) {
1017 0 : RTE_LOG(ERR, VROUTER, "Cannot get xstats count "
1018 : "port=%d slave=%d\n", port_id, slave_id);
1019 0 : continue;
1020 : }
1021 0 : ret = display_xstats(msg_req, slave_id, xstats_count, is_all);
1022 0 : if (ret < 0)
1023 0 : continue;
1024 : }
1025 0 : break;
1026 : }
1027 : }
1028 : }else {
1029 : /* if bond is not configured */
1030 0 : if (strcmp(msg_req->inbuf, "") == 0 || is_all) {
1031 0 : if (router->vr_eth_if[0]) {
1032 0 : ethdev = (struct vr_dpdk_ethdev* ) router->vr_eth_if[0]->vif_os;
1033 : }
1034 0 : if (!ethdev) {
1035 0 : RTE_LOG(ERR, VROUTER, "%s: ethdev null\n", __func__);
1036 0 : return -1;
1037 : }
1038 :
1039 0 : port_id = ethdev->ethdev_port_id;
1040 0 : xstats_count = rte_eth_xstats_get_names_by_id(port_id, NULL,
1041 : 0, NULL);
1042 0 : if (xstats_count < 0) {
1043 0 : RTE_LOG(ERR, VROUTER, "Cannot get xstats count\n");
1044 0 : return -1;
1045 : }
1046 :
1047 0 : ret = display_xstats(msg_req, port_id, xstats_count, is_all);
1048 0 : if (ret < 0)
1049 0 : goto err;
1050 :
1051 : } else {
1052 0 : RTE_LOG(ERR, VROUTER, "Invalid argument.\n");
1053 0 : return -1;
1054 : }
1055 : }
1056 :
1057 0 : return 0;
1058 0 : err:
1059 0 : return ret;
1060 : }
1061 :
1062 : int
1063 0 : dpdk_info_get_lcore(VR_INFO_ARGS)
1064 : {
1065 : struct vr_dpdk_queue *rx_queue;
1066 : struct vr_dpdk_lcore *lcore;
1067 : unsigned char *name;
1068 : int i;
1069 :
1070 0 : VR_INFO_BUF_INIT();
1071 :
1072 0 : VI_PRINTF("No. of forwarding lcores: %d \n\n", vr_dpdk.nb_fwd_lcores);
1073 :
1074 0 : for (i = 0; i < vr_dpdk.nb_fwd_lcores; i++) {
1075 0 : VI_PRINTF("Lcore %d: \n", (VR_DPDK_FWD_LCORE_ID + i));
1076 0 : lcore = vr_dpdk.lcores[VR_DPDK_FWD_LCORE_ID + i];
1077 0 : SLIST_FOREACH(rx_queue, &lcore->lcore_rx_head, q_next) {
1078 0 : name = rx_queue->q_vif->vif_name;
1079 0 : VI_PRINTF("\tInterface: %-20s", name);
1080 0 : VI_PRINTF("Queue ID: %"
1081 : PRId16 " \n", rx_queue->vring_queue_id);
1082 : }
1083 0 : VI_PRINTF("\n");
1084 : }
1085 :
1086 0 : return 0;
1087 : }
1088 :
1089 : int
1090 0 : dpdk_info_get_app(VR_INFO_ARGS)
1091 : {
1092 :
1093 : uint16_t port_id;
1094 0 : struct vr_dpdk_ethdev *ethdev = NULL;
1095 : struct rte_eth_dev_info dev_info;
1096 0 : struct vr_dpdk_tapdev *tapdev = vr_dpdk.tapdevs;
1097 : struct vr_dpdk_bond_port_list port_list;
1098 : size_t soff;
1099 0 : struct vrouter *router = vrouter_get(0);
1100 0 : int i, j = 0, k = 0;
1101 : struct vr_interface *vif;
1102 0 : bool monitoring_intf = false, sriov_flag = false;
1103 0 : char name[VR_INTERFACE_NAME_LEN] = "";
1104 :
1105 0 : VR_INFO_BUF_INIT();
1106 :
1107 0 : VI_PRINTF("No. of lcores: %d \n", vr_num_cpus);
1108 0 : VI_PRINTF("No. of forwarding lcores: %d \n", vr_dpdk.nb_fwd_lcores);
1109 :
1110 : /* Get the port_id list for master, Incase of non-bond devices, */
1111 0 : if (!dpdk_find_bond_port_id_list(&port_list)) {
1112 0 : RTE_LOG(ERR, VROUTER, "%s: Port Id list is invalid\n", __func__);
1113 0 : return -1;
1114 : }
1115 :
1116 : /* Display vlan information */
1117 0 : if (vr_dpdk.vlan_vif){
1118 0 : VI_PRINTF("Vlan vif: %s \n", vr_dpdk.vlan_vif->vif_name);
1119 0 : VI_PRINTF("Vlan name: %s \n", vr_dpdk.vlan_name);
1120 0 : VI_PRINTF("Vlan tag: %d \n", vr_dpdk.vlan_tag);
1121 : }
1122 :
1123 0 : VI_PRINTF("No. of bond id available: %d\n", port_list.intf_count);
1124 0 : for (j = 0; j < port_list.intf_count ; j++) {
1125 0 : port_id = port_list.intf_list[j];
1126 0 : ethdev = &vr_dpdk.ethdevs[port_id];
1127 0 : if (ethdev == NULL ||
1128 0 : ethdev->ethdev_ptr == NULL) {
1129 0 : RTE_LOG(ERR, VROUTER, "%s: Ethdev not available\n", __func__);
1130 0 : continue;
1131 : }
1132 :
1133 : /* Display Ethdev information */
1134 0 : if (ethdev->ethdev_ptr) {
1135 0 : rte_eth_dev_get_name_by_port(port_id, name);
1136 0 : rte_eth_dev_info_get(port_id, &dev_info);
1137 0 : VI_PRINTF("Ethdev (Master: %s):\n", name);
1138 0 : VI_PRINTF("================================\n");
1139 0 : VI_PRINTF("\tMax rx queues: %"PRIu16"\n", dev_info.max_rx_queues);
1140 0 : VI_PRINTF("\tMax tx queues: %"PRIu16"\n", dev_info.max_tx_queues);
1141 0 : VI_PRINTF("\tEthdev nb rx queues: %"PRIu16"\n",
1142 : ethdev->ethdev_nb_rx_queues);
1143 0 : VI_PRINTF("\tEthdev nb tx queues: %"PRIu16"\n",
1144 : ethdev->ethdev_nb_tx_queues);
1145 0 : VI_PRINTF("\tEthdev nb rss queues: %"PRIu16"\n",
1146 : ethdev->ethdev_nb_rss_queues);
1147 0 : VI_PRINTF("\tEthdev reta size: %"PRIu16"\n", ethdev->ethdev_reta_size);
1148 0 : VI_PRINTF("\tEthdev port id: %"PRIu16"\n", ethdev->ethdev_port_id);
1149 0 : VI_PRINTF("\tEthdev nb slaves: %d \n", ethdev->ethdev_nb_slaves);
1150 0 : VI_PRINTF("\tEthdev slaves: ");
1151 0 : for (i = 0; i < VR_DPDK_BOND_MAX_SLAVES; i++){
1152 0 : VI_PRINTF("%"PRIu16 " ", ethdev->ethdev_slaves[i]);
1153 : }
1154 0 : VI_PRINTF("\n\n");
1155 : }
1156 :
1157 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
1158 0 : VI_PRINTF("Ethdev (Slave %d): %s\n", i, rte_eth_devices[i].data->name);
1159 0 : VI_PRINTF("\tNb rx queues: %"PRIu16"\n",
1160 : rte_eth_devices[i].data->nb_rx_queues);
1161 0 : VI_PRINTF("\tNb tx queues: %"PRIu16"\n",
1162 : rte_eth_devices[i].data->nb_tx_queues);
1163 0 : VI_PRINTF("\tEthdev reta size: %"PRIu16"\n\n", dev_info.reta_size);
1164 : }
1165 : }
1166 :
1167 : /* Display Tapdev information */
1168 0 : if(tapdev) {
1169 0 : VI_PRINTF("Tapdev:\n");
1170 0 : while (tapdev[k].tapdev_fd){
1171 0 : VI_PRINTF("\tfd: %d", tapdev[k].tapdev_fd);
1172 0 : if(tapdev[k].tapdev_vif) {
1173 0 : VI_PRINTF("\tvif name: %s \n", tapdev[k].tapdev_vif->vif_name);
1174 : }
1175 0 : k++;
1176 : }
1177 : }
1178 0 : VI_PRINTF("\n");
1179 :
1180 : /* Display Monitoring interfaces */
1181 0 : for (i = 0; i < router->vr_max_interfaces; i++){
1182 0 : if (vr_dpdk.monitorings[i] != 0 &&
1183 0 : vr_dpdk.monitorings[i] != VR_MAX_INTERFACES){
1184 0 : if (!monitoring_intf){
1185 0 : VI_PRINTF("Monitorings:\n");
1186 0 : monitoring_intf = true;
1187 : }
1188 0 : vif = router->vr_interfaces[i];
1189 0 : VI_PRINTF("\t%s\n", vif->vif_name);
1190 : }
1191 : }
1192 :
1193 : /* Display SRIOV information */
1194 0 : VR_DPDK_RTE_ETH_FOREACH_DEV(i){
1195 0 : rte_eth_dev_info_get(i, &dev_info);
1196 : /* Check PMD name suffix to detect SR-IOV virtual function. */
1197 0 : soff = strlen(dev_info.driver_name) - sizeof(VR_DPDK_VF_PMD_SFX) + 1;
1198 0 : if (soff > 0 &&
1199 0 : strncmp(dev_info.driver_name + soff, VR_DPDK_VF_PMD_SFX,
1200 : sizeof(VR_DPDK_VF_PMD_SFX)) == 0){
1201 0 : if (dev_info.max_tx_queues < vr_dpdk.nb_fwd_lcores
1202 : /* We also need 2 TX queues for Netlink and Packet lcores. */
1203 : + VR_DPDK_FWD_LCORE_ID - VR_DPDK_PACKET_LCORE_ID) {
1204 0 : if (!sriov_flag){
1205 0 : VI_PRINTF("Sriov:\n");
1206 0 : sriov_flag = true;
1207 : }
1208 0 : VI_PRINTF("\tLcore: %d", VR_DPDK_FWD_LCORE_ID);
1209 0 : VI_PRINTF("\tEthdev port id: %d", i);
1210 0 : VI_PRINTF("\tDriver Name: %s\n", dev_info.driver_name);
1211 0 : break;
1212 : }
1213 : }
1214 : }
1215 :
1216 0 : VI_PRINTF("\n");
1217 :
1218 0 : return 0;
1219 : }
1220 :
1221 : int
1222 0 : dpdk_info_get_ddp(VR_INFO_ARGS)
1223 : {
1224 : struct rte_pmd_i40e_profile_list *p_list;
1225 : struct rte_pmd_i40e_profile_info *p_info;
1226 : uint32_t p_num, size, i;
1227 : int ret;
1228 0 : uint16_t port_id = 0;
1229 0 : VR_INFO_BUF_INIT();
1230 :
1231 0 : if (strcmp(msg_req->inbuf, "list") != 0) {
1232 0 : return -1;
1233 : }
1234 :
1235 0 : size = I40E_MAX_PROFILE_NUM * sizeof(struct rte_pmd_i40e_profile_list);
1236 :
1237 0 : p_list = (struct rte_pmd_i40e_profile_list *)vr_zalloc(size,
1238 : VR_INFO_REQ_OBJECT);
1239 0 : if(!p_list) {
1240 0 : RTE_LOG(ERR, VROUTER, "%s: Memory allocation failed\n", __func__);
1241 0 : return -1;
1242 : }
1243 :
1244 0 : ret = rte_pmd_i40e_get_ddp_list(port_id, (uint8_t *)p_list, size);
1245 :
1246 0 : if (!ret) {
1247 0 : p_num = p_list->p_count;
1248 0 : VI_PRINTF("Profile count is: %d\n\n", p_num);
1249 0 : if(p_num == 0) {
1250 0 : VI_PRINTF("DDP profile is not enabled \n\n");
1251 : }
1252 :
1253 0 : for (i = 0; i < p_num; i++) {
1254 0 : p_info = &p_list->p_info[i];
1255 0 : VI_PRINTF("Profile %d:\n", i);
1256 0 : VI_PRINTF("Track id: 0x%x\n", p_info->track_id);
1257 0 : VI_PRINTF("Version: %d.%d.%d.%d\n",
1258 : p_info->version.major,
1259 : p_info->version.minor,
1260 : p_info->version.update,
1261 : p_info->version.draft);
1262 0 : VI_PRINTF("Profile name: %s\n\n", p_info->name);
1263 : }
1264 : }
1265 :
1266 0 : if(p_list)
1267 0 : vr_free(p_list, VR_INFO_REQ_OBJECT);
1268 :
1269 0 : if(ret == -ENOTSUP) {
1270 0 : VI_PRINTF("DDP works only on X710 NIC series \n\n");
1271 0 : } else if (ret < 0) {
1272 0 : VI_PRINTF("Failed to get ddp list, return value is %d \n\n", ret);
1273 : }
1274 :
1275 0 : return 0;
1276 : }
1277 :
1278 : int
1279 0 : dpdk_link_status_change(VR_INFO_ARGS) {
1280 0 : uint16_t port_id = VR_DPDK_INVALID_PORT_ID;
1281 0 : int i, idx = -1;
1282 : char args[7], oper[4];
1283 : char *ptr;
1284 0 : unsigned bond_type = VR_DPDK_BOND_MASTER;
1285 : struct vr_dpdk_bond_member_info member_info;
1286 0 : struct vrouter *router = vrouter_get(0);
1287 :
1288 0 : VR_INFO_BUF_INIT();
1289 0 : memcpy(args, msg_req->inbuf, 7);
1290 :
1291 0 : ptr = strtok(args, ",");
1292 0 : while (ptr != NULL) {
1293 0 : if (ptr[0] >= '0' && ptr[0] <= '2')
1294 0 : idx = atoi(&ptr[0]);
1295 : else
1296 0 : memcpy(oper, ptr, 4);
1297 0 : ptr = strtok(NULL, ",");
1298 : }
1299 :
1300 0 : if (idx == -1) {
1301 0 : VI_PRINTF("Invalid vif ID!\n");
1302 0 : return -1;
1303 : }
1304 0 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
1305 0 : if (vr_dpdk.ethdevs[i].ethdev_vif_idx == idx) {
1306 0 : port_id = vr_dpdk.ethdevs[i].ethdev_port_id;
1307 0 : break;
1308 : }
1309 : }
1310 :
1311 0 : if (port_id == VR_DPDK_INVALID_PORT_ID) {
1312 0 : RTE_LOG(ERR, VROUTER, "Port Id is invalid\n");
1313 0 : return -1;
1314 : }
1315 :
1316 : /* Set msginfo */
1317 0 : memset(&member_info, 0, sizeof(member_info));
1318 0 : strcpy(member_info.intf_name, (char *)router->vr_interfaces[idx]->vif_name);
1319 :
1320 0 : if(rte_eth_devices[port_id].device->driver->name != NULL)
1321 0 : snprintf(member_info.intf_drv_name, (VR_INTERFACE_NAME_LEN - 1),
1322 0 : "%s", rte_eth_devices[port_id].device->driver->name);
1323 :
1324 0 : if (!strncmp(oper, "up", 2)) {
1325 0 : member_info.status = 1;
1326 0 : } else if (!strncmp(oper, "down", 4)) {
1327 0 : member_info.status = 0;
1328 : } else {
1329 0 : VI_PRINTF("Enter link operation 'up' or 'down'\n\n");
1330 0 : return -1;
1331 : }
1332 0 : vr_dpdk_nl_send_bond_intf_state(&member_info, bond_type, idx);
1333 :
1334 0 : return 0;
1335 : }
|