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