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