remove version in all files
[dpdk.git] / examples / vmdq_dcb / main.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 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 <stdint.h>
36 #include <sys/queue.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <assert.h>
42 #include <errno.h>
43 #include <signal.h>
44 #include <stdarg.h>
45 #include <inttypes.h>
46
47 #include <rte_common.h>
48 #include <rte_log.h>
49 #include <rte_memory.h>
50 #include <rte_memcpy.h>
51 #include <rte_memzone.h>
52 #include <rte_tailq.h>
53 #include <rte_eal.h>
54 #include <rte_per_lcore.h>
55 #include <rte_launch.h>
56 #include <rte_atomic.h>
57 #include <rte_cycles.h>
58 #include <rte_prefetch.h>
59 #include <rte_lcore.h>
60 #include <rte_per_lcore.h>
61 #include <rte_branch_prediction.h>
62 #include <rte_interrupts.h>
63 #include <rte_pci.h>
64 #include <rte_random.h>
65 #include <rte_debug.h>
66 #include <rte_ether.h>
67 #include <rte_ethdev.h>
68 #include <rte_ring.h>
69 #include <rte_log.h>
70 #include <rte_mempool.h>
71 #include <rte_mbuf.h>
72 #include <rte_memcpy.h>
73
74 #include "main.h"
75
76 /* basic constants used in application */
77 #define SOCKET0 0
78 #define SOCKET1 1
79
80 #define NUM_QUEUES 128
81
82 #define NUM_MBUFS 64*1024
83 #define MBUF_CACHE_SIZE 64
84 #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
85
86 /* Basic application settings */
87 #define NUM_POOLS ETH_16_POOLS /* can be ETH_16_POOLS or ETH_32_POOLS */
88
89 #define RX_PORT 0
90 #define TX_PORT 1
91
92 /*
93  * RX and TX Prefetch, Host, and Write-back threshold values should be
94  * carefully set for optimal performance. Consult the network
95  * controller's datasheet and supporting DPDK documentation for guidance
96  * on how these parameters should be set.
97  */
98 /* Default configuration for rx and tx thresholds etc. */
99 static const struct rte_eth_rxconf rx_conf_default = {
100         .rx_thresh = {
101                 .pthresh = 8,
102                 .hthresh = 8,
103                 .wthresh = 4,
104         },
105 };
106
107 /*
108  * These default values are optimized for use with the Intel(R) 82599 10 GbE
109  * Controller and the DPDK ixgbe PMD. Consider using other values for other
110  * network controllers and/or network drivers.
111  */
112 static const struct rte_eth_txconf tx_conf_default = {
113         .tx_thresh = {
114                 .pthresh = 36,
115                 .hthresh = 0,
116                 .wthresh = 0,
117         },
118         .tx_free_thresh = 0, /* Use PMD default values */
119         .tx_rs_thresh = 0, /* Use PMD default values */
120 };
121
122 /* empty vmdq+dcb configuration structure. Filled in programatically */
123 static const struct rte_eth_conf vmdq_dcb_conf_default = {
124         .rxmode = {
125                 .mq_mode        = ETH_VMDQ_DCB,
126                 .split_hdr_size = 0,
127                 .header_split   = 0, /**< Header Split disabled */
128                 .hw_ip_checksum = 0, /**< IP checksum offload disabled */
129                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
130                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
131         },
132         .txmode = {
133         },
134         .rx_adv_conf = {
135                 /*
136                  * should be overridden separately in code with
137                  * appropriate values
138                  */
139                 .vmdq_dcb_conf = {
140                         .nb_queue_pools = NUM_POOLS,
141                         .enable_default_pool = 0,
142                         .default_pool = 0,
143                         .nb_pool_maps = 0,
144                         .pool_map = {{0, 0},},
145                         .dcb_queue = {0},
146                 },
147         },
148 };
149
150 /* array used for printing out statistics */
151 volatile unsigned long rxPackets[ NUM_QUEUES ] = {0};
152
153 const uint16_t vlan_tags[] = {
154         0,  1,  2,  3,  4,  5,  6,  7,
155         8,  9, 10, 11,  12, 13, 14, 15,
156         16, 17, 18, 19, 20, 21, 22, 23,
157         24, 25, 26, 27, 28, 29, 30, 31
158 };
159
160 /* Builds up the correct configuration for vmdq+dcb based on the vlan tags array
161  * given above, and the number of traffic classes available for use. */
162 static inline int
163 get_eth_conf(struct rte_eth_conf *eth_conf, enum rte_eth_nb_pools num_pools)
164 {
165         struct rte_eth_vmdq_dcb_conf conf;
166         unsigned i;
167
168         if (num_pools != ETH_16_POOLS && num_pools != ETH_32_POOLS ) return -1;
169
170         conf.nb_queue_pools = num_pools;
171         conf.enable_default_pool = 0;
172         conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]);
173         for (i = 0; i < conf.nb_pool_maps; i++){
174                 conf.pool_map[i].vlan_id = vlan_tags[ i ];
175                 conf.pool_map[i].pools = 1 << (i % num_pools);
176         }
177         for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){
178                 conf.dcb_queue[i] = (uint8_t)(i % (NUM_QUEUES/num_pools));
179         }
180         rte_memcpy(eth_conf, &vmdq_dcb_conf_default, sizeof(*eth_conf));
181         rte_memcpy(&eth_conf->rx_adv_conf.vmdq_dcb_conf, &conf,
182                    sizeof(eth_conf->rx_adv_conf.vmdq_dcb_conf));
183         return 0;
184 }
185
186 /*
187  * Initialises a given port using global settings and with the rx buffers
188  * coming from the mbuf_pool passed as parameter
189  */
190 static inline int
191 port_init(uint8_t port, struct rte_mempool *mbuf_pool)
192 {
193         struct rte_eth_conf port_conf;
194         const uint16_t rxRings = ETH_VMDQ_DCB_NUM_QUEUES,
195                 txRings = (uint16_t)rte_lcore_count();
196         const uint16_t rxRingSize = 128, txRingSize = 512;
197         int retval;
198         uint16_t q;
199
200         get_eth_conf(&port_conf, NUM_POOLS);
201
202         if (port >= rte_eth_dev_count()) return -1;
203
204         retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf);
205         if (retval != 0)
206                 return retval;
207
208         for (q = 0; q < rxRings; q ++) {
209                 retval = rte_eth_rx_queue_setup(port, q, rxRingSize,
210                                                 SOCKET0, &rx_conf_default,
211                                                 mbuf_pool);
212                 if (retval < 0)
213                         return retval;
214         }
215
216         for (q = 0; q < txRings; q ++) {
217                 retval = rte_eth_tx_queue_setup(port, q, txRingSize,
218                                                 SOCKET0, &tx_conf_default);
219                 if (retval < 0)
220                         return retval;
221         }
222
223         retval  = rte_eth_dev_start(port);
224         if (retval < 0)
225                 return retval;
226
227         return 0;
228 }
229
230 #ifndef RTE_EXEC_ENV_BAREMETAL
231 /* When we receive a HUP signal, print out our stats */
232 static void
233 sighup_handler(int signum)
234 {
235         unsigned q;
236         for (q = 0; q < NUM_QUEUES; q ++) {
237                 if (q % (NUM_QUEUES/NUM_POOLS) == 0)
238                         printf("\nPool %u: ", q/(NUM_QUEUES/NUM_POOLS));
239                 printf("%lu ", rxPackets[ q ]);
240         }
241         printf("\nFinished handling signal %d\n", signum);
242 }
243 #endif
244
245 /*
246  * Main thread that does the work, reading from INPUT_PORT
247  * and writing to OUTPUT_PORT
248  */
249 static  __attribute__((noreturn)) int
250 lcore_main(void *arg)
251 {
252         const uintptr_t core_num = (uintptr_t)arg;
253         const unsigned num_cores = rte_lcore_count();
254         uint16_t startQueue = (uint16_t)(core_num * (NUM_QUEUES/num_cores));
255         uint16_t endQueue = (uint16_t)(startQueue + (NUM_QUEUES/num_cores));
256         uint16_t q, i;
257
258         printf("Core %u(lcore %u) reading queues %i-%i\n", (unsigned)core_num,
259                rte_lcore_id(), startQueue, endQueue - 1);
260
261         for (;;) {
262                 struct rte_mbuf *buf[32];
263                 const uint16_t buf_size = sizeof(buf) / sizeof(buf[0]);
264
265                 for (q = startQueue; q < endQueue; q++) {
266                         const uint16_t rxCount = rte_eth_rx_burst(RX_PORT,
267                                         q, buf, buf_size);
268                         if (rxCount == 0)
269                                 continue;
270                         rxPackets[q] += rxCount;
271
272                         const uint16_t txCount = rte_eth_tx_burst(TX_PORT,
273                                         (uint16_t)core_num, buf, rxCount);
274                         if (txCount != rxCount) {
275                                 for (i = txCount; i < rxCount; i++)
276                                         rte_pktmbuf_free(buf[i]);
277                         }
278                 }
279         }
280 }
281
282 /* Main function, does initialisation and calls the per-lcore functions */
283 int
284 MAIN(int argc, char *argv[])
285 {
286         unsigned cores;
287         struct rte_mempool *mbuf_pool;
288         unsigned lcore_id;
289         uintptr_t i;
290
291 #ifndef RTE_EXEC_ENV_BAREMETAL
292         signal(SIGHUP, sighup_handler);
293 #endif
294
295         if (rte_eal_init(argc, argv) < 0)
296                 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
297         if (rte_igb_pmd_init() != 0 ||
298                         rte_ixgbe_pmd_init() != 0 ||
299                         rte_eal_pci_probe() != 0)
300                 rte_exit(EXIT_FAILURE, "Error with NIC driver initialization\n");
301
302         cores = rte_lcore_count();
303         if ((cores & (cores - 1)) != 0 || cores > 16) {
304                 rte_exit(EXIT_FAILURE,
305                          "This program can only run on 2,4,8 or 16 cores\n\n");
306         }
307
308         mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS,
309                                        MBUF_SIZE, MBUF_CACHE_SIZE,
310                                        sizeof(struct rte_pktmbuf_pool_private),
311                                        rte_pktmbuf_pool_init, NULL,
312                                        rte_pktmbuf_init, NULL,
313                                        SOCKET0, 0);
314         if (mbuf_pool == NULL)
315                 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
316
317         if (port_init(RX_PORT, mbuf_pool) != 0 ||
318             port_init(TX_PORT, mbuf_pool) != 0)
319                 rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n");
320
321         /* call lcore_main() on every slave lcore */
322         i = 0;
323         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
324                 rte_eal_remote_launch(lcore_main, (void*)i++, lcore_id);
325         }
326         /* call on master too */
327         (void) lcore_main((void*)i);
328
329         return 0;
330 }