+/* Configure the Rx with optional split. */
+int
+rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
+ uint16_t nb_rx_desc, unsigned int socket_id,
+ struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp)
+{
+ union rte_eth_rxseg rx_useg[MAX_SEGS_BUFFER_SPLIT] = {};
+ unsigned int i, mp_n;
+ int ret;
+
+ if (rx_pkt_nb_segs <= 1 ||
+ (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) == 0) {
+ rx_conf->rx_seg = NULL;
+ rx_conf->rx_nseg = 0;
+ ret = rte_eth_rx_queue_setup(port_id, rx_queue_id,
+ nb_rx_desc, socket_id,
+ rx_conf, mp);
+ return ret;
+ }
+ for (i = 0; i < rx_pkt_nb_segs; i++) {
+ struct rte_eth_rxseg_split *rx_seg = &rx_useg[i].split;
+ struct rte_mempool *mpx;
+ /*
+ * Use last valid pool for the segments with number
+ * exceeding the pool index.
+ */
+ mp_n = (i > mbuf_data_size_n) ? mbuf_data_size_n - 1 : i;
+ mpx = mbuf_pool_find(socket_id, mp_n);
+ /* Handle zero as mbuf data buffer size. */
+ rx_seg->length = rx_pkt_seg_lengths[i] ?
+ rx_pkt_seg_lengths[i] :
+ mbuf_data_size[mp_n];
+ rx_seg->offset = i < rx_pkt_nb_offs ?
+ rx_pkt_seg_offsets[i] : 0;
+ rx_seg->mp = mpx ? mpx : mp;
+ }
+ rx_conf->rx_nseg = rx_pkt_nb_segs;
+ rx_conf->rx_seg = rx_useg;
+ ret = rte_eth_rx_queue_setup(port_id, rx_queue_id, nb_rx_desc,
+ socket_id, rx_conf, NULL);
+ rx_conf->rx_seg = NULL;
+ rx_conf->rx_nseg = 0;
+ return ret;
+}
+
+static int
+alloc_xstats_display_info(portid_t pi)
+{
+ uint64_t **ids_supp = &ports[pi].xstats_info.ids_supp;
+ uint64_t **prev_values = &ports[pi].xstats_info.prev_values;
+ uint64_t **curr_values = &ports[pi].xstats_info.curr_values;
+
+ if (xstats_display_num == 0)
+ return 0;
+
+ *ids_supp = calloc(xstats_display_num, sizeof(**ids_supp));
+ if (*ids_supp == NULL)
+ goto fail_ids_supp;
+
+ *prev_values = calloc(xstats_display_num,
+ sizeof(**prev_values));
+ if (*prev_values == NULL)
+ goto fail_prev_values;
+
+ *curr_values = calloc(xstats_display_num,
+ sizeof(**curr_values));
+ if (*curr_values == NULL)
+ goto fail_curr_values;
+
+ ports[pi].xstats_info.allocated = true;
+
+ return 0;
+
+fail_curr_values:
+ free(*prev_values);
+fail_prev_values:
+ free(*ids_supp);
+fail_ids_supp:
+ return -ENOMEM;
+}
+
+static void
+free_xstats_display_info(portid_t pi)
+{
+ if (!ports[pi].xstats_info.allocated)
+ return;
+ free(ports[pi].xstats_info.ids_supp);
+ free(ports[pi].xstats_info.prev_values);
+ free(ports[pi].xstats_info.curr_values);
+ ports[pi].xstats_info.allocated = false;
+}
+
+/** Fill helper structures for specified port to show extended statistics. */
+static void
+fill_xstats_display_info_for_port(portid_t pi)
+{
+ unsigned int stat, stat_supp;
+ const char *xstat_name;
+ struct rte_port *port;
+ uint64_t *ids_supp;
+ int rc;
+
+ if (xstats_display_num == 0)
+ return;
+
+ if (pi == (portid_t)RTE_PORT_ALL) {
+ fill_xstats_display_info();
+ return;
+ }
+
+ port = &ports[pi];
+ if (port->port_status != RTE_PORT_STARTED)
+ return;
+
+ if (!port->xstats_info.allocated && alloc_xstats_display_info(pi) != 0)
+ rte_exit(EXIT_FAILURE,
+ "Failed to allocate xstats display memory\n");
+
+ ids_supp = port->xstats_info.ids_supp;
+ for (stat = stat_supp = 0; stat < xstats_display_num; stat++) {
+ xstat_name = xstats_display[stat].name;
+ rc = rte_eth_xstats_get_id_by_name(pi, xstat_name,
+ ids_supp + stat_supp);
+ if (rc != 0) {
+ fprintf(stderr, "No xstat '%s' on port %u - skip it %u\n",
+ xstat_name, pi, stat);
+ continue;
+ }
+ stat_supp++;
+ }
+
+ port->xstats_info.ids_supp_sz = stat_supp;
+}
+
+/** Fill helper structures for all ports to show extended statistics. */
+static void
+fill_xstats_display_info(void)
+{
+ portid_t pi;
+
+ if (xstats_display_num == 0)
+ return;
+
+ RTE_ETH_FOREACH_DEV(pi)
+ fill_xstats_display_info_for_port(pi);
+}
+