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 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 .f_action_bulk = NULL, 144 .arg_ah = NULL, 145 }; 146 147 if (rte_pipeline_port_out_create(p, &port_params, 148 &port_out_id[i])) 149 rte_panic("Unable to configure output port for " 150 "ring %d\n", i); 151 } 152 153 /* Table configuration */ 154 switch (app.pipeline_type) { 155 case e_APP_PIPELINE_HASH_KEY8_EXT: 156 case e_APP_PIPELINE_HASH_KEY16_EXT: 157 case e_APP_PIPELINE_HASH_KEY32_EXT: 158 { 159 struct rte_table_hash_ext_params table_hash_params = { 160 .key_size = key_size, 161 .n_keys = 1 << 24, 162 .n_buckets = 1 << 22, 163 .n_buckets_ext = 1 << 21, 164 .f_hash = test_hash, 165 .seed = 0, 166 .signature_offset = 0, 167 .key_offset = 32, 168 }; 169 170 struct rte_pipeline_table_params table_params = { 171 .ops = &rte_table_hash_ext_ops, 172 .arg_create = &table_hash_params, 173 .f_action_hit = NULL, 174 .f_action_miss = NULL, 175 .arg_ah = NULL, 176 .action_data_size = 0, 177 }; 178 179 if (rte_pipeline_table_create(p, &table_params, &table_id)) 180 rte_panic("Unable to configure the hash table\n"); 181 } 182 break; 183 184 case e_APP_PIPELINE_HASH_KEY8_LRU: 185 case e_APP_PIPELINE_HASH_KEY16_LRU: 186 case e_APP_PIPELINE_HASH_KEY32_LRU: 187 { 188 struct rte_table_hash_lru_params table_hash_params = { 189 .key_size = key_size, 190 .n_keys = 1 << 24, 191 .n_buckets = 1 << 22, 192 .f_hash = test_hash, 193 .seed = 0, 194 .signature_offset = 0, 195 .key_offset = 32, 196 }; 197 198 struct rte_pipeline_table_params table_params = { 199 .ops = &rte_table_hash_lru_ops, 200 .arg_create = &table_hash_params, 201 .f_action_hit = NULL, 202 .f_action_miss = NULL, 203 .arg_ah = NULL, 204 .action_data_size = 0, 205 }; 206 207 if (rte_pipeline_table_create(p, &table_params, &table_id)) 208 rte_panic("Unable to configure the hash table\n"); 209 } 210 break; 211 212 case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT: 213 { 214 struct rte_table_hash_key8_ext_params table_hash_params = { 215 .n_entries = 1 << 24, 216 .n_entries_ext = 1 << 23, 217 .signature_offset = 0, 218 .key_offset = 32, 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 = 0, 242 .key_offset = 32, 243 .f_hash = test_hash, 244 .seed = 0, 245 }; 246 247 struct rte_pipeline_table_params table_params = { 248 .ops = &rte_table_hash_key8_lru_ops, 249 .arg_create = &table_hash_params, 250 .f_action_hit = NULL, 251 .f_action_miss = NULL, 252 .arg_ah = NULL, 253 .action_data_size = 0, 254 }; 255 256 if (rte_pipeline_table_create(p, &table_params, &table_id)) 257 rte_panic("Unable to configure the hash table\n"); 258 } 259 break; 260 261 case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT: 262 { 263 struct rte_table_hash_key16_ext_params table_hash_params = { 264 .n_entries = 1 << 24, 265 .n_entries_ext = 1 << 23, 266 .signature_offset = 0, 267 .key_offset = 32, 268 .f_hash = test_hash, 269 .seed = 0, 270 }; 271 272 struct rte_pipeline_table_params table_params = { 273 .ops = &rte_table_hash_key16_ext_ops, 274 .arg_create = &table_hash_params, 275 .f_action_hit = NULL, 276 .f_action_miss = NULL, 277 .arg_ah = NULL, 278 .action_data_size = 0, 279 }; 280 281 if (rte_pipeline_table_create(p, &table_params, &table_id)) 282 rte_panic("Unable to configure the hash table)\n"); 283 } 284 break; 285 286 case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU: 287 { 288 struct rte_table_hash_key16_lru_params table_hash_params = { 289 .n_entries = 1 << 24, 290 .signature_offset = 0, 291 .key_offset = 32, 292 .f_hash = test_hash, 293 .seed = 0, 294 }; 295 296 struct rte_pipeline_table_params table_params = { 297 .ops = &rte_table_hash_key16_lru_ops, 298 .arg_create = &table_hash_params, 299 .f_action_hit = NULL, 300 .f_action_miss = NULL, 301 .arg_ah = NULL, 302 .action_data_size = 0, 303 }; 304 305 if (rte_pipeline_table_create(p, &table_params, &table_id)) 306 rte_panic("Unable to configure the hash table\n"); 307 } 308 break; 309 310 case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT: 311 { 312 struct rte_table_hash_key32_ext_params table_hash_params = { 313 .n_entries = 1 << 24, 314 .n_entries_ext = 1 << 23, 315 .signature_offset = 0, 316 .key_offset = 32, 317 .f_hash = test_hash, 318 .seed = 0, 319 }; 320 321 struct rte_pipeline_table_params table_params = { 322 .ops = &rte_table_hash_key32_ext_ops, 323 .arg_create = &table_hash_params, 324 .f_action_hit = NULL, 325 .f_action_miss = NULL, 326 .arg_ah = NULL, 327 .action_data_size = 0, 328 }; 329 330 if (rte_pipeline_table_create(p, &table_params, &table_id)) 331 rte_panic("Unable to configure the hash table\n"); 332 } 333 break; 334 335 336 case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU: 337 { 338 struct rte_table_hash_key32_lru_params table_hash_params = { 339 .n_entries = 1 << 24, 340 .signature_offset = 0, 341 .key_offset = 32, 342 .f_hash = test_hash, 343 .seed = 0, 344 }; 345 346 struct rte_pipeline_table_params table_params = { 347 .ops = &rte_table_hash_key32_lru_ops, 348 .arg_create = &table_hash_params, 349 .f_action_hit = NULL, 350 .f_action_miss = NULL, 351 .arg_ah = NULL, 352 .action_data_size = 0, 353 }; 354 355 if (rte_pipeline_table_create(p, &table_params, &table_id)) 356 rte_panic("Unable to configure the hash table\n"); 357 } 358 break; 359 360 default: 361 rte_panic("Invalid hash table type or key size\n"); 362 } 363 364 /* Interconnecting ports and tables */ 365 for (i = 0; i < app.n_ports; i++) 366 if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], 367 table_id)) 368 rte_panic("Unable to connect input port %u to " 369 "table %u\n", port_in_id[i], table_id); 370 371 /* Add entries to tables */ 372 for (i = 0; i < (1 << 24); i++) { 373 struct rte_pipeline_table_entry entry = { 374 .action = RTE_PIPELINE_ACTION_PORT, 375 {.port_id = port_out_id[i & (app.n_ports - 1)]}, 376 }; 377 struct rte_pipeline_table_entry *entry_ptr; 378 uint8_t key[32]; 379 uint32_t *k32 = (uint32_t *) key; 380 int key_found, status; 381 382 memset(key, 0, sizeof(key)); 383 k32[0] = rte_be_to_cpu_32(i); 384 385 status = rte_pipeline_table_entry_add(p, table_id, key, &entry, 386 &key_found, &entry_ptr); 387 if (status < 0) 388 rte_panic("Unable to add entry to table %u (%d)\n", 389 table_id, status); 390 } 391 392 /* Enable input ports */ 393 for (i = 0; i < app.n_ports; i++) 394 if (rte_pipeline_port_in_enable(p, port_in_id[i])) 395 rte_panic("Unable to enable input port %u\n", 396 port_in_id[i]); 397 398 /* Check pipeline consistency */ 399 if (rte_pipeline_check(p) < 0) 400 rte_panic("Pipeline consistency check failed\n"); 401 402 /* Run-time */ 403 #if APP_FLUSH == 0 404 for ( ; ; ) 405 rte_pipeline_run(p); 406 #else 407 for (i = 0; ; i++) { 408 rte_pipeline_run(p); 409 410 if ((i & APP_FLUSH) == 0) 411 rte_pipeline_flush(p); 412 } 413 #endif 414 } 415 416 uint64_t test_hash( 417 void *key, 418 __attribute__((unused)) uint32_t key_size, 419 __attribute__((unused)) uint64_t seed) 420 { 421 uint32_t *k32 = (uint32_t *) key; 422 uint32_t ip_dst = rte_be_to_cpu_32(k32[0]); 423 uint64_t signature = (ip_dst >> 2) | ((ip_dst & 0x3) << 30); 424 425 return signature; 426 } 427 428 void 429 app_main_loop_rx_metadata(void) { 430 uint32_t i, j; 431 int ret; 432 433 RTE_LOG(INFO, USER1, "Core %u is doing RX (with meta-data)\n", 434 rte_lcore_id()); 435 436 for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { 437 uint16_t n_mbufs; 438 439 n_mbufs = rte_eth_rx_burst( 440 app.ports[i], 441 0, 442 app.mbuf_rx.array, 443 app.burst_size_rx_read); 444 445 if (n_mbufs == 0) 446 continue; 447 448 for (j = 0; j < n_mbufs; j++) { 449 struct rte_mbuf *m; 450 uint8_t *m_data, *key; 451 struct ipv4_hdr *ip_hdr; 452 struct ipv6_hdr *ipv6_hdr; 453 uint32_t ip_dst; 454 uint8_t *ipv6_dst; 455 uint32_t *signature, *k32; 456 457 m = app.mbuf_rx.array[j]; 458 m_data = rte_pktmbuf_mtod(m, uint8_t *); 459 signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0); 460 key = RTE_MBUF_METADATA_UINT8_PTR(m, 32); 461 462 if (m->ol_flags & PKT_RX_IPV4_HDR) { 463 ip_hdr = (struct ipv4_hdr *) 464 &m_data[sizeof(struct ether_hdr)]; 465 ip_dst = ip_hdr->dst_addr; 466 467 k32 = (uint32_t *) key; 468 k32[0] = ip_dst & 0xFFFFFF00; 469 } else { 470 ipv6_hdr = (struct ipv6_hdr *) 471 &m_data[sizeof(struct ether_hdr)]; 472 ipv6_dst = ipv6_hdr->dst_addr; 473 474 memcpy(key, ipv6_dst, 16); 475 } 476 477 *signature = test_hash(key, 0, 0); 478 } 479 480 do { 481 ret = rte_ring_sp_enqueue_bulk( 482 app.rings_rx[i], 483 (void **) app.mbuf_rx.array, 484 n_mbufs); 485 } while (ret < 0); 486 } 487 } 488