New upstream version 18.02
[deb_dpdk.git] / test / test-pipeline / pipeline_lpm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8
9 #include <rte_log.h>
10 #include <rte_ethdev.h>
11 #include <rte_ether.h>
12 #include <rte_ip.h>
13 #include <rte_byteorder.h>
14
15 #include <rte_port_ring.h>
16 #include <rte_table_lpm.h>
17 #include <rte_pipeline.h>
18
19 #include "main.h"
20
21 #ifndef PIPELINE_LPM_TABLE_NUMBER_TABLE8s
22 #define PIPELINE_LPM_TABLE_NUMBER_TABLE8s 256
23 #endif
24
25 void
26 app_main_loop_worker_pipeline_lpm(void) {
27         struct rte_pipeline_params pipeline_params = {
28                 .name = "pipeline",
29                 .socket_id = rte_socket_id(),
30         };
31
32         struct rte_pipeline *p;
33         uint32_t port_in_id[APP_MAX_PORTS];
34         uint32_t port_out_id[APP_MAX_PORTS];
35         uint32_t table_id;
36         uint32_t i;
37
38         RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with "
39                 "LPM table)\n", rte_lcore_id());
40
41         /* Pipeline configuration */
42         p = rte_pipeline_create(&pipeline_params);
43         if (p == NULL)
44                 rte_panic("Unable to configure the pipeline\n");
45
46         /* Input port configuration */
47         for (i = 0; i < app.n_ports; i++) {
48                 struct rte_port_ring_reader_params port_ring_params = {
49                         .ring = app.rings_rx[i],
50                 };
51
52                 struct rte_pipeline_port_in_params port_params = {
53                         .ops = &rte_port_ring_reader_ops,
54                         .arg_create = (void *) &port_ring_params,
55                         .f_action = NULL,
56                         .arg_ah = NULL,
57                         .burst_size = app.burst_size_worker_read,
58                 };
59
60                 if (rte_pipeline_port_in_create(p, &port_params,
61                         &port_in_id[i]))
62                         rte_panic("Unable to configure input port for "
63                                 "ring %d\n", i);
64         }
65
66         /* Output port configuration */
67         for (i = 0; i < app.n_ports; i++) {
68                 struct rte_port_ring_writer_params port_ring_params = {
69                         .ring = app.rings_tx[i],
70                         .tx_burst_sz = app.burst_size_worker_write,
71                 };
72
73                 struct rte_pipeline_port_out_params port_params = {
74                         .ops = &rte_port_ring_writer_ops,
75                         .arg_create = (void *) &port_ring_params,
76                         .f_action = NULL,
77                         .arg_ah = NULL,
78                 };
79
80                 if (rte_pipeline_port_out_create(p, &port_params,
81                         &port_out_id[i]))
82                         rte_panic("Unable to configure output port for "
83                                 "ring %d\n", i);
84         }
85
86         /* Table configuration */
87         {
88                 struct rte_table_lpm_params table_lpm_params = {
89                         .name = "LPM",
90                         .n_rules = 1 << 24,
91                         .number_tbl8s = PIPELINE_LPM_TABLE_NUMBER_TABLE8s,
92                         .flags = 0,
93                         .entry_unique_size =
94                                 sizeof(struct rte_pipeline_table_entry),
95                         .offset = APP_METADATA_OFFSET(32),
96                 };
97
98                 struct rte_pipeline_table_params table_params = {
99                         .ops = &rte_table_lpm_ops,
100                         .arg_create = &table_lpm_params,
101                         .f_action_hit = NULL,
102                         .f_action_miss = NULL,
103                         .arg_ah = NULL,
104                         .action_data_size = 0,
105                 };
106
107                 if (rte_pipeline_table_create(p, &table_params, &table_id))
108                         rte_panic("Unable to configure the LPM table\n");
109         }
110
111         /* Interconnecting ports and tables */
112         for (i = 0; i < app.n_ports; i++)
113                 if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
114                         table_id))
115                         rte_panic("Unable to connect input port %u to "
116                                 "table %u\n", port_in_id[i],  table_id);
117
118         /* Add entries to tables */
119         for (i = 0; i < app.n_ports; i++) {
120                 struct rte_pipeline_table_entry entry = {
121                         .action = RTE_PIPELINE_ACTION_PORT,
122                         {.port_id = port_out_id[i & (app.n_ports - 1)]},
123                 };
124
125                 struct rte_table_lpm_key key = {
126                         .ip = i << (24 - __builtin_popcount(app.n_ports - 1)),
127                         .depth = 8 + __builtin_popcount(app.n_ports - 1),
128                 };
129
130                 struct rte_pipeline_table_entry *entry_ptr;
131
132                 int key_found, status;
133
134                 printf("Adding rule to LPM table (IPv4 destination = %"
135                         PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu8
136                         " => port out = %" PRIu32 ")\n",
137                         (key.ip & 0xFF000000) >> 24,
138                         (key.ip & 0x00FF0000) >> 16,
139                         (key.ip & 0x0000FF00) >> 8,
140                         key.ip & 0x000000FF,
141                         key.depth,
142                         i);
143
144                 status = rte_pipeline_table_entry_add(p, table_id, &key, &entry,
145                         &key_found, &entry_ptr);
146                 if (status < 0)
147                         rte_panic("Unable to add entry to table %u (%d)\n",
148                                 table_id, status);
149         }
150
151         /* Enable input ports */
152         for (i = 0; i < app.n_ports; i++)
153                 if (rte_pipeline_port_in_enable(p, port_in_id[i]))
154                         rte_panic("Unable to enable input port %u\n",
155                                 port_in_id[i]);
156
157         /* Check pipeline consistency */
158         if (rte_pipeline_check(p) < 0)
159                 rte_panic("Pipeline consistency check failed\n");
160
161         /* Run-time */
162 #if APP_FLUSH == 0
163         for ( ; ; )
164                 rte_pipeline_run(p);
165 #else
166         for (i = 0; ; i++) {
167                 rte_pipeline_run(p);
168
169                 if ((i & APP_FLUSH) == 0)
170                         rte_pipeline_flush(p);
171         }
172 #endif
173 }