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