NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
simple_fwd_port.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <rte_eal.h>
27 #include <rte_common.h>
28 #include <rte_malloc.h>
29 #include <rte_ether.h>
30 #include <rte_ethdev.h>
31 #include <rte_mempool.h>
32 #include <rte_mbuf.h>
33 #include <rte_net.h>
34 
35 #include <doca_log.h>
36 #include <doca_flow.h>
37 
38 #include "simple_fwd_port.h"
39 
40 DOCA_LOG_REGISTER(SIMPLE_FWD_PORT);
41 
42 #define NS_PER_SEC 1E9 /* Nano-seconds per second */
43 #ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
44 
45 /* Defining the CLOCK ID type used for displaying stats of a port */
46 #define CLOCK_TYPE_ID CLOCK_MONOTONIC_RAW
47 #else
48 #define CLOCK_TYPE_ID CLOCK_MONOTONIC
49 #endif
50 
51 /*
52  * Dump port stats
53  *
54  * @port [in]: Port identifier of the port to dump the stats for
55  * @f [in]: file to dump or buffering the stats into
56  * @return: 0 on success and non-zero value on failure
57  */
58 static int simple_fwd_port_stats_display(uint16_t port, FILE *f)
59 {
60  uint32_t i;
61  int result;
62  static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS];
63  static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
64  static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];
65  static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];
66  static uint64_t prev_ns[RTE_MAX_ETHPORTS];
67  struct timespec cur_time;
68  uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx, diff_ns;
69  uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;
70  struct rte_eth_stats ethernet_stats;
71  struct rte_eth_dev_info dev_info;
72  static const char *nic_stats_border = "########################";
73  uint32_t max_rx_queues, max_tx_queues;
74 
75  result = rte_eth_stats_get(port, &ethernet_stats);
76  if (result != 0)
77  return result;
78  result = rte_eth_dev_info_get(port, &dev_info);
79  if (result != 0)
80  return result;
81 
82  max_rx_queues = dev_info.nb_rx_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS ? dev_info.nb_rx_queues :
83  RTE_ETHDEV_QUEUE_STAT_CNTRS;
84  max_tx_queues = dev_info.nb_tx_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS ? dev_info.nb_tx_queues :
85  RTE_ETHDEV_QUEUE_STAT_CNTRS;
86  fprintf(f, "\n %s NIC statistics for port %-2d %s\n", nic_stats_border, port, nic_stats_border);
87 
88  fprintf(f,
89  " RX-packets: %-10" PRIu64 " RX-missed: %-10" PRIu64 " RX-bytes: %-" PRIu64 "\n",
90  ethernet_stats.ipackets,
91  ethernet_stats.imissed,
92  ethernet_stats.ibytes);
93  fprintf(f, " RX-errors: %-" PRIu64 "\n", ethernet_stats.ierrors);
94  fprintf(f, " RX-nombuf: %-10" PRIu64 "\n", ethernet_stats.rx_nombuf);
95  fprintf(f,
96  " TX-packets: %-10" PRIu64 " TX-errors: %-10" PRIu64 " TX-bytes: %-" PRIu64 "\n",
97  ethernet_stats.opackets,
98  ethernet_stats.oerrors,
99  ethernet_stats.obytes);
100 
101  fprintf(f, "\n");
102 
103  for (i = 0; i < max_rx_queues; i++) {
104  printf(" ethernet_stats reg %2d RX-packets: %-10" PRIu64 " RX-errors: %-10" PRIu64
105  " RX-bytes: %-10" PRIu64 "\n",
106  i,
107  ethernet_stats.q_ipackets[i],
108  ethernet_stats.q_errors[i],
109  ethernet_stats.q_ibytes[i]);
110  }
111 
112  fprintf(f, "\n");
113  for (i = 0; i < max_tx_queues; i++) {
114  fprintf(stdout,
115  " ethernet_stats reg %2d TX-packets: %-10" PRIu64 " TX-bytes: %-10" PRIu64 "\n",
116  i,
117  ethernet_stats.q_opackets[i],
118  ethernet_stats.q_obytes[i]);
119  }
120 
121  diff_ns = 0;
122  if (clock_gettime(CLOCK_TYPE_ID, &cur_time) == 0) {
123  uint64_t ns;
124 
125  ns = cur_time.tv_sec * NS_PER_SEC;
126  ns += cur_time.tv_nsec;
127 
128  if (prev_ns[port] != 0)
129  diff_ns = ns - prev_ns[port];
130  prev_ns[port] = ns;
131  }
132 
133  diff_pkts_rx = (ethernet_stats.ipackets > prev_pkts_rx[port]) ? (ethernet_stats.ipackets - prev_pkts_rx[port]) :
134  0;
135  diff_pkts_tx = (ethernet_stats.opackets > prev_pkts_tx[port]) ? (ethernet_stats.opackets - prev_pkts_tx[port]) :
136  0;
137  prev_pkts_rx[port] = ethernet_stats.ipackets;
138  prev_pkts_tx[port] = ethernet_stats.opackets;
139  mpps_rx = diff_ns > 0 ? (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0;
140  mpps_tx = diff_ns > 0 ? (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0;
141 
142  diff_bytes_rx = (ethernet_stats.ibytes > prev_bytes_rx[port]) ? (ethernet_stats.ibytes - prev_bytes_rx[port]) :
143  0;
144  diff_bytes_tx = (ethernet_stats.obytes > prev_bytes_tx[port]) ? (ethernet_stats.obytes - prev_bytes_tx[port]) :
145  0;
146  prev_bytes_rx[port] = ethernet_stats.ibytes;
147  prev_bytes_tx[port] = ethernet_stats.obytes;
148  mbps_rx = diff_ns > 0 ? (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0;
149  mbps_tx = diff_ns > 0 ? (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0;
150 
151  fprintf(f, "\n Throughput (since last show)\n");
152  fprintf(f,
153  " Rx-pps: %12" PRIu64 " Rx-bps: %12" PRIu64 "\n Tx-pps: %12" PRIu64
154  " Tx-bps: %12" PRIu64 "\n",
155  mpps_rx,
156  mbps_rx * 8,
157  mpps_tx,
158  mbps_tx * 8);
159 
160  fprintf(f, " %s############################%s\n", nic_stats_border, nic_stats_border);
161  return 0;
162 }
163 
164 int simple_fwd_dump_port_stats(uint16_t port_id, struct doca_flow_port *port)
165 {
166  int result = 0;
167  const char clr[] = {27, '[', '2', 'J', '\0'};
168  const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'};
169 
170  fprintf(stdout, "%s%s", clr, topLeft);
171  doca_flow_port_pipes_dump(port, stdout);
172 
173  result = simple_fwd_port_stats_display(port_id, stdout);
174  fflush(stdout);
175  return result;
176 }
int32_t result
struct rte_eth_dev_info dev_info
Definition: device.c:32
DOCA_EXPERIMENTAL void doca_flow_port_pipes_dump(struct doca_flow_port *port, FILE *f)
Dump pipes of one port.
static int simple_fwd_port_stats_display(uint16_t port, FILE *f)
#define CLOCK_TYPE_ID
DOCA_LOG_REGISTER(SIMPLE_FWD_PORT)
int simple_fwd_dump_port_stats(uint16_t port_id, struct doca_flow_port *port)
#define NS_PER_SEC