2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-23 14:57:06 +00:00
Files
openvswitch/tests/dpdk/ring_client.c
Ethan Jackson bce01e3a89 netdev-dpdk: Fix sparse warnings.
These are all minor style issues.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
Acked-by: Daniele Di Proietto <diproiettod@vmware.com>
2015-05-19 14:47:00 -07:00

216 lines
6.0 KiB
C

/*
* BSD LICENSE
*
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <getopt.h>
#include <config.h>
#include <rte_config.h>
#include <rte_mbuf.h>
#include <rte_ether.h>
#include <rte_string_fns.h>
#include <rte_ip.h>
#include <rte_byteorder.h>
/* Number of packets to attempt to read from queue. */
#define PKT_READ_SIZE ((uint16_t)32)
/* Define common names for structures shared between ovs_dpdk and client. */
#define MP_CLIENT_RXQ_NAME "dpdkr%u_tx"
#define MP_CLIENT_TXQ_NAME "dpdkr%u_rx"
#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
#define BASE_10 10
/* Our client id number - tells us which rx queue to read, and tx
* queue to write to.
*/
static uint8_t client_id = 0;
/*
* Given the rx queue name template above, get the queue name.
*/
static inline const char *
get_rx_queue_name(unsigned id)
{
/* Buffer for return value. Size calculated by %u being replaced
* by maximum 3 digits (plus an extra byte for safety).
*/
static char buffer[sizeof(MP_CLIENT_RXQ_NAME) + 2];
snprintf(buffer, sizeof(buffer) - 1, MP_CLIENT_RXQ_NAME, id);
return buffer;
}
/*
* Given the tx queue name template above, get the queue name.
*/
static inline const char *
get_tx_queue_name(unsigned id)
{
/* Buffer for return value. Size calculated by %u being replaced
* by maximum 3 digits (plus an extra byte for safety).
*/
static char buffer[sizeof(MP_CLIENT_TXQ_NAME) + 2];
snprintf(buffer, sizeof(buffer) - 1, MP_CLIENT_TXQ_NAME, id);
return buffer;
}
/*
* Print a usage message.
*/
static void
usage(const char *progname)
{
printf("\nUsage: %s [EAL args] -- -n <client_id>\n", progname);
}
/*
* Convert the client id number from a string to an int.
*/
static int
parse_client_num(const char *client)
{
char *end = NULL;
unsigned long temp = 0;
if (client == NULL || *client == '\0') {
return -1;
}
temp = strtoul(client, &end, BASE_10);
/* If valid string argument is provided, terminating '/0' character
* is stored in 'end'. */
if (end == NULL || *end != '\0') {
return -1;
}
client_id = (uint8_t)temp;
return 0;
}
/*
* Parse the application arguments to the client app.
*/
static int
parse_app_args(int argc, char *argv[])
{
int option_index = 0, opt = 0;
char **argvopt = argv;
const char *progname = NULL;
static struct option lgopts[] = {
{NULL, 0, NULL, 0 }
};
progname = argv[0];
while ((opt = getopt_long(argc, argvopt, "n:", lgopts,
&option_index)) != EOF) {
switch (opt) {
case 'n':
if (parse_client_num(optarg) != 0) {
usage(progname);
return -1;
}
break;
default:
usage(progname);
return -1;
}
}
return 0;
}
/*
* Application main function - loops through
* receiving and processing packets. Never returns
*/
int
main(int argc, char *argv[])
{
struct rte_ring *rx_ring = NULL;
struct rte_ring *tx_ring = NULL;
int retval = 0;
void *pkts[PKT_READ_SIZE];
int rslt = 0;
if ((retval = rte_eal_init(argc, argv)) < 0) {
return -1;
}
argc -= retval;
argv += retval;
if (parse_app_args(argc, argv) < 0) {
rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
}
rx_ring = rte_ring_lookup(get_rx_queue_name(client_id));
if (rx_ring == NULL) {
rte_exit(EXIT_FAILURE,
"Cannot get RX ring - is server process running?\n");
}
tx_ring = rte_ring_lookup(get_tx_queue_name(client_id));
if (tx_ring == NULL) {
rte_exit(EXIT_FAILURE,
"Cannot get TX ring - is server process running?\n");
}
RTE_LOG(INFO, APP, "Finished Process Init.\n");
printf("\nClient process %d handling packets\n", client_id);
printf("[Press Ctrl-C to quit ...]\n");
for (;;) {
unsigned rx_pkts = PKT_READ_SIZE;
/* Try dequeuing max possible packets first, if that fails, get the
* most we can. Loop body should only execute once, maximum.
*/
while (unlikely(rte_ring_dequeue_bulk(rx_ring, pkts, rx_pkts) != 0) &&
rx_pkts > 0) {
rx_pkts = (uint16_t)RTE_MIN(rte_ring_count(rx_ring), PKT_READ_SIZE);
}
if (rx_pkts > 0) {
/* blocking enqueue */
do {
rslt = rte_ring_enqueue_bulk(tx_ring, pkts, rx_pkts);
} while (rslt == -ENOBUFS);
}
}
}