apps: use helper to create mbuf pools
[dpdk.git] / examples / ip_pipeline / init.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 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdint.h>
37 #include <inttypes.h>
38 #include <sys/types.h>
39 #include <string.h>
40 #include <sys/queue.h>
41 #include <stdarg.h>
42 #include <errno.h>
43 #include <getopt.h>
44
45 #include <rte_common.h>
46 #include <rte_byteorder.h>
47 #include <rte_log.h>
48 #include <rte_memory.h>
49 #include <rte_memcpy.h>
50 #include <rte_memzone.h>
51 #include <rte_eal.h>
52 #include <rte_per_lcore.h>
53 #include <rte_launch.h>
54 #include <rte_atomic.h>
55 #include <rte_cycles.h>
56 #include <rte_prefetch.h>
57 #include <rte_lcore.h>
58 #include <rte_per_lcore.h>
59 #include <rte_branch_prediction.h>
60 #include <rte_interrupts.h>
61 #include <rte_pci.h>
62 #include <rte_random.h>
63 #include <rte_debug.h>
64 #include <rte_ether.h>
65 #include <rte_ethdev.h>
66 #include <rte_ring.h>
67 #include <rte_mempool.h>
68 #include <rte_malloc.h>
69 #include <rte_mbuf.h>
70 #include <rte_string_fns.h>
71 #include <rte_ip.h>
72 #include <rte_tcp.h>
73 #include <rte_lpm.h>
74 #include <rte_lpm6.h>
75
76 #include "main.h"
77
78 #define NA                             APP_SWQ_INVALID
79
80 struct app_params app = {
81         /* CPU cores */
82         .cores = {
83         {0, APP_CORE_MASTER, {15, 16, 17, NA, NA, NA, NA, NA},
84                 {12, 13, 14, NA, NA, NA, NA, NA} },
85         {0, APP_CORE_RX,     {NA, NA, NA, NA, NA, NA, NA, 12},
86                 { 0,  1,  2,  3, NA, NA, NA, 15} },
87         {0, APP_CORE_FC,     { 0,  1,  2,  3, NA, NA, NA, 13},
88                 { 4,  5,  6,  7, NA, NA, NA, 16} },
89         {0, APP_CORE_RT,     { 4,  5,  6,  7, NA, NA, NA, 14},
90                 { 8,  9, 10, 11, NA, NA, NA, 17} },
91         {0, APP_CORE_TX,     { 8,  9, 10, 11, NA, NA, NA, NA},
92                 {NA, NA, NA, NA, NA, NA, NA, NA} },
93         },
94
95         /* Ports*/
96         .n_ports = APP_MAX_PORTS,
97         .rsz_hwq_rx = 128,
98         .rsz_hwq_tx = 512,
99         .bsz_hwq_rd = 64,
100         .bsz_hwq_wr = 64,
101
102         .port_conf = {
103                 .rxmode = {
104                         .split_hdr_size = 0,
105                         .header_split   = 0, /* Header Split disabled */
106                         .hw_ip_checksum = 1, /* IP checksum offload enabled */
107                         .hw_vlan_filter = 0, /* VLAN filtering disabled */
108                         .jumbo_frame    = 1, /* Jumbo Frame Support enabled */
109                         .max_rx_pkt_len = 9000, /* Jumbo Frame MAC pkt length */
110                         .hw_strip_crc   = 0, /* CRC stripped by hardware */
111                 },
112                 .rx_adv_conf = {
113                         .rss_conf = {
114                                 .rss_key = NULL,
115                                 .rss_hf = ETH_RSS_IP,
116                         },
117                 },
118                 .txmode = {
119                         .mq_mode = ETH_MQ_TX_NONE,
120                 },
121         },
122
123         .rx_conf = {
124                 .rx_thresh = {
125                         .pthresh = 8,
126                         .hthresh = 8,
127                         .wthresh = 4,
128                 },
129                 .rx_free_thresh = 64,
130                 .rx_drop_en = 0,
131         },
132
133         .tx_conf = {
134                 .tx_thresh = {
135                         .pthresh = 36,
136                         .hthresh = 0,
137                         .wthresh = 0,
138                 },
139                 .tx_free_thresh = 0,
140                 .tx_rs_thresh = 0,
141         },
142
143         /* SWQs */
144         .rsz_swq = 128,
145         .bsz_swq_rd = 64,
146         .bsz_swq_wr = 64,
147
148         /* Buffer pool */
149         .pool_buffer_size = 2048 + RTE_PKTMBUF_HEADROOM,
150         .pool_size = 32 * 1024,
151         .pool_cache_size = 256,
152
153         /* Message buffer pool */
154         .msg_pool_buffer_size = 256,
155         .msg_pool_size = 1024,
156         .msg_pool_cache_size = 64,
157
158         /* Rule tables */
159         .max_arp_rules = 1 << 10,
160         .max_firewall_rules = 1 << 5,
161         .max_routing_rules = 1 << 24,
162         .max_flow_rules = 1 << 24,
163
164         /* Application processing */
165         .ether_hdr_pop_push = 0,
166 };
167
168 struct app_core_params *
169 app_get_core_params(uint32_t core_id)
170 {
171         uint32_t i;
172
173         for (i = 0; i < RTE_MAX_LCORE; i++) {
174                 struct app_core_params *p = &app.cores[i];
175
176                 if (p->core_id != core_id)
177                         continue;
178
179                 return p;
180         }
181
182         return NULL;
183 }
184
185 static uint32_t
186 app_get_n_swq_in(void)
187 {
188         uint32_t max_swq_id = 0, i, j;
189
190         for (i = 0; i < RTE_MAX_LCORE; i++) {
191                 struct app_core_params *p = &app.cores[i];
192
193                 if (p->core_type == APP_CORE_NONE)
194                         continue;
195
196                 for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++) {
197                         uint32_t swq_id = p->swq_in[j];
198
199                         if ((swq_id != APP_SWQ_INVALID) &&
200                                 (swq_id > max_swq_id))
201                                 max_swq_id = swq_id;
202                 }
203         }
204
205         return (1 + max_swq_id);
206 }
207
208 static uint32_t
209 app_get_n_swq_out(void)
210 {
211         uint32_t max_swq_id = 0, i, j;
212
213         for (i = 0; i < RTE_MAX_LCORE; i++) {
214                 struct app_core_params *p = &app.cores[i];
215
216                 if (p->core_type == APP_CORE_NONE)
217                         continue;
218
219                 for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++) {
220                         uint32_t swq_id = p->swq_out[j];
221
222                         if ((swq_id != APP_SWQ_INVALID) &&
223                                 (swq_id > max_swq_id))
224                                 max_swq_id = swq_id;
225                 }
226         }
227
228         return (1 + max_swq_id);
229 }
230
231 static uint32_t
232 app_get_swq_in_count(uint32_t swq_id)
233 {
234         uint32_t n, i;
235
236         for (n = 0, i = 0; i < RTE_MAX_LCORE; i++) {
237                 struct app_core_params *p = &app.cores[i];
238                 uint32_t j;
239
240                 if (p->core_type == APP_CORE_NONE)
241                         continue;
242
243                 for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
244                         if (p->swq_in[j] == swq_id)
245                                 n++;
246         }
247
248         return n;
249 }
250
251 static uint32_t
252 app_get_swq_out_count(uint32_t swq_id)
253 {
254         uint32_t n, i;
255
256         for (n = 0, i = 0; i < RTE_MAX_LCORE; i++) {
257                 struct app_core_params *p = &app.cores[i];
258                 uint32_t j;
259
260                 if (p->core_type == APP_CORE_NONE)
261                         continue;
262
263                 for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
264                         if (p->swq_out[j] == swq_id)
265                                 n++;
266         }
267
268         return n;
269 }
270
271 void
272 app_check_core_params(void)
273 {
274         uint32_t n_swq_in = app_get_n_swq_in();
275         uint32_t n_swq_out = app_get_n_swq_out();
276         uint32_t i;
277
278         /* Check that range of SW queues is contiguous and each SW queue has
279            exactly one reader and one writer */
280         if (n_swq_in != n_swq_out)
281                 rte_panic("Number of input SW queues is not equal to the "
282                         "number of output SW queues\n");
283
284         for (i = 0; i < n_swq_in; i++) {
285                 uint32_t n = app_get_swq_in_count(i);
286
287                 if (n == 0)
288                         rte_panic("SW queue %u has no reader\n", i);
289
290                 if (n > 1)
291                         rte_panic("SW queue %u has more than one reader\n", i);
292         }
293
294         for (i = 0; i < n_swq_out; i++) {
295                 uint32_t n = app_get_swq_out_count(i);
296
297                 if (n == 0)
298                         rte_panic("SW queue %u has no writer\n", i);
299
300                 if (n > 1)
301                         rte_panic("SW queue %u has more than one writer\n", i);
302         }
303
304         /* Check the request and response queues are valid */
305         for (i = 0; i < RTE_MAX_LCORE; i++) {
306                 struct app_core_params *p = &app.cores[i];
307                 uint32_t ring_id_req, ring_id_resp;
308
309                 if ((p->core_type != APP_CORE_FC) &&
310                     (p->core_type != APP_CORE_FW) &&
311                         (p->core_type != APP_CORE_RT)) {
312                         continue;
313                 }
314
315                 ring_id_req = p->swq_in[APP_SWQ_IN_REQ];
316                 if (ring_id_req == APP_SWQ_INVALID)
317                         rte_panic("Core %u of type %u has invalid request "
318                                 "queue ID\n", p->core_id, p->core_type);
319
320                 ring_id_resp = p->swq_out[APP_SWQ_OUT_RESP];
321                 if (ring_id_resp == APP_SWQ_INVALID)
322                         rte_panic("Core %u of type %u has invalid response "
323                                 "queue ID\n", p->core_id, p->core_type);
324         }
325
326         return;
327 }
328
329 uint32_t
330 app_get_first_core_id(enum app_core_type core_type)
331 {
332         uint32_t i;
333
334         for (i = 0; i < RTE_MAX_LCORE; i++) {
335                 struct app_core_params *p = &app.cores[i];
336
337                 if (p->core_type == core_type)
338                         return p->core_id;
339         }
340
341         return RTE_MAX_LCORE;
342 }
343
344 struct rte_ring *
345 app_get_ring_req(uint32_t core_id)
346 {
347         struct app_core_params *p = app_get_core_params(core_id);
348         uint32_t ring_req_id = p->swq_in[APP_SWQ_IN_REQ];
349
350         return app.rings[ring_req_id];
351 }
352
353 struct rte_ring *
354 app_get_ring_resp(uint32_t core_id)
355 {
356         struct app_core_params *p = app_get_core_params(core_id);
357         uint32_t ring_resp_id = p->swq_out[APP_SWQ_OUT_RESP];
358
359         return app.rings[ring_resp_id];
360 }
361
362 static void
363 app_init_mbuf_pools(void)
364 {
365         /* Init the buffer pool */
366         RTE_LOG(INFO, USER1, "Creating the mbuf pool ...\n");
367         app.pool = rte_pktmbuf_pool_create("mempool", app.pool_size,
368                 app.pool_cache_size, 0, app.pool_buffer_size, rte_socket_id());
369         if (app.pool == NULL)
370                 rte_panic("Cannot create mbuf pool\n");
371
372         /* Init the indirect buffer pool */
373         RTE_LOG(INFO, USER1, "Creating the indirect mbuf pool ...\n");
374         app.indirect_pool = rte_pktmbuf_pool_create("indirect mempool",
375                 app.pool_size, app.pool_cache_size,
376                 sizeof(struct app_pkt_metadata), 0, rte_socket_id());
377         if (app.indirect_pool == NULL)
378                 rte_panic("Cannot create mbuf pool\n");
379
380         /* Init the message buffer pool */
381         RTE_LOG(INFO, USER1, "Creating the message pool ...\n");
382         app.msg_pool = rte_mempool_create(
383                 "mempool msg",
384                 app.msg_pool_size,
385                 app.msg_pool_buffer_size,
386                 app.msg_pool_cache_size,
387                 0,
388                 NULL, NULL,
389                 rte_ctrlmbuf_init, NULL,
390                 rte_socket_id(),
391                 0);
392         if (app.msg_pool == NULL)
393                 rte_panic("Cannot create message pool\n");
394 }
395
396 static void
397 app_init_rings(void)
398 {
399         uint32_t n_swq, i;
400
401         n_swq = app_get_n_swq_in();
402         RTE_LOG(INFO, USER1, "Initializing %u SW rings ...\n", n_swq);
403
404         app.rings = rte_malloc_socket(NULL, n_swq * sizeof(struct rte_ring *),
405                 RTE_CACHE_LINE_SIZE, rte_socket_id());
406         if (app.rings == NULL)
407                 rte_panic("Cannot allocate memory to store ring pointers\n");
408
409         for (i = 0; i < n_swq; i++) {
410                 struct rte_ring *ring;
411                 char name[32];
412
413                 snprintf(name, sizeof(name), "app_ring_%u", i);
414
415                 ring = rte_ring_create(
416                         name,
417                         app.rsz_swq,
418                         rte_socket_id(),
419                         RING_F_SP_ENQ | RING_F_SC_DEQ);
420
421                 if (ring == NULL)
422                         rte_panic("Cannot create ring %u\n", i);
423
424                 app.rings[i] = ring;
425         }
426 }
427
428 static void
429 app_ports_check_link(void)
430 {
431         uint32_t all_ports_up, i;
432
433         all_ports_up = 1;
434
435         for (i = 0; i < app.n_ports; i++) {
436                 struct rte_eth_link link;
437                 uint32_t port;
438
439                 port = app.ports[i];
440                 memset(&link, 0, sizeof(link));
441                 rte_eth_link_get_nowait(port, &link);
442                 RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n",
443                         port,
444                         link.link_speed / 1000,
445                         link.link_status ? "UP" : "DOWN");
446
447                 if (link.link_status == 0)
448                         all_ports_up = 0;
449         }
450
451         if (all_ports_up == 0)
452                 rte_panic("Some NIC ports are DOWN\n");
453 }
454
455 static void
456 app_init_ports(void)
457 {
458         uint32_t i;
459
460         /* Init NIC ports, then start the ports */
461         for (i = 0; i < app.n_ports; i++) {
462                 uint32_t port;
463                 int ret;
464
465                 port = app.ports[i];
466                 RTE_LOG(INFO, USER1, "Initializing NIC port %u ...\n", port);
467
468                 /* Init port */
469                 ret = rte_eth_dev_configure(
470                         port,
471                         1,
472                         1,
473                         &app.port_conf);
474                 if (ret < 0)
475                         rte_panic("Cannot init NIC port %u (%d)\n", port, ret);
476                 rte_eth_promiscuous_enable(port);
477
478                 /* Init RX queues */
479                 ret = rte_eth_rx_queue_setup(
480                         port,
481                         0,
482                         app.rsz_hwq_rx,
483                         rte_eth_dev_socket_id(port),
484                         &app.rx_conf,
485                         app.pool);
486                 if (ret < 0)
487                         rte_panic("Cannot init RX for port %u (%d)\n",
488                                 (uint32_t) port, ret);
489
490                 /* Init TX queues */
491                 ret = rte_eth_tx_queue_setup(
492                         port,
493                         0,
494                         app.rsz_hwq_tx,
495                         rte_eth_dev_socket_id(port),
496                         &app.tx_conf);
497                 if (ret < 0)
498                         rte_panic("Cannot init TX for port %u (%d)\n", port,
499                                 ret);
500
501                 /* Start port */
502                 ret = rte_eth_dev_start(port);
503                 if (ret < 0)
504                         rte_panic("Cannot start port %u (%d)\n", port, ret);
505         }
506
507         app_ports_check_link();
508 }
509
510 #define APP_PING_TIMEOUT_SEC                               5
511
512 void
513 app_ping(void)
514 {
515         unsigned i;
516         uint64_t timestamp, diff_tsc;
517
518         const uint64_t timeout = rte_get_tsc_hz() * APP_PING_TIMEOUT_SEC;
519
520         for (i = 0; i < RTE_MAX_LCORE; i++) {
521                 struct app_core_params *p = &app.cores[i];
522                 struct rte_ring *ring_req, *ring_resp;
523                 void *msg;
524                 struct app_msg_req *req;
525                 int status;
526
527                 if ((p->core_type != APP_CORE_FC) &&
528                     (p->core_type != APP_CORE_FW) &&
529                         (p->core_type != APP_CORE_RT) &&
530                         (p->core_type != APP_CORE_RX))
531                         continue;
532
533                 ring_req = app_get_ring_req(p->core_id);
534                 ring_resp = app_get_ring_resp(p->core_id);
535
536                 /* Fill request message */
537                 msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
538                 if (msg == NULL)
539                         rte_panic("Unable to allocate new message\n");
540
541                 req = (struct app_msg_req *)
542                                 rte_ctrlmbuf_data((struct rte_mbuf *)msg);
543                 req->type = APP_MSG_REQ_PING;
544
545                 /* Send request */
546                 do {
547                         status = rte_ring_sp_enqueue(ring_req, msg);
548                 } while (status == -ENOBUFS);
549
550                 /* Wait for response */
551                 timestamp = rte_rdtsc();
552                 do {
553                         status = rte_ring_sc_dequeue(ring_resp, &msg);
554                         diff_tsc = rte_rdtsc() - timestamp;
555
556                         if (unlikely(diff_tsc > timeout))
557                                 rte_panic("Core %u of type %d does not respond "
558                                         "to requests\n", p->core_id,
559                                         p->core_type);
560                 } while (status != 0);
561
562                 /* Free message buffer */
563                 rte_ctrlmbuf_free(msg);
564         }
565 }
566
567 static void
568 app_init_etc(void)
569 {
570         if ((app_get_first_core_id(APP_CORE_IPV4_FRAG) != RTE_MAX_LCORE) ||
571                 (app_get_first_core_id(APP_CORE_IPV4_RAS) != RTE_MAX_LCORE)) {
572                 RTE_LOG(INFO, USER1,
573                         "Activating the Ethernet header pop/push ...\n");
574                 app.ether_hdr_pop_push = 1;
575         }
576 }
577
578 void
579 app_init(void)
580 {
581         if ((sizeof(struct app_pkt_metadata) % RTE_CACHE_LINE_SIZE) != 0)
582                 rte_panic("Application pkt meta-data size mismatch\n");
583
584         app_check_core_params();
585
586         app_init_mbuf_pools();
587         app_init_rings();
588         app_init_ports();
589         app_init_etc();
590
591         RTE_LOG(INFO, USER1, "Initialization completed\n");
592 }