tests/dpdk/ring_client: extend range of supported dpdkr ports
[cascardo/ovs.git] / tests / dpdk / ring_client.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <getopt.h>
36
37 #include <config.h>
38 #include <rte_config.h>
39 #include <rte_mbuf.h>
40 #include <rte_ether.h>
41 #include <rte_string_fns.h>
42 #include <rte_ip.h>
43 #include <rte_byteorder.h>
44
45 #include "util.h"
46
47 /* Number of packets to attempt to read from queue. */
48 #define PKT_READ_SIZE  ((uint16_t)32)
49
50 /* Define common names for structures shared between ovs_dpdk and client. */
51 #define MP_CLIENT_RXQ_NAME "dpdkr%u_tx"
52 #define MP_CLIENT_TXQ_NAME "dpdkr%u_rx"
53
54 #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
55
56 /* Our client id number - tells us which rx queue to read, and tx
57  * queue to write to.
58  */
59 static unsigned int client_id;
60
61 /*
62  * Given the rx queue name template above, get the queue name.
63  */
64 static inline const char *
65 get_rx_queue_name(unsigned int id)
66 {
67     /* Buffer for return value. */
68     static char buffer[RTE_RING_NAMESIZE];
69
70     snprintf(buffer, sizeof(buffer), MP_CLIENT_RXQ_NAME, id);
71     return buffer;
72 }
73
74 /*
75  * Given the tx queue name template above, get the queue name.
76  */
77 static inline const char *
78 get_tx_queue_name(unsigned int id)
79 {
80     /* Buffer for return value. */
81     static char buffer[RTE_RING_NAMESIZE];
82
83     snprintf(buffer, sizeof(buffer), MP_CLIENT_TXQ_NAME, id);
84     return buffer;
85 }
86
87 /*
88  * Print a usage message.
89  */
90 static void
91 usage(const char *progname)
92 {
93     printf("\nUsage: %s [EAL args] -- -n <client_id>\n", progname);
94 }
95
96 /*
97  * Convert the client id number from a string to an usigned int.
98  */
99 static int
100 parse_client_num(const char *client)
101 {
102     if (str_to_uint(client, 10, &client_id)) {
103         return 0;
104     } else {
105         return -1;
106     }
107 }
108
109 /*
110  * Parse the application arguments to the client app.
111  */
112 static int
113 parse_app_args(int argc, char *argv[])
114 {
115     int option_index = 0, opt = 0;
116     char **argvopt = argv;
117     const char *progname = NULL;
118     static struct option lgopts[] = {
119         {NULL, 0, NULL, 0 }
120     };
121     progname = argv[0];
122
123     while ((opt = getopt_long(argc, argvopt, "n:", lgopts,
124         &option_index)) != EOF) {
125         switch (opt) {
126             case 'n':
127                 if (parse_client_num(optarg) != 0) {
128                     usage(progname);
129                     return -1;
130                 }
131                 break;
132             default:
133                 usage(progname);
134                 return -1;
135         }
136     }
137
138     return 0;
139 }
140
141 /*
142  * Application main function - loops through
143  * receiving and processing packets. Never returns
144  */
145 int
146 main(int argc, char *argv[])
147 {
148     struct rte_ring *rx_ring = NULL;
149     struct rte_ring *tx_ring = NULL;
150     int retval = 0;
151     void *pkts[PKT_READ_SIZE];
152     int rslt = 0;
153
154     if ((retval = rte_eal_init(argc, argv)) < 0) {
155         return -1;
156     }
157
158     argc -= retval;
159     argv += retval;
160
161     if (parse_app_args(argc, argv) < 0) {
162         rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
163     }
164
165     rx_ring = rte_ring_lookup(get_rx_queue_name(client_id));
166     if (rx_ring == NULL) {
167         rte_exit(EXIT_FAILURE,
168             "Cannot get RX ring - is server process running?\n");
169     }
170
171     tx_ring = rte_ring_lookup(get_tx_queue_name(client_id));
172     if (tx_ring == NULL) {
173         rte_exit(EXIT_FAILURE,
174             "Cannot get TX ring - is server process running?\n");
175     }
176
177     RTE_LOG(INFO, APP, "Finished Process Init.\n");
178
179     printf("\nClient process %d handling packets\n", client_id);
180     printf("[Press Ctrl-C to quit ...]\n");
181
182     for (;;) {
183         unsigned rx_pkts = PKT_READ_SIZE;
184
185         /* Try dequeuing max possible packets first, if that fails, get the
186          * most we can. Loop body should only execute once, maximum.
187          */
188         while (unlikely(rte_ring_dequeue_bulk(rx_ring, pkts, rx_pkts) != 0) &&
189             rx_pkts > 0) {
190             rx_pkts = (uint16_t)RTE_MIN(rte_ring_count(rx_ring), PKT_READ_SIZE);
191         }
192
193         if (rx_pkts > 0) {
194             /* blocking enqueue */
195             do {
196                 rslt = rte_ring_enqueue_bulk(tx_ring, pkts, rx_pkts);
197             } while (rslt == -ENOBUFS);
198         }
199     }
200 }