New upstream version 18.02
[deb_dpdk.git] / test / test-pipeline / pipeline_hash.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_hash.h>
17 #include <rte_hash.h>
18 #include <rte_pipeline.h>
19
20 #include "main.h"
21
22 static void
23 translate_options(uint32_t *special, uint32_t *ext, uint32_t *key_size)
24 {
25         switch (app.pipeline_type) {
26         case e_APP_PIPELINE_HASH_KEY8_EXT:
27                 *special = 0; *ext = 1; *key_size = 8; return;
28         case e_APP_PIPELINE_HASH_KEY8_LRU:
29                 *special = 0; *ext = 0; *key_size = 8; return;
30         case e_APP_PIPELINE_HASH_KEY16_EXT:
31                 *special = 0; *ext = 1; *key_size = 16; return;
32         case e_APP_PIPELINE_HASH_KEY16_LRU:
33                 *special = 0; *ext = 0; *key_size = 16; return;
34         case e_APP_PIPELINE_HASH_KEY32_EXT:
35                 *special = 0; *ext = 1; *key_size = 32; return;
36         case e_APP_PIPELINE_HASH_KEY32_LRU:
37                 *special = 0; *ext = 0; *key_size = 32; return;
38
39         case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT:
40                 *special = 1; *ext = 1; *key_size = 8; return;
41         case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU:
42                 *special = 1; *ext = 0; *key_size = 8; return;
43         case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT:
44                 *special = 1; *ext = 1; *key_size = 16; return;
45         case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU:
46                 *special = 1; *ext = 0; *key_size = 16; return;
47         case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT:
48                 *special = 1; *ext = 1; *key_size = 32; return;
49         case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU:
50                 *special = 1; *ext = 0; *key_size = 32; return;
51
52         case e_APP_PIPELINE_HASH_CUCKOO_KEY8:
53                 *special = 0; *ext = 0; *key_size = 8; return;
54         case e_APP_PIPELINE_HASH_CUCKOO_KEY16:
55                 *special = 0; *ext = 0; *key_size = 16; return;
56         case e_APP_PIPELINE_HASH_CUCKOO_KEY32:
57                 *special = 0; *ext = 0; *key_size = 32; return;
58         case e_APP_PIPELINE_HASH_CUCKOO_KEY48:
59                 *special = 0; *ext = 0; *key_size = 48; return;
60         case e_APP_PIPELINE_HASH_CUCKOO_KEY64:
61                 *special = 0; *ext = 0; *key_size = 64; return;
62         case e_APP_PIPELINE_HASH_CUCKOO_KEY80:
63                 *special = 0; *ext = 0; *key_size = 80; return;
64         case e_APP_PIPELINE_HASH_CUCKOO_KEY96:
65                 *special = 0; *ext = 0; *key_size = 96; return;
66         case e_APP_PIPELINE_HASH_CUCKOO_KEY112:
67                 *special = 0; *ext = 0; *key_size = 112; return;
68         case e_APP_PIPELINE_HASH_CUCKOO_KEY128:
69                 *special = 0; *ext = 0; *key_size = 128; return;
70
71         default:
72                 rte_panic("Invalid hash table type or key size\n");
73         }
74 }
75 void
76 app_main_loop_worker_pipeline_hash(void) {
77         struct rte_pipeline_params pipeline_params = {
78                 .name = "pipeline",
79                 .socket_id = rte_socket_id(),
80         };
81
82         struct rte_pipeline *p;
83         uint32_t port_in_id[APP_MAX_PORTS];
84         uint32_t port_out_id[APP_MAX_PORTS];
85         uint32_t table_id;
86         uint32_t i;
87         uint32_t special, ext, key_size;
88
89         translate_options(&special, &ext, &key_size);
90
91         RTE_LOG(INFO, USER1, "Core %u is doing work "
92                 "(pipeline with hash table, %s, %s, %d-byte key)\n",
93                 rte_lcore_id(),
94                 special ? "specialized" : "non-specialized",
95                 ext ? "extendible bucket" : "LRU",
96                 key_size);
97
98         /* Pipeline configuration */
99         p = rte_pipeline_create(&pipeline_params);
100         if (p == NULL)
101                 rte_panic("Unable to configure the pipeline\n");
102
103         /* Input port configuration */
104         for (i = 0; i < app.n_ports; i++) {
105                 struct rte_port_ring_reader_params port_ring_params = {
106                         .ring = app.rings_rx[i],
107                 };
108
109                 struct rte_pipeline_port_in_params port_params = {
110                         .ops = &rte_port_ring_reader_ops,
111                         .arg_create = (void *) &port_ring_params,
112                         .f_action = NULL,
113                         .arg_ah = NULL,
114                         .burst_size = app.burst_size_worker_read,
115                 };
116
117                 if (rte_pipeline_port_in_create(p, &port_params,
118                         &port_in_id[i]))
119                         rte_panic("Unable to configure input port for "
120                                 "ring %d\n", i);
121         }
122
123         /* Output port configuration */
124         for (i = 0; i < app.n_ports; i++) {
125                 struct rte_port_ring_writer_params port_ring_params = {
126                         .ring = app.rings_tx[i],
127                         .tx_burst_sz = app.burst_size_worker_write,
128                 };
129
130                 struct rte_pipeline_port_out_params port_params = {
131                         .ops = &rte_port_ring_writer_ops,
132                         .arg_create = (void *) &port_ring_params,
133                         .f_action = NULL,
134                         .arg_ah = NULL,
135                 };
136
137                 if (rte_pipeline_port_out_create(p, &port_params,
138                         &port_out_id[i]))
139                         rte_panic("Unable to configure output port for "
140                                 "ring %d\n", i);
141         }
142
143         struct rte_table_hash_params table_hash_params = {
144                 .name = "TABLE",
145                 .key_size = key_size,
146                 .key_offset = APP_METADATA_OFFSET(32),
147                 .key_mask = NULL,
148                 .n_keys = 1 << 24,
149                 .n_buckets = 1 << 22,
150                 .f_hash = test_hash,
151                 .seed = 0,
152         };
153
154         /* Table configuration */
155         switch (app.pipeline_type) {
156         case e_APP_PIPELINE_HASH_KEY8_EXT:
157         case e_APP_PIPELINE_HASH_KEY16_EXT:
158         case e_APP_PIPELINE_HASH_KEY32_EXT:
159         {
160                 struct rte_pipeline_table_params table_params = {
161                         .ops = &rte_table_hash_ext_ops,
162                         .arg_create = &table_hash_params,
163                         .f_action_hit = NULL,
164                         .f_action_miss = NULL,
165                         .arg_ah = NULL,
166                         .action_data_size = 0,
167                 };
168
169                 if (rte_pipeline_table_create(p, &table_params, &table_id))
170                         rte_panic("Unable to configure the hash table\n");
171         }
172         break;
173
174         case e_APP_PIPELINE_HASH_KEY8_LRU:
175         case e_APP_PIPELINE_HASH_KEY16_LRU:
176         case e_APP_PIPELINE_HASH_KEY32_LRU:
177         {
178                 struct rte_pipeline_table_params table_params = {
179                         .ops = &rte_table_hash_lru_ops,
180                         .arg_create = &table_hash_params,
181                         .f_action_hit = NULL,
182                         .f_action_miss = NULL,
183                         .arg_ah = NULL,
184                         .action_data_size = 0,
185                 };
186
187                 if (rte_pipeline_table_create(p, &table_params, &table_id))
188                         rte_panic("Unable to configure the hash table\n");
189         }
190         break;
191
192         case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT:
193         {
194                 struct rte_pipeline_table_params table_params = {
195                         .ops = &rte_table_hash_key8_ext_ops,
196                         .arg_create = &table_hash_params,
197                         .f_action_hit = NULL,
198                         .f_action_miss = NULL,
199                         .arg_ah = NULL,
200                         .action_data_size = 0,
201                 };
202
203                 if (rte_pipeline_table_create(p, &table_params, &table_id))
204                         rte_panic("Unable to configure the hash table\n");
205         }
206         break;
207
208         case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU:
209         {
210                 struct rte_pipeline_table_params table_params = {
211                         .ops = &rte_table_hash_key8_lru_ops,
212                         .arg_create = &table_hash_params,
213                         .f_action_hit = NULL,
214                         .f_action_miss = NULL,
215                         .arg_ah = NULL,
216                         .action_data_size = 0,
217                 };
218
219                 if (rte_pipeline_table_create(p, &table_params, &table_id))
220                         rte_panic("Unable to configure the hash table\n");
221         }
222         break;
223
224         case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT:
225         {
226                 struct rte_pipeline_table_params table_params = {
227                         .ops = &rte_table_hash_key16_ext_ops,
228                         .arg_create = &table_hash_params,
229                         .f_action_hit = NULL,
230                         .f_action_miss = NULL,
231                         .arg_ah = NULL,
232                         .action_data_size = 0,
233                 };
234
235                 if (rte_pipeline_table_create(p, &table_params, &table_id))
236                         rte_panic("Unable to configure the hash table)\n");
237         }
238         break;
239
240         case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU:
241         {
242                 struct rte_pipeline_table_params table_params = {
243                         .ops = &rte_table_hash_key16_lru_ops,
244                         .arg_create = &table_hash_params,
245                         .f_action_hit = NULL,
246                         .f_action_miss = NULL,
247                         .arg_ah = NULL,
248                         .action_data_size = 0,
249                 };
250
251                 if (rte_pipeline_table_create(p, &table_params, &table_id))
252                         rte_panic("Unable to configure the hash table\n");
253         }
254         break;
255
256         case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT:
257         {
258                 struct rte_pipeline_table_params table_params = {
259                         .ops = &rte_table_hash_key32_ext_ops,
260                         .arg_create = &table_hash_params,
261                         .f_action_hit = NULL,
262                         .f_action_miss = NULL,
263                         .arg_ah = NULL,
264                         .action_data_size = 0,
265                 };
266
267                 if (rte_pipeline_table_create(p, &table_params, &table_id))
268                         rte_panic("Unable to configure the hash table\n");
269         }
270         break;
271
272
273         case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU:
274         {
275                 struct rte_pipeline_table_params table_params = {
276                         .ops = &rte_table_hash_key32_lru_ops,
277                         .arg_create = &table_hash_params,
278                         .f_action_hit = NULL,
279                         .f_action_miss = NULL,
280                         .arg_ah = NULL,
281                         .action_data_size = 0,
282                 };
283
284                 if (rte_pipeline_table_create(p, &table_params, &table_id))
285                         rte_panic("Unable to configure the hash table\n");
286         }
287         break;
288
289         case e_APP_PIPELINE_HASH_CUCKOO_KEY8:
290         case e_APP_PIPELINE_HASH_CUCKOO_KEY16:
291         case e_APP_PIPELINE_HASH_CUCKOO_KEY32:
292         case e_APP_PIPELINE_HASH_CUCKOO_KEY48:
293         case e_APP_PIPELINE_HASH_CUCKOO_KEY64:
294         case e_APP_PIPELINE_HASH_CUCKOO_KEY80:
295         case e_APP_PIPELINE_HASH_CUCKOO_KEY96:
296         case e_APP_PIPELINE_HASH_CUCKOO_KEY112:
297         case e_APP_PIPELINE_HASH_CUCKOO_KEY128:
298         {
299                 struct rte_pipeline_table_params table_params = {
300                         .ops = &rte_table_hash_cuckoo_ops,
301                         .arg_create = &table_hash_params,
302                         .f_action_hit = NULL,
303                         .f_action_miss = NULL,
304                         .arg_ah = NULL,
305                         .action_data_size = 0,
306                 };
307
308                 if (rte_pipeline_table_create(p, &table_params, &table_id))
309                         rte_panic("Unable to configure the hash table\n");
310         }
311         break;
312
313         default:
314                 rte_panic("Invalid hash table type or key size\n");
315         }
316
317         /* Interconnecting ports and tables */
318         for (i = 0; i < app.n_ports; i++)
319                 if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
320                         table_id))
321                         rte_panic("Unable to connect input port %u to "
322                                 "table %u\n", port_in_id[i],  table_id);
323
324         /* Add entries to tables */
325         for (i = 0; i < (1 << 24); i++) {
326                 struct rte_pipeline_table_entry entry = {
327                         .action = RTE_PIPELINE_ACTION_PORT,
328                         {.port_id = port_out_id[i & (app.n_ports - 1)]},
329                 };
330                 struct rte_pipeline_table_entry *entry_ptr;
331                 uint8_t key[32];
332                 uint32_t *k32 = (uint32_t *) key;
333                 int key_found, status;
334
335                 memset(key, 0, sizeof(key));
336                 k32[0] = rte_be_to_cpu_32(i);
337
338                 status = rte_pipeline_table_entry_add(p, table_id, key, &entry,
339                         &key_found, &entry_ptr);
340                 if (status < 0)
341                         rte_panic("Unable to add entry to table %u (%d)\n",
342                                 table_id, status);
343         }
344
345         /* Enable input ports */
346         for (i = 0; i < app.n_ports; i++)
347                 if (rte_pipeline_port_in_enable(p, port_in_id[i]))
348                         rte_panic("Unable to enable input port %u\n",
349                                 port_in_id[i]);
350
351         /* Check pipeline consistency */
352         if (rte_pipeline_check(p) < 0)
353                 rte_panic("Pipeline consistency check failed\n");
354
355         /* Run-time */
356 #if APP_FLUSH == 0
357         for ( ; ; )
358                 rte_pipeline_run(p);
359 #else
360         for (i = 0; ; i++) {
361                 rte_pipeline_run(p);
362
363                 if ((i & APP_FLUSH) == 0)
364                         rte_pipeline_flush(p);
365         }
366 #endif
367 }
368
369 uint64_t test_hash(
370         void *key,
371         __attribute__((unused)) void *key_mask,
372         __attribute__((unused)) uint32_t key_size,
373         __attribute__((unused)) uint64_t seed)
374 {
375         uint32_t *k32 = key;
376         uint32_t ip_dst = rte_be_to_cpu_32(k32[0]);
377         uint64_t signature = (ip_dst >> 2) | ((ip_dst & 0x3) << 30);
378
379         return signature;
380 }
381
382 void
383 app_main_loop_rx_metadata(void) {
384         uint32_t i, j;
385         int ret;
386
387         RTE_LOG(INFO, USER1, "Core %u is doing RX (with meta-data)\n",
388                 rte_lcore_id());
389
390         for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
391                 uint16_t n_mbufs;
392
393                 n_mbufs = rte_eth_rx_burst(
394                         app.ports[i],
395                         0,
396                         app.mbuf_rx.array,
397                         app.burst_size_rx_read);
398
399                 if (n_mbufs == 0)
400                         continue;
401
402                 for (j = 0; j < n_mbufs; j++) {
403                         struct rte_mbuf *m;
404                         uint8_t *m_data, *key;
405                         struct ipv4_hdr *ip_hdr;
406                         struct ipv6_hdr *ipv6_hdr;
407                         uint32_t ip_dst;
408                         uint8_t *ipv6_dst;
409                         uint32_t *signature, *k32;
410
411                         m = app.mbuf_rx.array[j];
412                         m_data = rte_pktmbuf_mtod(m, uint8_t *);
413                         signature = RTE_MBUF_METADATA_UINT32_PTR(m,
414                                         APP_METADATA_OFFSET(0));
415                         key = RTE_MBUF_METADATA_UINT8_PTR(m,
416                                         APP_METADATA_OFFSET(32));
417
418                         if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
419                                 ip_hdr = (struct ipv4_hdr *)
420                                         &m_data[sizeof(struct ether_hdr)];
421                                 ip_dst = ip_hdr->dst_addr;
422
423                                 k32 = (uint32_t *) key;
424                                 k32[0] = ip_dst & 0xFFFFFF00;
425                         } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
426                                 ipv6_hdr = (struct ipv6_hdr *)
427                                         &m_data[sizeof(struct ether_hdr)];
428                                 ipv6_dst = ipv6_hdr->dst_addr;
429
430                                 memcpy(key, ipv6_dst, 16);
431                         } else
432                                 continue;
433
434                         *signature = test_hash(key, NULL, 0, 0);
435                 }
436
437                 do {
438                         ret = rte_ring_sp_enqueue_bulk(
439                                 app.rings_rx[i],
440                                 (void **) app.mbuf_rx.array,
441                                 n_mbufs,
442                                 NULL);
443                 } while (ret == 0);
444         }
445 }