1*ed2a80fdSPablo de Lara /*- 2*ed2a80fdSPablo de Lara * BSD LICENSE 3*ed2a80fdSPablo de Lara * 4*ed2a80fdSPablo de Lara * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. 5*ed2a80fdSPablo de Lara * All rights reserved. 6*ed2a80fdSPablo de Lara * 7*ed2a80fdSPablo de Lara * Redistribution and use in source and binary forms, with or without 8*ed2a80fdSPablo de Lara * modification, are permitted provided that the following conditions 9*ed2a80fdSPablo de Lara * are met: 10*ed2a80fdSPablo de Lara * 11*ed2a80fdSPablo de Lara * * Redistributions of source code must retain the above copyright 12*ed2a80fdSPablo de Lara * notice, this list of conditions and the following disclaimer. 13*ed2a80fdSPablo de Lara * * Redistributions in binary form must reproduce the above copyright 14*ed2a80fdSPablo de Lara * notice, this list of conditions and the following disclaimer in 15*ed2a80fdSPablo de Lara * the documentation and/or other materials provided with the 16*ed2a80fdSPablo de Lara * distribution. 17*ed2a80fdSPablo de Lara * * Neither the name of Intel Corporation nor the names of its 18*ed2a80fdSPablo de Lara * contributors may be used to endorse or promote products derived 19*ed2a80fdSPablo de Lara * from this software without specific prior written permission. 20*ed2a80fdSPablo de Lara * 21*ed2a80fdSPablo de Lara * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*ed2a80fdSPablo de Lara * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*ed2a80fdSPablo de Lara * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24*ed2a80fdSPablo de Lara * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25*ed2a80fdSPablo de Lara * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*ed2a80fdSPablo de Lara * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27*ed2a80fdSPablo de Lara * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28*ed2a80fdSPablo de Lara * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29*ed2a80fdSPablo de Lara * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30*ed2a80fdSPablo de Lara * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31*ed2a80fdSPablo de Lara * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*ed2a80fdSPablo de Lara */ 33*ed2a80fdSPablo de Lara 34*ed2a80fdSPablo de Lara #include <stdint.h> 35*ed2a80fdSPablo de Lara #include <stdio.h> 36*ed2a80fdSPablo de Lara #include <inttypes.h> 37*ed2a80fdSPablo de Lara #include <stdarg.h> 38*ed2a80fdSPablo de Lara #include <errno.h> 39*ed2a80fdSPablo de Lara #include <sys/queue.h> 40*ed2a80fdSPablo de Lara #include <stdlib.h> 41*ed2a80fdSPablo de Lara #include <getopt.h> 42*ed2a80fdSPablo de Lara #include <string.h> 43*ed2a80fdSPablo de Lara 44*ed2a80fdSPablo de Lara #include <rte_common.h> 45*ed2a80fdSPablo de Lara #include <rte_malloc.h> 46*ed2a80fdSPablo de Lara #include <rte_memory.h> 47*ed2a80fdSPablo de Lara #include <rte_memzone.h> 48*ed2a80fdSPablo de Lara #include <rte_eal.h> 49*ed2a80fdSPablo de Lara #include <rte_atomic.h> 50*ed2a80fdSPablo de Lara #include <rte_branch_prediction.h> 51*ed2a80fdSPablo de Lara #include <rte_log.h> 52*ed2a80fdSPablo de Lara #include <rte_per_lcore.h> 53*ed2a80fdSPablo de Lara #include <rte_launch.h> 54*ed2a80fdSPablo de Lara #include <rte_lcore.h> 55*ed2a80fdSPablo de Lara #include <rte_ring.h> 56*ed2a80fdSPablo de Lara #include <rte_launch.h> 57*ed2a80fdSPablo de Lara #include <rte_lcore.h> 58*ed2a80fdSPablo de Lara #include <rte_debug.h> 59*ed2a80fdSPablo de Lara #include <rte_mempool.h> 60*ed2a80fdSPablo de Lara #include <rte_mbuf.h> 61*ed2a80fdSPablo de Lara #include <rte_interrupts.h> 62*ed2a80fdSPablo de Lara #include <rte_pci.h> 63*ed2a80fdSPablo de Lara #include <rte_ether.h> 64*ed2a80fdSPablo de Lara #include <rte_ethdev.h> 65*ed2a80fdSPablo de Lara #include <rte_string_fns.h> 66*ed2a80fdSPablo de Lara #include <rte_ip.h> 67*ed2a80fdSPablo de Lara 68*ed2a80fdSPablo de Lara #include "common.h" 69*ed2a80fdSPablo de Lara 70*ed2a80fdSPablo de Lara /* Number of packets to attempt to read from queue */ 71*ed2a80fdSPablo de Lara #define PKT_READ_SIZE ((uint16_t)32) 72*ed2a80fdSPablo de Lara 73*ed2a80fdSPablo de Lara /* 74*ed2a80fdSPablo de Lara * Our node id number - tells us which rx queue to read, and NIC TX 75*ed2a80fdSPablo de Lara * queue to write to. 76*ed2a80fdSPablo de Lara */ 77*ed2a80fdSPablo de Lara static uint8_t node_id; 78*ed2a80fdSPablo de Lara 79*ed2a80fdSPablo de Lara #define MBQ_CAPACITY 32 80*ed2a80fdSPablo de Lara 81*ed2a80fdSPablo de Lara /* maps input ports to output ports for packets */ 82*ed2a80fdSPablo de Lara static uint8_t output_ports[RTE_MAX_ETHPORTS]; 83*ed2a80fdSPablo de Lara 84*ed2a80fdSPablo de Lara /* buffers up a set of packet that are ready to send */ 85*ed2a80fdSPablo de Lara struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 86*ed2a80fdSPablo de Lara 87*ed2a80fdSPablo de Lara /* shared data from server. We update statistics here */ 88*ed2a80fdSPablo de Lara static struct tx_stats *tx_stats; 89*ed2a80fdSPablo de Lara 90*ed2a80fdSPablo de Lara static struct filter_stats *filter_stats; 91*ed2a80fdSPablo de Lara 92*ed2a80fdSPablo de Lara /* 93*ed2a80fdSPablo de Lara * print a usage message 94*ed2a80fdSPablo de Lara */ 95*ed2a80fdSPablo de Lara static void 96*ed2a80fdSPablo de Lara usage(const char *progname) 97*ed2a80fdSPablo de Lara { 98*ed2a80fdSPablo de Lara printf("Usage: %s [EAL args] -- -n <node_id>\n\n", progname); 99*ed2a80fdSPablo de Lara } 100*ed2a80fdSPablo de Lara 101*ed2a80fdSPablo de Lara /* 102*ed2a80fdSPablo de Lara * Convert the node id number from a string to an int. 103*ed2a80fdSPablo de Lara */ 104*ed2a80fdSPablo de Lara static int 105*ed2a80fdSPablo de Lara parse_node_num(const char *node) 106*ed2a80fdSPablo de Lara { 107*ed2a80fdSPablo de Lara char *end = NULL; 108*ed2a80fdSPablo de Lara unsigned long temp; 109*ed2a80fdSPablo de Lara 110*ed2a80fdSPablo de Lara if (node == NULL || *node == '\0') 111*ed2a80fdSPablo de Lara return -1; 112*ed2a80fdSPablo de Lara 113*ed2a80fdSPablo de Lara temp = strtoul(node, &end, 10); 114*ed2a80fdSPablo de Lara if (end == NULL || *end != '\0') 115*ed2a80fdSPablo de Lara return -1; 116*ed2a80fdSPablo de Lara 117*ed2a80fdSPablo de Lara node_id = (uint8_t)temp; 118*ed2a80fdSPablo de Lara return 0; 119*ed2a80fdSPablo de Lara } 120*ed2a80fdSPablo de Lara 121*ed2a80fdSPablo de Lara /* 122*ed2a80fdSPablo de Lara * Parse the application arguments to the node app. 123*ed2a80fdSPablo de Lara */ 124*ed2a80fdSPablo de Lara static int 125*ed2a80fdSPablo de Lara parse_app_args(int argc, char *argv[]) 126*ed2a80fdSPablo de Lara { 127*ed2a80fdSPablo de Lara int option_index, opt; 128*ed2a80fdSPablo de Lara char **argvopt = argv; 129*ed2a80fdSPablo de Lara const char *progname = NULL; 130*ed2a80fdSPablo de Lara static struct option lgopts[] = { /* no long options */ 131*ed2a80fdSPablo de Lara {NULL, 0, 0, 0 } 132*ed2a80fdSPablo de Lara }; 133*ed2a80fdSPablo de Lara progname = argv[0]; 134*ed2a80fdSPablo de Lara 135*ed2a80fdSPablo de Lara while ((opt = getopt_long(argc, argvopt, "n:", lgopts, 136*ed2a80fdSPablo de Lara &option_index)) != EOF) { 137*ed2a80fdSPablo de Lara switch (opt) { 138*ed2a80fdSPablo de Lara case 'n': 139*ed2a80fdSPablo de Lara if (parse_node_num(optarg) != 0) { 140*ed2a80fdSPablo de Lara usage(progname); 141*ed2a80fdSPablo de Lara return -1; 142*ed2a80fdSPablo de Lara } 143*ed2a80fdSPablo de Lara break; 144*ed2a80fdSPablo de Lara default: 145*ed2a80fdSPablo de Lara usage(progname); 146*ed2a80fdSPablo de Lara return -1; 147*ed2a80fdSPablo de Lara } 148*ed2a80fdSPablo de Lara } 149*ed2a80fdSPablo de Lara return 0; 150*ed2a80fdSPablo de Lara } 151*ed2a80fdSPablo de Lara 152*ed2a80fdSPablo de Lara /* 153*ed2a80fdSPablo de Lara * Tx buffer error callback 154*ed2a80fdSPablo de Lara */ 155*ed2a80fdSPablo de Lara static void 156*ed2a80fdSPablo de Lara flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count, 157*ed2a80fdSPablo de Lara void *userdata) { 158*ed2a80fdSPablo de Lara int i; 159*ed2a80fdSPablo de Lara uint8_t port_id = (uintptr_t)userdata; 160*ed2a80fdSPablo de Lara 161*ed2a80fdSPablo de Lara tx_stats->tx_drop[port_id] += count; 162*ed2a80fdSPablo de Lara 163*ed2a80fdSPablo de Lara /* free the mbufs which failed from transmit */ 164*ed2a80fdSPablo de Lara for (i = 0; i < count; i++) 165*ed2a80fdSPablo de Lara rte_pktmbuf_free(unsent[i]); 166*ed2a80fdSPablo de Lara 167*ed2a80fdSPablo de Lara } 168*ed2a80fdSPablo de Lara 169*ed2a80fdSPablo de Lara static void 170*ed2a80fdSPablo de Lara configure_tx_buffer(uint8_t port_id, uint16_t size) 171*ed2a80fdSPablo de Lara { 172*ed2a80fdSPablo de Lara int ret; 173*ed2a80fdSPablo de Lara 174*ed2a80fdSPablo de Lara /* Initialize TX buffers */ 175*ed2a80fdSPablo de Lara tx_buffer[port_id] = rte_zmalloc_socket("tx_buffer", 176*ed2a80fdSPablo de Lara RTE_ETH_TX_BUFFER_SIZE(size), 0, 177*ed2a80fdSPablo de Lara rte_eth_dev_socket_id(port_id)); 178*ed2a80fdSPablo de Lara if (tx_buffer[port_id] == NULL) 179*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx " 180*ed2a80fdSPablo de Lara "on port %u\n", (unsigned int) port_id); 181*ed2a80fdSPablo de Lara 182*ed2a80fdSPablo de Lara rte_eth_tx_buffer_init(tx_buffer[port_id], size); 183*ed2a80fdSPablo de Lara 184*ed2a80fdSPablo de Lara ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[port_id], 185*ed2a80fdSPablo de Lara flush_tx_error_callback, (void *)(intptr_t)port_id); 186*ed2a80fdSPablo de Lara if (ret < 0) 187*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Cannot set error callback for " 188*ed2a80fdSPablo de Lara "tx buffer on port %u\n", (unsigned int) port_id); 189*ed2a80fdSPablo de Lara } 190*ed2a80fdSPablo de Lara 191*ed2a80fdSPablo de Lara /* 192*ed2a80fdSPablo de Lara * set up output ports so that all traffic on port gets sent out 193*ed2a80fdSPablo de Lara * its paired port. Index using actual port numbers since that is 194*ed2a80fdSPablo de Lara * what comes in the mbuf structure. 195*ed2a80fdSPablo de Lara */ 196*ed2a80fdSPablo de Lara static void 197*ed2a80fdSPablo de Lara configure_output_ports(const struct shared_info *info) 198*ed2a80fdSPablo de Lara { 199*ed2a80fdSPablo de Lara int i; 200*ed2a80fdSPablo de Lara 201*ed2a80fdSPablo de Lara if (info->num_ports > RTE_MAX_ETHPORTS) 202*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Too many ethernet ports. " 203*ed2a80fdSPablo de Lara "RTE_MAX_ETHPORTS = %u\n", 204*ed2a80fdSPablo de Lara (unsigned int)RTE_MAX_ETHPORTS); 205*ed2a80fdSPablo de Lara for (i = 0; i < info->num_ports - 1; i += 2) { 206*ed2a80fdSPablo de Lara uint8_t p1 = info->id[i]; 207*ed2a80fdSPablo de Lara uint8_t p2 = info->id[i+1]; 208*ed2a80fdSPablo de Lara 209*ed2a80fdSPablo de Lara output_ports[p1] = p2; 210*ed2a80fdSPablo de Lara output_ports[p2] = p1; 211*ed2a80fdSPablo de Lara 212*ed2a80fdSPablo de Lara configure_tx_buffer(p1, MBQ_CAPACITY); 213*ed2a80fdSPablo de Lara configure_tx_buffer(p2, MBQ_CAPACITY); 214*ed2a80fdSPablo de Lara 215*ed2a80fdSPablo de Lara } 216*ed2a80fdSPablo de Lara } 217*ed2a80fdSPablo de Lara 218*ed2a80fdSPablo de Lara /* 219*ed2a80fdSPablo de Lara * Create the hash table that will contain the flows that 220*ed2a80fdSPablo de Lara * the node will handle, which will be used to decide if packet 221*ed2a80fdSPablo de Lara * is transmitted or dropped. 222*ed2a80fdSPablo de Lara */ 223*ed2a80fdSPablo de Lara static struct rte_hash * 224*ed2a80fdSPablo de Lara create_hash_table(const struct shared_info *info) 225*ed2a80fdSPablo de Lara { 226*ed2a80fdSPablo de Lara uint32_t num_flows_node = info->num_flows / info->num_nodes; 227*ed2a80fdSPablo de Lara char name[RTE_HASH_NAMESIZE]; 228*ed2a80fdSPablo de Lara struct rte_hash *h; 229*ed2a80fdSPablo de Lara 230*ed2a80fdSPablo de Lara /* create table */ 231*ed2a80fdSPablo de Lara struct rte_hash_parameters hash_params = { 232*ed2a80fdSPablo de Lara .entries = num_flows_node * 2, /* table load = 50% */ 233*ed2a80fdSPablo de Lara .key_len = sizeof(uint32_t), /* Store IPv4 dest IP address */ 234*ed2a80fdSPablo de Lara .socket_id = rte_socket_id(), 235*ed2a80fdSPablo de Lara .hash_func_init_val = 0, 236*ed2a80fdSPablo de Lara }; 237*ed2a80fdSPablo de Lara 238*ed2a80fdSPablo de Lara snprintf(name, sizeof(name), "hash_table_%d", node_id); 239*ed2a80fdSPablo de Lara hash_params.name = name; 240*ed2a80fdSPablo de Lara h = rte_hash_create(&hash_params); 241*ed2a80fdSPablo de Lara 242*ed2a80fdSPablo de Lara if (h == NULL) 243*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, 244*ed2a80fdSPablo de Lara "Problem creating the hash table for node %d\n", 245*ed2a80fdSPablo de Lara node_id); 246*ed2a80fdSPablo de Lara return h; 247*ed2a80fdSPablo de Lara } 248*ed2a80fdSPablo de Lara 249*ed2a80fdSPablo de Lara static void 250*ed2a80fdSPablo de Lara populate_hash_table(const struct rte_hash *h, const struct shared_info *info) 251*ed2a80fdSPablo de Lara { 252*ed2a80fdSPablo de Lara unsigned int i; 253*ed2a80fdSPablo de Lara int32_t ret; 254*ed2a80fdSPablo de Lara uint32_t ip_dst; 255*ed2a80fdSPablo de Lara uint32_t num_flows_node = 0; 256*ed2a80fdSPablo de Lara uint64_t target_node; 257*ed2a80fdSPablo de Lara 258*ed2a80fdSPablo de Lara /* Add flows in table */ 259*ed2a80fdSPablo de Lara for (i = 0; i < info->num_flows; i++) { 260*ed2a80fdSPablo de Lara target_node = i % info->num_nodes; 261*ed2a80fdSPablo de Lara if (target_node != node_id) 262*ed2a80fdSPablo de Lara continue; 263*ed2a80fdSPablo de Lara 264*ed2a80fdSPablo de Lara ip_dst = rte_cpu_to_be_32(i); 265*ed2a80fdSPablo de Lara 266*ed2a80fdSPablo de Lara ret = rte_hash_add_key(h, (void *) &ip_dst); 267*ed2a80fdSPablo de Lara if (ret < 0) 268*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Unable to add entry %u " 269*ed2a80fdSPablo de Lara "in hash table\n", i); 270*ed2a80fdSPablo de Lara else 271*ed2a80fdSPablo de Lara num_flows_node++; 272*ed2a80fdSPablo de Lara 273*ed2a80fdSPablo de Lara } 274*ed2a80fdSPablo de Lara 275*ed2a80fdSPablo de Lara printf("Hash table: Adding 0x%x keys\n", num_flows_node); 276*ed2a80fdSPablo de Lara } 277*ed2a80fdSPablo de Lara 278*ed2a80fdSPablo de Lara /* 279*ed2a80fdSPablo de Lara * This function performs routing of packets 280*ed2a80fdSPablo de Lara * Just sends each input packet out an output port based solely on the input 281*ed2a80fdSPablo de Lara * port it arrived on. 282*ed2a80fdSPablo de Lara */ 283*ed2a80fdSPablo de Lara static inline void 284*ed2a80fdSPablo de Lara transmit_packet(struct rte_mbuf *buf) 285*ed2a80fdSPablo de Lara { 286*ed2a80fdSPablo de Lara int sent; 287*ed2a80fdSPablo de Lara const uint8_t in_port = buf->port; 288*ed2a80fdSPablo de Lara const uint8_t out_port = output_ports[in_port]; 289*ed2a80fdSPablo de Lara struct rte_eth_dev_tx_buffer *buffer = tx_buffer[out_port]; 290*ed2a80fdSPablo de Lara 291*ed2a80fdSPablo de Lara sent = rte_eth_tx_buffer(out_port, node_id, buffer, buf); 292*ed2a80fdSPablo de Lara if (sent) 293*ed2a80fdSPablo de Lara tx_stats->tx[out_port] += sent; 294*ed2a80fdSPablo de Lara 295*ed2a80fdSPablo de Lara } 296*ed2a80fdSPablo de Lara 297*ed2a80fdSPablo de Lara static inline void 298*ed2a80fdSPablo de Lara handle_packets(struct rte_hash *h, struct rte_mbuf **bufs, uint16_t num_packets) 299*ed2a80fdSPablo de Lara { 300*ed2a80fdSPablo de Lara struct ipv4_hdr *ipv4_hdr; 301*ed2a80fdSPablo de Lara uint32_t ipv4_dst_ip[PKT_READ_SIZE]; 302*ed2a80fdSPablo de Lara const void *key_ptrs[PKT_READ_SIZE]; 303*ed2a80fdSPablo de Lara unsigned int i; 304*ed2a80fdSPablo de Lara int32_t positions[PKT_READ_SIZE] = {0}; 305*ed2a80fdSPablo de Lara 306*ed2a80fdSPablo de Lara for (i = 0; i < num_packets; i++) { 307*ed2a80fdSPablo de Lara /* Handle IPv4 header.*/ 308*ed2a80fdSPablo de Lara ipv4_hdr = rte_pktmbuf_mtod_offset(bufs[i], struct ipv4_hdr *, 309*ed2a80fdSPablo de Lara sizeof(struct ether_hdr)); 310*ed2a80fdSPablo de Lara ipv4_dst_ip[i] = ipv4_hdr->dst_addr; 311*ed2a80fdSPablo de Lara key_ptrs[i] = &ipv4_dst_ip[i]; 312*ed2a80fdSPablo de Lara } 313*ed2a80fdSPablo de Lara /* Check if packets belongs to any flows handled by this node */ 314*ed2a80fdSPablo de Lara rte_hash_lookup_bulk(h, key_ptrs, num_packets, positions); 315*ed2a80fdSPablo de Lara 316*ed2a80fdSPablo de Lara for (i = 0; i < num_packets; i++) { 317*ed2a80fdSPablo de Lara if (likely(positions[i] >= 0)) { 318*ed2a80fdSPablo de Lara filter_stats->passed++; 319*ed2a80fdSPablo de Lara transmit_packet(bufs[i]); 320*ed2a80fdSPablo de Lara } else { 321*ed2a80fdSPablo de Lara filter_stats->drop++; 322*ed2a80fdSPablo de Lara /* Drop packet, as flow is not handled by this node */ 323*ed2a80fdSPablo de Lara rte_pktmbuf_free(bufs[i]); 324*ed2a80fdSPablo de Lara } 325*ed2a80fdSPablo de Lara } 326*ed2a80fdSPablo de Lara } 327*ed2a80fdSPablo de Lara 328*ed2a80fdSPablo de Lara /* 329*ed2a80fdSPablo de Lara * Application main function - loops through 330*ed2a80fdSPablo de Lara * receiving and processing packets. Never returns 331*ed2a80fdSPablo de Lara */ 332*ed2a80fdSPablo de Lara int 333*ed2a80fdSPablo de Lara main(int argc, char *argv[]) 334*ed2a80fdSPablo de Lara { 335*ed2a80fdSPablo de Lara const struct rte_memzone *mz; 336*ed2a80fdSPablo de Lara struct rte_ring *rx_ring; 337*ed2a80fdSPablo de Lara struct rte_hash *h; 338*ed2a80fdSPablo de Lara struct rte_mempool *mp; 339*ed2a80fdSPablo de Lara struct shared_info *info; 340*ed2a80fdSPablo de Lara int need_flush = 0; /* indicates whether we have unsent packets */ 341*ed2a80fdSPablo de Lara int retval; 342*ed2a80fdSPablo de Lara void *pkts[PKT_READ_SIZE]; 343*ed2a80fdSPablo de Lara uint16_t sent; 344*ed2a80fdSPablo de Lara 345*ed2a80fdSPablo de Lara retval = rte_eal_init(argc, argv); 346*ed2a80fdSPablo de Lara if (retval < 0) 347*ed2a80fdSPablo de Lara return -1; 348*ed2a80fdSPablo de Lara argc -= retval; 349*ed2a80fdSPablo de Lara argv += retval; 350*ed2a80fdSPablo de Lara 351*ed2a80fdSPablo de Lara if (parse_app_args(argc, argv) < 0) 352*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); 353*ed2a80fdSPablo de Lara 354*ed2a80fdSPablo de Lara if (rte_eth_dev_count() == 0) 355*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); 356*ed2a80fdSPablo de Lara 357*ed2a80fdSPablo de Lara rx_ring = rte_ring_lookup(get_rx_queue_name(node_id)); 358*ed2a80fdSPablo de Lara if (rx_ring == NULL) 359*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Cannot get RX ring - " 360*ed2a80fdSPablo de Lara "is server process running?\n"); 361*ed2a80fdSPablo de Lara 362*ed2a80fdSPablo de Lara mp = rte_mempool_lookup(PKTMBUF_POOL_NAME); 363*ed2a80fdSPablo de Lara if (mp == NULL) 364*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Cannot get mempool for mbufs\n"); 365*ed2a80fdSPablo de Lara 366*ed2a80fdSPablo de Lara mz = rte_memzone_lookup(MZ_SHARED_INFO); 367*ed2a80fdSPablo de Lara if (mz == NULL) 368*ed2a80fdSPablo de Lara rte_exit(EXIT_FAILURE, "Cannot get port info structure\n"); 369*ed2a80fdSPablo de Lara info = mz->addr; 370*ed2a80fdSPablo de Lara tx_stats = &(info->tx_stats[node_id]); 371*ed2a80fdSPablo de Lara filter_stats = &(info->filter_stats[node_id]); 372*ed2a80fdSPablo de Lara 373*ed2a80fdSPablo de Lara configure_output_ports(info); 374*ed2a80fdSPablo de Lara 375*ed2a80fdSPablo de Lara h = create_hash_table(info); 376*ed2a80fdSPablo de Lara 377*ed2a80fdSPablo de Lara populate_hash_table(h, info); 378*ed2a80fdSPablo de Lara 379*ed2a80fdSPablo de Lara RTE_LOG(INFO, APP, "Finished Process Init.\n"); 380*ed2a80fdSPablo de Lara 381*ed2a80fdSPablo de Lara printf("\nNode process %d handling packets\n", node_id); 382*ed2a80fdSPablo de Lara printf("[Press Ctrl-C to quit ...]\n"); 383*ed2a80fdSPablo de Lara 384*ed2a80fdSPablo de Lara for (;;) { 385*ed2a80fdSPablo de Lara uint16_t rx_pkts = PKT_READ_SIZE; 386*ed2a80fdSPablo de Lara uint8_t port; 387*ed2a80fdSPablo de Lara 388*ed2a80fdSPablo de Lara /* 389*ed2a80fdSPablo de Lara * Try dequeuing max possible packets first, if that fails, 390*ed2a80fdSPablo de Lara * get the most we can. Loop body should only execute once, 391*ed2a80fdSPablo de Lara * maximum 392*ed2a80fdSPablo de Lara */ 393*ed2a80fdSPablo de Lara while (rx_pkts > 0 && 394*ed2a80fdSPablo de Lara unlikely(rte_ring_dequeue_bulk(rx_ring, pkts, 395*ed2a80fdSPablo de Lara rx_pkts) != 0)) 396*ed2a80fdSPablo de Lara rx_pkts = (uint16_t)RTE_MIN(rte_ring_count(rx_ring), 397*ed2a80fdSPablo de Lara PKT_READ_SIZE); 398*ed2a80fdSPablo de Lara 399*ed2a80fdSPablo de Lara if (unlikely(rx_pkts == 0)) { 400*ed2a80fdSPablo de Lara if (need_flush) 401*ed2a80fdSPablo de Lara for (port = 0; port < info->num_ports; port++) { 402*ed2a80fdSPablo de Lara sent = rte_eth_tx_buffer_flush( 403*ed2a80fdSPablo de Lara info->id[port], 404*ed2a80fdSPablo de Lara node_id, 405*ed2a80fdSPablo de Lara tx_buffer[port]); 406*ed2a80fdSPablo de Lara if (unlikely(sent)) 407*ed2a80fdSPablo de Lara tx_stats->tx[port] += sent; 408*ed2a80fdSPablo de Lara } 409*ed2a80fdSPablo de Lara need_flush = 0; 410*ed2a80fdSPablo de Lara continue; 411*ed2a80fdSPablo de Lara } 412*ed2a80fdSPablo de Lara 413*ed2a80fdSPablo de Lara handle_packets(h, (struct rte_mbuf **)pkts, rx_pkts); 414*ed2a80fdSPablo de Lara 415*ed2a80fdSPablo de Lara need_flush = 1; 416*ed2a80fdSPablo de Lara } 417*ed2a80fdSPablo de Lara } 418