1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2*99a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 3*99a2dd95SBruce Richardson */ 4*99a2dd95SBruce Richardson #include <string.h> 5*99a2dd95SBruce Richardson #include <stdint.h> 6*99a2dd95SBruce Richardson 7*99a2dd95SBruce Richardson #include <rte_mbuf.h> 8*99a2dd95SBruce Richardson #include <rte_ethdev.h> 9*99a2dd95SBruce Richardson #include <rte_malloc.h> 10*99a2dd95SBruce Richardson 11*99a2dd95SBruce Richardson #include "rte_port_ethdev.h" 12*99a2dd95SBruce Richardson 13*99a2dd95SBruce Richardson /* 14*99a2dd95SBruce Richardson * Port ETHDEV Reader 15*99a2dd95SBruce Richardson */ 16*99a2dd95SBruce Richardson #ifdef RTE_PORT_STATS_COLLECT 17*99a2dd95SBruce Richardson 18*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_READER_STATS_PKTS_IN_ADD(port, val) \ 19*99a2dd95SBruce Richardson port->stats.n_pkts_in += val 20*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_READER_STATS_PKTS_DROP_ADD(port, val) \ 21*99a2dd95SBruce Richardson port->stats.n_pkts_drop += val 22*99a2dd95SBruce Richardson 23*99a2dd95SBruce Richardson #else 24*99a2dd95SBruce Richardson 25*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_READER_STATS_PKTS_IN_ADD(port, val) 26*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_READER_STATS_PKTS_DROP_ADD(port, val) 27*99a2dd95SBruce Richardson 28*99a2dd95SBruce Richardson #endif 29*99a2dd95SBruce Richardson 30*99a2dd95SBruce Richardson struct rte_port_ethdev_reader { 31*99a2dd95SBruce Richardson struct rte_port_in_stats stats; 32*99a2dd95SBruce Richardson 33*99a2dd95SBruce Richardson uint16_t queue_id; 34*99a2dd95SBruce Richardson uint16_t port_id; 35*99a2dd95SBruce Richardson }; 36*99a2dd95SBruce Richardson 37*99a2dd95SBruce Richardson static void * 38*99a2dd95SBruce Richardson rte_port_ethdev_reader_create(void *params, int socket_id) 39*99a2dd95SBruce Richardson { 40*99a2dd95SBruce Richardson struct rte_port_ethdev_reader_params *conf = 41*99a2dd95SBruce Richardson params; 42*99a2dd95SBruce Richardson struct rte_port_ethdev_reader *port; 43*99a2dd95SBruce Richardson 44*99a2dd95SBruce Richardson /* Check input parameters */ 45*99a2dd95SBruce Richardson if (conf == NULL) { 46*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: params is NULL\n", __func__); 47*99a2dd95SBruce Richardson return NULL; 48*99a2dd95SBruce Richardson } 49*99a2dd95SBruce Richardson 50*99a2dd95SBruce Richardson /* Memory allocation */ 51*99a2dd95SBruce Richardson port = rte_zmalloc_socket("PORT", sizeof(*port), 52*99a2dd95SBruce Richardson RTE_CACHE_LINE_SIZE, socket_id); 53*99a2dd95SBruce Richardson if (port == NULL) { 54*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); 55*99a2dd95SBruce Richardson return NULL; 56*99a2dd95SBruce Richardson } 57*99a2dd95SBruce Richardson 58*99a2dd95SBruce Richardson /* Initialization */ 59*99a2dd95SBruce Richardson port->port_id = conf->port_id; 60*99a2dd95SBruce Richardson port->queue_id = conf->queue_id; 61*99a2dd95SBruce Richardson 62*99a2dd95SBruce Richardson return port; 63*99a2dd95SBruce Richardson } 64*99a2dd95SBruce Richardson 65*99a2dd95SBruce Richardson static int 66*99a2dd95SBruce Richardson rte_port_ethdev_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) 67*99a2dd95SBruce Richardson { 68*99a2dd95SBruce Richardson struct rte_port_ethdev_reader *p = 69*99a2dd95SBruce Richardson port; 70*99a2dd95SBruce Richardson uint16_t rx_pkt_cnt; 71*99a2dd95SBruce Richardson 72*99a2dd95SBruce Richardson rx_pkt_cnt = rte_eth_rx_burst(p->port_id, p->queue_id, pkts, n_pkts); 73*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_READER_STATS_PKTS_IN_ADD(p, rx_pkt_cnt); 74*99a2dd95SBruce Richardson return rx_pkt_cnt; 75*99a2dd95SBruce Richardson } 76*99a2dd95SBruce Richardson 77*99a2dd95SBruce Richardson static int 78*99a2dd95SBruce Richardson rte_port_ethdev_reader_free(void *port) 79*99a2dd95SBruce Richardson { 80*99a2dd95SBruce Richardson if (port == NULL) { 81*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); 82*99a2dd95SBruce Richardson return -EINVAL; 83*99a2dd95SBruce Richardson } 84*99a2dd95SBruce Richardson 85*99a2dd95SBruce Richardson rte_free(port); 86*99a2dd95SBruce Richardson 87*99a2dd95SBruce Richardson return 0; 88*99a2dd95SBruce Richardson } 89*99a2dd95SBruce Richardson 90*99a2dd95SBruce Richardson static int rte_port_ethdev_reader_stats_read(void *port, 91*99a2dd95SBruce Richardson struct rte_port_in_stats *stats, int clear) 92*99a2dd95SBruce Richardson { 93*99a2dd95SBruce Richardson struct rte_port_ethdev_reader *p = 94*99a2dd95SBruce Richardson port; 95*99a2dd95SBruce Richardson 96*99a2dd95SBruce Richardson if (stats != NULL) 97*99a2dd95SBruce Richardson memcpy(stats, &p->stats, sizeof(p->stats)); 98*99a2dd95SBruce Richardson 99*99a2dd95SBruce Richardson if (clear) 100*99a2dd95SBruce Richardson memset(&p->stats, 0, sizeof(p->stats)); 101*99a2dd95SBruce Richardson 102*99a2dd95SBruce Richardson return 0; 103*99a2dd95SBruce Richardson } 104*99a2dd95SBruce Richardson 105*99a2dd95SBruce Richardson /* 106*99a2dd95SBruce Richardson * Port ETHDEV Writer 107*99a2dd95SBruce Richardson */ 108*99a2dd95SBruce Richardson #ifdef RTE_PORT_STATS_COLLECT 109*99a2dd95SBruce Richardson 110*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(port, val) \ 111*99a2dd95SBruce Richardson port->stats.n_pkts_in += val 112*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(port, val) \ 113*99a2dd95SBruce Richardson port->stats.n_pkts_drop += val 114*99a2dd95SBruce Richardson 115*99a2dd95SBruce Richardson #else 116*99a2dd95SBruce Richardson 117*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(port, val) 118*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(port, val) 119*99a2dd95SBruce Richardson 120*99a2dd95SBruce Richardson #endif 121*99a2dd95SBruce Richardson 122*99a2dd95SBruce Richardson struct rte_port_ethdev_writer { 123*99a2dd95SBruce Richardson struct rte_port_out_stats stats; 124*99a2dd95SBruce Richardson 125*99a2dd95SBruce Richardson struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; 126*99a2dd95SBruce Richardson uint32_t tx_burst_sz; 127*99a2dd95SBruce Richardson uint16_t tx_buf_count; 128*99a2dd95SBruce Richardson uint64_t bsz_mask; 129*99a2dd95SBruce Richardson uint16_t queue_id; 130*99a2dd95SBruce Richardson uint16_t port_id; 131*99a2dd95SBruce Richardson }; 132*99a2dd95SBruce Richardson 133*99a2dd95SBruce Richardson static void * 134*99a2dd95SBruce Richardson rte_port_ethdev_writer_create(void *params, int socket_id) 135*99a2dd95SBruce Richardson { 136*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_params *conf = 137*99a2dd95SBruce Richardson params; 138*99a2dd95SBruce Richardson struct rte_port_ethdev_writer *port; 139*99a2dd95SBruce Richardson 140*99a2dd95SBruce Richardson /* Check input parameters */ 141*99a2dd95SBruce Richardson if ((conf == NULL) || 142*99a2dd95SBruce Richardson (conf->tx_burst_sz == 0) || 143*99a2dd95SBruce Richardson (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || 144*99a2dd95SBruce Richardson (!rte_is_power_of_2(conf->tx_burst_sz))) { 145*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__); 146*99a2dd95SBruce Richardson return NULL; 147*99a2dd95SBruce Richardson } 148*99a2dd95SBruce Richardson 149*99a2dd95SBruce Richardson /* Memory allocation */ 150*99a2dd95SBruce Richardson port = rte_zmalloc_socket("PORT", sizeof(*port), 151*99a2dd95SBruce Richardson RTE_CACHE_LINE_SIZE, socket_id); 152*99a2dd95SBruce Richardson if (port == NULL) { 153*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); 154*99a2dd95SBruce Richardson return NULL; 155*99a2dd95SBruce Richardson } 156*99a2dd95SBruce Richardson 157*99a2dd95SBruce Richardson /* Initialization */ 158*99a2dd95SBruce Richardson port->port_id = conf->port_id; 159*99a2dd95SBruce Richardson port->queue_id = conf->queue_id; 160*99a2dd95SBruce Richardson port->tx_burst_sz = conf->tx_burst_sz; 161*99a2dd95SBruce Richardson port->tx_buf_count = 0; 162*99a2dd95SBruce Richardson port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); 163*99a2dd95SBruce Richardson 164*99a2dd95SBruce Richardson return port; 165*99a2dd95SBruce Richardson } 166*99a2dd95SBruce Richardson 167*99a2dd95SBruce Richardson static inline void 168*99a2dd95SBruce Richardson send_burst(struct rte_port_ethdev_writer *p) 169*99a2dd95SBruce Richardson { 170*99a2dd95SBruce Richardson uint32_t nb_tx; 171*99a2dd95SBruce Richardson 172*99a2dd95SBruce Richardson nb_tx = rte_eth_tx_burst(p->port_id, p->queue_id, 173*99a2dd95SBruce Richardson p->tx_buf, p->tx_buf_count); 174*99a2dd95SBruce Richardson 175*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); 176*99a2dd95SBruce Richardson for ( ; nb_tx < p->tx_buf_count; nb_tx++) 177*99a2dd95SBruce Richardson rte_pktmbuf_free(p->tx_buf[nb_tx]); 178*99a2dd95SBruce Richardson 179*99a2dd95SBruce Richardson p->tx_buf_count = 0; 180*99a2dd95SBruce Richardson } 181*99a2dd95SBruce Richardson 182*99a2dd95SBruce Richardson static int 183*99a2dd95SBruce Richardson rte_port_ethdev_writer_tx(void *port, struct rte_mbuf *pkt) 184*99a2dd95SBruce Richardson { 185*99a2dd95SBruce Richardson struct rte_port_ethdev_writer *p = 186*99a2dd95SBruce Richardson port; 187*99a2dd95SBruce Richardson 188*99a2dd95SBruce Richardson p->tx_buf[p->tx_buf_count++] = pkt; 189*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(p, 1); 190*99a2dd95SBruce Richardson if (p->tx_buf_count >= p->tx_burst_sz) 191*99a2dd95SBruce Richardson send_burst(p); 192*99a2dd95SBruce Richardson 193*99a2dd95SBruce Richardson return 0; 194*99a2dd95SBruce Richardson } 195*99a2dd95SBruce Richardson 196*99a2dd95SBruce Richardson static int 197*99a2dd95SBruce Richardson rte_port_ethdev_writer_tx_bulk(void *port, 198*99a2dd95SBruce Richardson struct rte_mbuf **pkts, 199*99a2dd95SBruce Richardson uint64_t pkts_mask) 200*99a2dd95SBruce Richardson { 201*99a2dd95SBruce Richardson struct rte_port_ethdev_writer *p = 202*99a2dd95SBruce Richardson port; 203*99a2dd95SBruce Richardson uint64_t bsz_mask = p->bsz_mask; 204*99a2dd95SBruce Richardson uint32_t tx_buf_count = p->tx_buf_count; 205*99a2dd95SBruce Richardson uint64_t expr = (pkts_mask & (pkts_mask + 1)) | 206*99a2dd95SBruce Richardson ((pkts_mask & bsz_mask) ^ bsz_mask); 207*99a2dd95SBruce Richardson 208*99a2dd95SBruce Richardson if (expr == 0) { 209*99a2dd95SBruce Richardson uint64_t n_pkts = __builtin_popcountll(pkts_mask); 210*99a2dd95SBruce Richardson uint32_t n_pkts_ok; 211*99a2dd95SBruce Richardson 212*99a2dd95SBruce Richardson if (tx_buf_count) 213*99a2dd95SBruce Richardson send_burst(p); 214*99a2dd95SBruce Richardson 215*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(p, n_pkts); 216*99a2dd95SBruce Richardson n_pkts_ok = rte_eth_tx_burst(p->port_id, p->queue_id, pkts, 217*99a2dd95SBruce Richardson n_pkts); 218*99a2dd95SBruce Richardson 219*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - n_pkts_ok); 220*99a2dd95SBruce Richardson for ( ; n_pkts_ok < n_pkts; n_pkts_ok++) { 221*99a2dd95SBruce Richardson struct rte_mbuf *pkt = pkts[n_pkts_ok]; 222*99a2dd95SBruce Richardson 223*99a2dd95SBruce Richardson rte_pktmbuf_free(pkt); 224*99a2dd95SBruce Richardson } 225*99a2dd95SBruce Richardson } else { 226*99a2dd95SBruce Richardson for ( ; pkts_mask; ) { 227*99a2dd95SBruce Richardson uint32_t pkt_index = __builtin_ctzll(pkts_mask); 228*99a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << pkt_index; 229*99a2dd95SBruce Richardson struct rte_mbuf *pkt = pkts[pkt_index]; 230*99a2dd95SBruce Richardson 231*99a2dd95SBruce Richardson p->tx_buf[tx_buf_count++] = pkt; 232*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(p, 1); 233*99a2dd95SBruce Richardson pkts_mask &= ~pkt_mask; 234*99a2dd95SBruce Richardson } 235*99a2dd95SBruce Richardson 236*99a2dd95SBruce Richardson p->tx_buf_count = tx_buf_count; 237*99a2dd95SBruce Richardson if (tx_buf_count >= p->tx_burst_sz) 238*99a2dd95SBruce Richardson send_burst(p); 239*99a2dd95SBruce Richardson } 240*99a2dd95SBruce Richardson 241*99a2dd95SBruce Richardson return 0; 242*99a2dd95SBruce Richardson } 243*99a2dd95SBruce Richardson 244*99a2dd95SBruce Richardson static int 245*99a2dd95SBruce Richardson rte_port_ethdev_writer_flush(void *port) 246*99a2dd95SBruce Richardson { 247*99a2dd95SBruce Richardson struct rte_port_ethdev_writer *p = 248*99a2dd95SBruce Richardson port; 249*99a2dd95SBruce Richardson 250*99a2dd95SBruce Richardson if (p->tx_buf_count > 0) 251*99a2dd95SBruce Richardson send_burst(p); 252*99a2dd95SBruce Richardson 253*99a2dd95SBruce Richardson return 0; 254*99a2dd95SBruce Richardson } 255*99a2dd95SBruce Richardson 256*99a2dd95SBruce Richardson static int 257*99a2dd95SBruce Richardson rte_port_ethdev_writer_free(void *port) 258*99a2dd95SBruce Richardson { 259*99a2dd95SBruce Richardson if (port == NULL) { 260*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); 261*99a2dd95SBruce Richardson return -EINVAL; 262*99a2dd95SBruce Richardson } 263*99a2dd95SBruce Richardson 264*99a2dd95SBruce Richardson rte_port_ethdev_writer_flush(port); 265*99a2dd95SBruce Richardson rte_free(port); 266*99a2dd95SBruce Richardson 267*99a2dd95SBruce Richardson return 0; 268*99a2dd95SBruce Richardson } 269*99a2dd95SBruce Richardson 270*99a2dd95SBruce Richardson static int rte_port_ethdev_writer_stats_read(void *port, 271*99a2dd95SBruce Richardson struct rte_port_out_stats *stats, int clear) 272*99a2dd95SBruce Richardson { 273*99a2dd95SBruce Richardson struct rte_port_ethdev_writer *p = 274*99a2dd95SBruce Richardson port; 275*99a2dd95SBruce Richardson 276*99a2dd95SBruce Richardson if (stats != NULL) 277*99a2dd95SBruce Richardson memcpy(stats, &p->stats, sizeof(p->stats)); 278*99a2dd95SBruce Richardson 279*99a2dd95SBruce Richardson if (clear) 280*99a2dd95SBruce Richardson memset(&p->stats, 0, sizeof(p->stats)); 281*99a2dd95SBruce Richardson 282*99a2dd95SBruce Richardson return 0; 283*99a2dd95SBruce Richardson } 284*99a2dd95SBruce Richardson 285*99a2dd95SBruce Richardson /* 286*99a2dd95SBruce Richardson * Port ETHDEV Writer Nodrop 287*99a2dd95SBruce Richardson */ 288*99a2dd95SBruce Richardson #ifdef RTE_PORT_STATS_COLLECT 289*99a2dd95SBruce Richardson 290*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \ 291*99a2dd95SBruce Richardson port->stats.n_pkts_in += val 292*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \ 293*99a2dd95SBruce Richardson port->stats.n_pkts_drop += val 294*99a2dd95SBruce Richardson 295*99a2dd95SBruce Richardson #else 296*99a2dd95SBruce Richardson 297*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) 298*99a2dd95SBruce Richardson #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) 299*99a2dd95SBruce Richardson 300*99a2dd95SBruce Richardson #endif 301*99a2dd95SBruce Richardson 302*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop { 303*99a2dd95SBruce Richardson struct rte_port_out_stats stats; 304*99a2dd95SBruce Richardson 305*99a2dd95SBruce Richardson struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; 306*99a2dd95SBruce Richardson uint32_t tx_burst_sz; 307*99a2dd95SBruce Richardson uint16_t tx_buf_count; 308*99a2dd95SBruce Richardson uint64_t bsz_mask; 309*99a2dd95SBruce Richardson uint64_t n_retries; 310*99a2dd95SBruce Richardson uint16_t queue_id; 311*99a2dd95SBruce Richardson uint16_t port_id; 312*99a2dd95SBruce Richardson }; 313*99a2dd95SBruce Richardson 314*99a2dd95SBruce Richardson static void * 315*99a2dd95SBruce Richardson rte_port_ethdev_writer_nodrop_create(void *params, int socket_id) 316*99a2dd95SBruce Richardson { 317*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop_params *conf = 318*99a2dd95SBruce Richardson params; 319*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop *port; 320*99a2dd95SBruce Richardson 321*99a2dd95SBruce Richardson /* Check input parameters */ 322*99a2dd95SBruce Richardson if ((conf == NULL) || 323*99a2dd95SBruce Richardson (conf->tx_burst_sz == 0) || 324*99a2dd95SBruce Richardson (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || 325*99a2dd95SBruce Richardson (!rte_is_power_of_2(conf->tx_burst_sz))) { 326*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__); 327*99a2dd95SBruce Richardson return NULL; 328*99a2dd95SBruce Richardson } 329*99a2dd95SBruce Richardson 330*99a2dd95SBruce Richardson /* Memory allocation */ 331*99a2dd95SBruce Richardson port = rte_zmalloc_socket("PORT", sizeof(*port), 332*99a2dd95SBruce Richardson RTE_CACHE_LINE_SIZE, socket_id); 333*99a2dd95SBruce Richardson if (port == NULL) { 334*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); 335*99a2dd95SBruce Richardson return NULL; 336*99a2dd95SBruce Richardson } 337*99a2dd95SBruce Richardson 338*99a2dd95SBruce Richardson /* Initialization */ 339*99a2dd95SBruce Richardson port->port_id = conf->port_id; 340*99a2dd95SBruce Richardson port->queue_id = conf->queue_id; 341*99a2dd95SBruce Richardson port->tx_burst_sz = conf->tx_burst_sz; 342*99a2dd95SBruce Richardson port->tx_buf_count = 0; 343*99a2dd95SBruce Richardson port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); 344*99a2dd95SBruce Richardson 345*99a2dd95SBruce Richardson /* 346*99a2dd95SBruce Richardson * When n_retries is 0 it means that we should wait for every packet to 347*99a2dd95SBruce Richardson * send no matter how many retries should it take. To limit number of 348*99a2dd95SBruce Richardson * branches in fast path, we use UINT64_MAX instead of branching. 349*99a2dd95SBruce Richardson */ 350*99a2dd95SBruce Richardson port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries; 351*99a2dd95SBruce Richardson 352*99a2dd95SBruce Richardson return port; 353*99a2dd95SBruce Richardson } 354*99a2dd95SBruce Richardson 355*99a2dd95SBruce Richardson static inline void 356*99a2dd95SBruce Richardson send_burst_nodrop(struct rte_port_ethdev_writer_nodrop *p) 357*99a2dd95SBruce Richardson { 358*99a2dd95SBruce Richardson uint32_t nb_tx = 0, i; 359*99a2dd95SBruce Richardson 360*99a2dd95SBruce Richardson nb_tx = rte_eth_tx_burst(p->port_id, p->queue_id, p->tx_buf, 361*99a2dd95SBruce Richardson p->tx_buf_count); 362*99a2dd95SBruce Richardson 363*99a2dd95SBruce Richardson /* We sent all the packets in a first try */ 364*99a2dd95SBruce Richardson if (nb_tx >= p->tx_buf_count) { 365*99a2dd95SBruce Richardson p->tx_buf_count = 0; 366*99a2dd95SBruce Richardson return; 367*99a2dd95SBruce Richardson } 368*99a2dd95SBruce Richardson 369*99a2dd95SBruce Richardson for (i = 0; i < p->n_retries; i++) { 370*99a2dd95SBruce Richardson nb_tx += rte_eth_tx_burst(p->port_id, p->queue_id, 371*99a2dd95SBruce Richardson p->tx_buf + nb_tx, p->tx_buf_count - nb_tx); 372*99a2dd95SBruce Richardson 373*99a2dd95SBruce Richardson /* We sent all the packets in more than one try */ 374*99a2dd95SBruce Richardson if (nb_tx >= p->tx_buf_count) { 375*99a2dd95SBruce Richardson p->tx_buf_count = 0; 376*99a2dd95SBruce Richardson return; 377*99a2dd95SBruce Richardson } 378*99a2dd95SBruce Richardson } 379*99a2dd95SBruce Richardson 380*99a2dd95SBruce Richardson /* We didn't send the packets in maximum allowed attempts */ 381*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); 382*99a2dd95SBruce Richardson for ( ; nb_tx < p->tx_buf_count; nb_tx++) 383*99a2dd95SBruce Richardson rte_pktmbuf_free(p->tx_buf[nb_tx]); 384*99a2dd95SBruce Richardson 385*99a2dd95SBruce Richardson p->tx_buf_count = 0; 386*99a2dd95SBruce Richardson } 387*99a2dd95SBruce Richardson 388*99a2dd95SBruce Richardson static int 389*99a2dd95SBruce Richardson rte_port_ethdev_writer_nodrop_tx(void *port, struct rte_mbuf *pkt) 390*99a2dd95SBruce Richardson { 391*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop *p = 392*99a2dd95SBruce Richardson port; 393*99a2dd95SBruce Richardson 394*99a2dd95SBruce Richardson p->tx_buf[p->tx_buf_count++] = pkt; 395*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); 396*99a2dd95SBruce Richardson if (p->tx_buf_count >= p->tx_burst_sz) 397*99a2dd95SBruce Richardson send_burst_nodrop(p); 398*99a2dd95SBruce Richardson 399*99a2dd95SBruce Richardson return 0; 400*99a2dd95SBruce Richardson } 401*99a2dd95SBruce Richardson 402*99a2dd95SBruce Richardson static int 403*99a2dd95SBruce Richardson rte_port_ethdev_writer_nodrop_tx_bulk(void *port, 404*99a2dd95SBruce Richardson struct rte_mbuf **pkts, 405*99a2dd95SBruce Richardson uint64_t pkts_mask) 406*99a2dd95SBruce Richardson { 407*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop *p = 408*99a2dd95SBruce Richardson port; 409*99a2dd95SBruce Richardson 410*99a2dd95SBruce Richardson uint64_t bsz_mask = p->bsz_mask; 411*99a2dd95SBruce Richardson uint32_t tx_buf_count = p->tx_buf_count; 412*99a2dd95SBruce Richardson uint64_t expr = (pkts_mask & (pkts_mask + 1)) | 413*99a2dd95SBruce Richardson ((pkts_mask & bsz_mask) ^ bsz_mask); 414*99a2dd95SBruce Richardson 415*99a2dd95SBruce Richardson if (expr == 0) { 416*99a2dd95SBruce Richardson uint64_t n_pkts = __builtin_popcountll(pkts_mask); 417*99a2dd95SBruce Richardson uint32_t n_pkts_ok; 418*99a2dd95SBruce Richardson 419*99a2dd95SBruce Richardson if (tx_buf_count) 420*99a2dd95SBruce Richardson send_burst_nodrop(p); 421*99a2dd95SBruce Richardson 422*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts); 423*99a2dd95SBruce Richardson n_pkts_ok = rte_eth_tx_burst(p->port_id, p->queue_id, pkts, 424*99a2dd95SBruce Richardson n_pkts); 425*99a2dd95SBruce Richardson 426*99a2dd95SBruce Richardson if (n_pkts_ok >= n_pkts) 427*99a2dd95SBruce Richardson return 0; 428*99a2dd95SBruce Richardson 429*99a2dd95SBruce Richardson /* 430*99a2dd95SBruce Richardson * If we did not manage to send all packets in single burst, 431*99a2dd95SBruce Richardson * move remaining packets to the buffer and call send burst. 432*99a2dd95SBruce Richardson */ 433*99a2dd95SBruce Richardson for (; n_pkts_ok < n_pkts; n_pkts_ok++) { 434*99a2dd95SBruce Richardson struct rte_mbuf *pkt = pkts[n_pkts_ok]; 435*99a2dd95SBruce Richardson p->tx_buf[p->tx_buf_count++] = pkt; 436*99a2dd95SBruce Richardson } 437*99a2dd95SBruce Richardson send_burst_nodrop(p); 438*99a2dd95SBruce Richardson } else { 439*99a2dd95SBruce Richardson for ( ; pkts_mask; ) { 440*99a2dd95SBruce Richardson uint32_t pkt_index = __builtin_ctzll(pkts_mask); 441*99a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << pkt_index; 442*99a2dd95SBruce Richardson struct rte_mbuf *pkt = pkts[pkt_index]; 443*99a2dd95SBruce Richardson 444*99a2dd95SBruce Richardson p->tx_buf[tx_buf_count++] = pkt; 445*99a2dd95SBruce Richardson RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); 446*99a2dd95SBruce Richardson pkts_mask &= ~pkt_mask; 447*99a2dd95SBruce Richardson } 448*99a2dd95SBruce Richardson 449*99a2dd95SBruce Richardson p->tx_buf_count = tx_buf_count; 450*99a2dd95SBruce Richardson if (tx_buf_count >= p->tx_burst_sz) 451*99a2dd95SBruce Richardson send_burst_nodrop(p); 452*99a2dd95SBruce Richardson } 453*99a2dd95SBruce Richardson 454*99a2dd95SBruce Richardson return 0; 455*99a2dd95SBruce Richardson } 456*99a2dd95SBruce Richardson 457*99a2dd95SBruce Richardson static int 458*99a2dd95SBruce Richardson rte_port_ethdev_writer_nodrop_flush(void *port) 459*99a2dd95SBruce Richardson { 460*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop *p = 461*99a2dd95SBruce Richardson port; 462*99a2dd95SBruce Richardson 463*99a2dd95SBruce Richardson if (p->tx_buf_count > 0) 464*99a2dd95SBruce Richardson send_burst_nodrop(p); 465*99a2dd95SBruce Richardson 466*99a2dd95SBruce Richardson return 0; 467*99a2dd95SBruce Richardson } 468*99a2dd95SBruce Richardson 469*99a2dd95SBruce Richardson static int 470*99a2dd95SBruce Richardson rte_port_ethdev_writer_nodrop_free(void *port) 471*99a2dd95SBruce Richardson { 472*99a2dd95SBruce Richardson if (port == NULL) { 473*99a2dd95SBruce Richardson RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); 474*99a2dd95SBruce Richardson return -EINVAL; 475*99a2dd95SBruce Richardson } 476*99a2dd95SBruce Richardson 477*99a2dd95SBruce Richardson rte_port_ethdev_writer_nodrop_flush(port); 478*99a2dd95SBruce Richardson rte_free(port); 479*99a2dd95SBruce Richardson 480*99a2dd95SBruce Richardson return 0; 481*99a2dd95SBruce Richardson } 482*99a2dd95SBruce Richardson 483*99a2dd95SBruce Richardson static int rte_port_ethdev_writer_nodrop_stats_read(void *port, 484*99a2dd95SBruce Richardson struct rte_port_out_stats *stats, int clear) 485*99a2dd95SBruce Richardson { 486*99a2dd95SBruce Richardson struct rte_port_ethdev_writer_nodrop *p = 487*99a2dd95SBruce Richardson port; 488*99a2dd95SBruce Richardson 489*99a2dd95SBruce Richardson if (stats != NULL) 490*99a2dd95SBruce Richardson memcpy(stats, &p->stats, sizeof(p->stats)); 491*99a2dd95SBruce Richardson 492*99a2dd95SBruce Richardson if (clear) 493*99a2dd95SBruce Richardson memset(&p->stats, 0, sizeof(p->stats)); 494*99a2dd95SBruce Richardson 495*99a2dd95SBruce Richardson return 0; 496*99a2dd95SBruce Richardson } 497*99a2dd95SBruce Richardson 498*99a2dd95SBruce Richardson /* 499*99a2dd95SBruce Richardson * Summary of port operations 500*99a2dd95SBruce Richardson */ 501*99a2dd95SBruce Richardson struct rte_port_in_ops rte_port_ethdev_reader_ops = { 502*99a2dd95SBruce Richardson .f_create = rte_port_ethdev_reader_create, 503*99a2dd95SBruce Richardson .f_free = rte_port_ethdev_reader_free, 504*99a2dd95SBruce Richardson .f_rx = rte_port_ethdev_reader_rx, 505*99a2dd95SBruce Richardson .f_stats = rte_port_ethdev_reader_stats_read, 506*99a2dd95SBruce Richardson }; 507*99a2dd95SBruce Richardson 508*99a2dd95SBruce Richardson struct rte_port_out_ops rte_port_ethdev_writer_ops = { 509*99a2dd95SBruce Richardson .f_create = rte_port_ethdev_writer_create, 510*99a2dd95SBruce Richardson .f_free = rte_port_ethdev_writer_free, 511*99a2dd95SBruce Richardson .f_tx = rte_port_ethdev_writer_tx, 512*99a2dd95SBruce Richardson .f_tx_bulk = rte_port_ethdev_writer_tx_bulk, 513*99a2dd95SBruce Richardson .f_flush = rte_port_ethdev_writer_flush, 514*99a2dd95SBruce Richardson .f_stats = rte_port_ethdev_writer_stats_read, 515*99a2dd95SBruce Richardson }; 516*99a2dd95SBruce Richardson 517*99a2dd95SBruce Richardson struct rte_port_out_ops rte_port_ethdev_writer_nodrop_ops = { 518*99a2dd95SBruce Richardson .f_create = rte_port_ethdev_writer_nodrop_create, 519*99a2dd95SBruce Richardson .f_free = rte_port_ethdev_writer_nodrop_free, 520*99a2dd95SBruce Richardson .f_tx = rte_port_ethdev_writer_nodrop_tx, 521*99a2dd95SBruce Richardson .f_tx_bulk = rte_port_ethdev_writer_nodrop_tx_bulk, 522*99a2dd95SBruce Richardson .f_flush = rte_port_ethdev_writer_nodrop_flush, 523*99a2dd95SBruce Richardson .f_stats = rte_port_ethdev_writer_nodrop_stats_read, 524*99a2dd95SBruce Richardson }; 525