1 /* 2 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 #include <assert.h> 27 28 #include <rte_common.h> 29 #include <rte_byteorder.h> 30 #include <rte_log.h> 31 #include <rte_memory.h> 32 #include <rte_memcpy.h> 33 #include <rte_memzone.h> 34 #include <rte_config.h> 35 #include <rte_eal.h> 36 #include <rte_pci.h> 37 #include <rte_mbuf.h> 38 #include <rte_memory.h> 39 #include <rte_lcore.h> 40 #include <rte_launch.h> 41 #include <rte_ethdev.h> 42 #include <rte_debug.h> 43 #include <rte_common.h> 44 #include <rte_ether.h> 45 #include <rte_malloc.h> 46 #include <rte_cycles.h> 47 #include <rte_timer.h> 48 #include <rte_thash.h> 49 #include <rte_ip.h> 50 #include <rte_tcp.h> 51 #include <rte_udp.h> 52 53 #include "ff_dpdk_if.h" 54 #include "ff_dpdk_pcap.h" 55 #include "ff_dpdk_kni.h" 56 #include "ff_config.h" 57 #include "ff_veth.h" 58 #include "ff_host_interface.h" 59 #include "ff_msg.h" 60 #include "ff_api.h" 61 62 #define MEMPOOL_CACHE_SIZE 256 63 64 #define DISPATCH_RING_SIZE 2048 65 66 #define MSG_RING_SIZE 32 67 68 /* 69 * Configurable number of RX/TX ring descriptors 70 */ 71 #define RX_QUEUE_SIZE 512 72 #define TX_QUEUE_SIZE 512 73 74 #define MAX_PKT_BURST 32 75 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 76 77 /* 78 * Try to avoid TX buffering if we have at least MAX_TX_BURST packets to send. 79 */ 80 #define MAX_TX_BURST (MAX_PKT_BURST / 2) 81 82 #define NB_SOCKETS 8 83 84 /* Configure how many packets ahead to prefetch, when reading packets */ 85 #define PREFETCH_OFFSET 3 86 87 #define MAX_RX_QUEUE_PER_LCORE 16 88 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS 89 #define MAX_RX_QUEUE_PER_PORT 128 90 91 #define KNI_MBUF_MAX 2048 92 #define KNI_QUEUE_SIZE 2048 93 94 static int enable_kni; 95 static int kni_accept; 96 97 static int numa_on; 98 99 static struct rte_timer freebsd_clock; 100 101 // Mellanox Linux's driver key 102 static uint8_t default_rsskey_40bytes[40] = { 103 0xd1, 0x81, 0xc6, 0x2c, 0xf7, 0xf4, 0xdb, 0x5b, 104 0x19, 0x83, 0xa2, 0xfc, 0x94, 0x3e, 0x1a, 0xdb, 105 0xd9, 0x38, 0x9e, 0x6b, 0xd1, 0x03, 0x9c, 0x2c, 106 0xa7, 0x44, 0x99, 0xad, 0x59, 0x3d, 0x56, 0xd9, 107 0xf3, 0x25, 0x3c, 0x06, 0x2a, 0xdc, 0x1f, 0xfc 108 }; 109 110 static struct rte_eth_conf default_port_conf = { 111 .rxmode = { 112 .mq_mode = ETH_MQ_RX_RSS, 113 .max_rx_pkt_len = ETHER_MAX_LEN, 114 .split_hdr_size = 0, /**< hdr buf size */ 115 .header_split = 0, /**< Header Split disabled */ 116 .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 117 .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 118 .hw_vlan_strip = 0, /**< VLAN strip disabled. */ 119 .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ 120 .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 121 .hw_strip_crc = 0, /**< CRC stripped by hardware */ 122 .enable_lro = 0, /**< LRO disabled */ 123 }, 124 .rx_adv_conf = { 125 .rss_conf = { 126 .rss_key = default_rsskey_40bytes, 127 .rss_key_len = 40, 128 .rss_hf = ETH_RSS_PROTO_MASK, 129 }, 130 }, 131 .txmode = { 132 .mq_mode = ETH_MQ_TX_NONE, 133 }, 134 }; 135 136 struct mbuf_table { 137 uint16_t len; 138 struct rte_mbuf *m_table[MAX_PKT_BURST]; 139 }; 140 141 struct lcore_rx_queue { 142 uint16_t port_id; 143 uint16_t queue_id; 144 } __rte_cache_aligned; 145 146 struct lcore_conf { 147 uint16_t proc_id; 148 uint16_t socket_id; 149 uint16_t nb_queue_list[RTE_MAX_ETHPORTS]; 150 struct ff_port_cfg *port_cfgs; 151 152 uint16_t nb_rx_queue; 153 struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 154 uint16_t nb_tx_port; 155 uint16_t tx_port_id[RTE_MAX_ETHPORTS]; 156 uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 157 struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; 158 char *pcap[RTE_MAX_ETHPORTS]; 159 } __rte_cache_aligned; 160 161 static struct lcore_conf lcore_conf; 162 163 static struct rte_mempool *pktmbuf_pool[NB_SOCKETS]; 164 165 static struct rte_ring **dispatch_ring[RTE_MAX_ETHPORTS]; 166 static dispatch_func_t packet_dispatcher; 167 168 static uint16_t rss_reta_size[RTE_MAX_ETHPORTS]; 169 170 struct ff_msg_ring { 171 char ring_name[2][RTE_RING_NAMESIZE]; 172 /* ring[0] for lcore recv msg, other send */ 173 /* ring[1] for lcore send msg, other read */ 174 struct rte_ring *ring[2]; 175 } __rte_cache_aligned; 176 177 static struct ff_msg_ring msg_ring[RTE_MAX_LCORE]; 178 static struct rte_mempool *message_pool; 179 180 struct ff_dpdk_if_context { 181 void *sc; 182 void *ifp; 183 uint16_t port_id; 184 struct ff_hw_features hw_features; 185 } __rte_cache_aligned; 186 187 static struct ff_dpdk_if_context *veth_ctx[RTE_MAX_ETHPORTS]; 188 189 extern void ff_hardclock(void); 190 191 static void 192 ff_hardclock_job(__rte_unused struct rte_timer *timer, 193 __rte_unused void *arg) { 194 ff_hardclock(); 195 ff_update_current_ts(); 196 } 197 198 struct ff_dpdk_if_context * 199 ff_dpdk_register_if(void *sc, void *ifp, struct ff_port_cfg *cfg) 200 { 201 struct ff_dpdk_if_context *ctx; 202 203 ctx = calloc(1, sizeof(struct ff_dpdk_if_context)); 204 if (ctx == NULL) 205 return NULL; 206 207 ctx->sc = sc; 208 ctx->ifp = ifp; 209 ctx->port_id = cfg->port_id; 210 ctx->hw_features = cfg->hw_features; 211 212 return ctx; 213 } 214 215 void 216 ff_dpdk_deregister_if(struct ff_dpdk_if_context *ctx) 217 { 218 free(ctx); 219 } 220 221 static void 222 check_all_ports_link_status(void) 223 { 224 #define CHECK_INTERVAL 100 /* 100ms */ 225 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 226 227 uint16_t portid; 228 uint8_t count, all_ports_up, print_flag = 0; 229 struct rte_eth_link link; 230 231 printf("\nChecking link status"); 232 fflush(stdout); 233 234 int i, nb_ports; 235 nb_ports = ff_global_cfg.dpdk.nb_ports; 236 for (count = 0; count <= MAX_CHECK_TIME; count++) { 237 all_ports_up = 1; 238 for (i = 0; i < nb_ports; i++) { 239 uint16_t portid = ff_global_cfg.dpdk.portid_list[i]; 240 memset(&link, 0, sizeof(link)); 241 rte_eth_link_get_nowait(portid, &link); 242 243 /* print link status if flag set */ 244 if (print_flag == 1) { 245 if (link.link_status) { 246 printf("Port %d Link Up - speed %u " 247 "Mbps - %s\n", (int)portid, 248 (unsigned)link.link_speed, 249 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 250 ("full-duplex") : ("half-duplex\n")); 251 } else { 252 printf("Port %d Link Down\n", (int)portid); 253 } 254 continue; 255 } 256 /* clear all_ports_up flag if any link down */ 257 if (link.link_status == 0) { 258 all_ports_up = 0; 259 break; 260 } 261 } 262 263 /* after finally printing all link status, get out */ 264 if (print_flag == 1) 265 break; 266 267 if (all_ports_up == 0) { 268 printf("."); 269 fflush(stdout); 270 rte_delay_ms(CHECK_INTERVAL); 271 } 272 273 /* set the print_flag if all ports up or timeout */ 274 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 275 print_flag = 1; 276 printf("done\n"); 277 } 278 } 279 } 280 281 static int 282 init_lcore_conf(void) 283 { 284 uint8_t nb_dev_ports = rte_eth_dev_count(); 285 if (nb_dev_ports == 0) { 286 rte_exit(EXIT_FAILURE, "No probed ethernet devices\n"); 287 } 288 289 if (ff_global_cfg.dpdk.max_portid >= nb_dev_ports) { 290 rte_exit(EXIT_FAILURE, "this machine doesn't have port %d.\n", 291 ff_global_cfg.dpdk.max_portid); 292 } 293 294 lcore_conf.port_cfgs = ff_global_cfg.dpdk.port_cfgs; 295 lcore_conf.proc_id = ff_global_cfg.dpdk.proc_id; 296 297 uint16_t proc_id; 298 for (proc_id = 0; proc_id < ff_global_cfg.dpdk.nb_procs; proc_id++) { 299 uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[proc_id]; 300 if (!lcore_config[lcore_id].detected) { 301 rte_exit(EXIT_FAILURE, "lcore %u unavailable\n", lcore_id); 302 } 303 } 304 305 uint16_t socket_id = 0; 306 if (numa_on) { 307 socket_id = rte_lcore_to_socket_id(rte_lcore_id()); 308 } 309 310 lcore_conf.socket_id = socket_id; 311 312 uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[lcore_conf.proc_id]; 313 int j; 314 for (j = 0; j < ff_global_cfg.dpdk.nb_ports; ++j) { 315 uint16_t port_id = ff_global_cfg.dpdk.portid_list[j]; 316 struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id]; 317 318 int queueid = -1; 319 int i; 320 for (i = 0; i < pconf->nb_lcores; i++) { 321 if (pconf->lcore_list[i] == lcore_id) { 322 queueid = i; 323 } 324 } 325 if (queueid < 0) { 326 continue; 327 } 328 printf("lcore: %u, port: %u, queue: %u\n", lcore_id, port_id, queueid); 329 uint16_t nb_rx_queue = lcore_conf.nb_rx_queue; 330 lcore_conf.rx_queue_list[nb_rx_queue].port_id = port_id; 331 lcore_conf.rx_queue_list[nb_rx_queue].queue_id = queueid; 332 lcore_conf.nb_rx_queue++; 333 334 lcore_conf.tx_queue_id[port_id] = queueid; 335 lcore_conf.tx_port_id[lcore_conf.nb_tx_port] = port_id; 336 lcore_conf.nb_tx_port++; 337 338 lcore_conf.pcap[port_id] = pconf->pcap; 339 lcore_conf.nb_queue_list[port_id] = pconf->nb_lcores; 340 } 341 342 if (lcore_conf.nb_rx_queue == 0) { 343 rte_exit(EXIT_FAILURE, "lcore %u has nothing to do\n", lcore_id); 344 } 345 346 return 0; 347 } 348 349 static int 350 init_mem_pool(void) 351 { 352 uint8_t nb_ports = ff_global_cfg.dpdk.nb_ports; 353 uint32_t nb_lcores = ff_global_cfg.dpdk.nb_procs; 354 uint32_t nb_tx_queue = nb_lcores; 355 uint32_t nb_rx_queue = lcore_conf.nb_rx_queue * nb_lcores; 356 357 unsigned nb_mbuf = RTE_MAX ( 358 (nb_rx_queue*RX_QUEUE_SIZE + 359 nb_ports*nb_lcores*MAX_PKT_BURST + 360 nb_ports*nb_tx_queue*TX_QUEUE_SIZE + 361 nb_lcores*MEMPOOL_CACHE_SIZE + 362 nb_ports*KNI_MBUF_MAX + 363 nb_ports*KNI_QUEUE_SIZE + 364 nb_lcores*nb_ports*DISPATCH_RING_SIZE), 365 (unsigned)8192); 366 367 unsigned socketid = 0; 368 uint16_t i, lcore_id; 369 char s[64]; 370 371 for (i = 0; i < ff_global_cfg.dpdk.nb_procs; i++) { 372 lcore_id = ff_global_cfg.dpdk.proc_lcore[i]; 373 if (numa_on) { 374 socketid = rte_lcore_to_socket_id(lcore_id); 375 } 376 377 if (socketid >= NB_SOCKETS) { 378 rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", 379 socketid, i, NB_SOCKETS); 380 } 381 382 if (pktmbuf_pool[socketid] != NULL) { 383 continue; 384 } 385 386 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 387 snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 388 pktmbuf_pool[socketid] = 389 rte_pktmbuf_pool_create(s, nb_mbuf, 390 MEMPOOL_CACHE_SIZE, 0, 391 RTE_MBUF_DEFAULT_BUF_SIZE, socketid); 392 } else { 393 snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 394 pktmbuf_pool[socketid] = rte_mempool_lookup(s); 395 } 396 397 if (pktmbuf_pool[socketid] == NULL) { 398 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool on socket %d\n", socketid); 399 } else { 400 printf("create mbuf pool on socket %d\n", socketid); 401 } 402 } 403 404 return 0; 405 } 406 407 static struct rte_ring * 408 create_ring(const char *name, unsigned count, int socket_id, unsigned flags) 409 { 410 struct rte_ring *ring; 411 412 if (name == NULL) 413 return NULL; 414 415 /* If already create, just attached it */ 416 if (likely((ring = rte_ring_lookup(name)) != NULL)) 417 return ring; 418 419 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 420 return rte_ring_create(name, count, socket_id, flags); 421 } else { 422 return rte_ring_lookup(name); 423 } 424 } 425 426 static int 427 init_dispatch_ring(void) 428 { 429 int j; 430 char name_buf[RTE_RING_NAMESIZE]; 431 int queueid; 432 433 unsigned socketid = lcore_conf.socket_id; 434 435 /* Create ring according to ports actually being used. */ 436 int nb_ports = ff_global_cfg.dpdk.nb_ports; 437 for (j = 0; j < nb_ports; j++) { 438 uint16_t portid = ff_global_cfg.dpdk.portid_list[j]; 439 struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[portid]; 440 int nb_queues = pconf->nb_lcores; 441 if (dispatch_ring[portid] == NULL) { 442 snprintf(name_buf, RTE_RING_NAMESIZE, "ring_ptr_p%d", portid); 443 444 dispatch_ring[portid] = rte_zmalloc(name_buf, 445 sizeof(struct rte_ring *) * nb_queues, 446 RTE_CACHE_LINE_SIZE); 447 if (dispatch_ring[portid] == NULL) { 448 rte_exit(EXIT_FAILURE, "rte_zmalloc(%s (struct rte_ring*)) " 449 "failed\n", name_buf); 450 } 451 } 452 453 for(queueid = 0; queueid < nb_queues; ++queueid) { 454 snprintf(name_buf, RTE_RING_NAMESIZE, "dispatch_ring_p%d_q%d", 455 portid, queueid); 456 dispatch_ring[portid][queueid] = create_ring(name_buf, 457 DISPATCH_RING_SIZE, socketid, RING_F_SC_DEQ); 458 459 if (dispatch_ring[portid][queueid] == NULL) 460 rte_panic("create ring:%s failed!\n", name_buf); 461 462 printf("create ring:%s success, %u ring entries are now free!\n", 463 name_buf, rte_ring_free_count(dispatch_ring[portid][queueid])); 464 } 465 } 466 467 return 0; 468 } 469 470 static void 471 ff_msg_init(struct rte_mempool *mp, 472 __attribute__((unused)) void *opaque_arg, 473 void *obj, __attribute__((unused)) unsigned i) 474 { 475 struct ff_msg *msg = (struct ff_msg *)obj; 476 msg->msg_type = FF_UNKNOWN; 477 msg->buf_addr = (char *)msg + sizeof(struct ff_msg); 478 msg->buf_len = mp->elt_size - sizeof(struct ff_msg); 479 } 480 481 static int 482 init_msg_ring(void) 483 { 484 uint16_t i; 485 uint16_t nb_procs = ff_global_cfg.dpdk.nb_procs; 486 unsigned socketid = lcore_conf.socket_id; 487 488 /* Create message buffer pool */ 489 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 490 message_pool = rte_mempool_create(FF_MSG_POOL, 491 MSG_RING_SIZE * 2 * nb_procs, 492 MAX_MSG_BUF_SIZE, MSG_RING_SIZE / 2, 0, 493 NULL, NULL, ff_msg_init, NULL, 494 socketid, 0); 495 } else { 496 message_pool = rte_mempool_lookup(FF_MSG_POOL); 497 } 498 499 if (message_pool == NULL) { 500 rte_panic("Create msg mempool failed\n"); 501 } 502 503 for(i = 0; i < nb_procs; ++i) { 504 snprintf(msg_ring[i].ring_name[0], RTE_RING_NAMESIZE, 505 "%s%u", FF_MSG_RING_IN, i); 506 snprintf(msg_ring[i].ring_name[1], RTE_RING_NAMESIZE, 507 "%s%u", FF_MSG_RING_OUT, i); 508 509 msg_ring[i].ring[0] = create_ring(msg_ring[i].ring_name[0], 510 MSG_RING_SIZE, socketid, RING_F_SP_ENQ | RING_F_SC_DEQ); 511 if (msg_ring[i].ring[0] == NULL) 512 rte_panic("create ring::%s failed!\n", msg_ring[i].ring_name[0]); 513 514 msg_ring[i].ring[1] = create_ring(msg_ring[i].ring_name[1], 515 MSG_RING_SIZE, socketid, RING_F_SP_ENQ | RING_F_SC_DEQ); 516 if (msg_ring[i].ring[1] == NULL) 517 rte_panic("create ring::%s failed!\n", msg_ring[i].ring_name[0]); 518 } 519 520 return 0; 521 } 522 523 static int 524 init_kni(void) 525 { 526 int nb_ports = rte_eth_dev_count(); 527 kni_accept = 0; 528 if(strcasecmp(ff_global_cfg.kni.method, "accept") == 0) 529 kni_accept = 1; 530 531 ff_kni_init(nb_ports, ff_global_cfg.kni.tcp_port, 532 ff_global_cfg.kni.udp_port); 533 534 unsigned socket_id = lcore_conf.socket_id; 535 struct rte_mempool *mbuf_pool = pktmbuf_pool[socket_id]; 536 537 nb_ports = ff_global_cfg.dpdk.nb_ports; 538 int i, ret; 539 for (i = 0; i < nb_ports; i++) { 540 uint16_t port_id = ff_global_cfg.dpdk.portid_list[i]; 541 ff_kni_alloc(port_id, socket_id, mbuf_pool, KNI_QUEUE_SIZE); 542 } 543 544 return 0; 545 } 546 547 static void 548 set_rss_table(uint16_t port_id, uint16_t reta_size, uint16_t nb_queues) 549 { 550 if (reta_size == 0) { 551 return; 552 } 553 554 int reta_conf_size = RTE_MAX(1, reta_size / RTE_RETA_GROUP_SIZE); 555 struct rte_eth_rss_reta_entry64 reta_conf[reta_conf_size]; 556 557 /* config HW indirection table */ 558 unsigned i, j, hash=0; 559 for (i = 0; i < reta_conf_size; i++) { 560 reta_conf[i].mask = ~0ULL; 561 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) { 562 reta_conf[i].reta[j] = hash++ % nb_queues; 563 } 564 } 565 566 if (rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size)) { 567 rte_exit(EXIT_FAILURE, "port[%d], failed to update rss table\n", 568 port_id); 569 } 570 } 571 572 static int 573 init_port_start(void) 574 { 575 int nb_ports = ff_global_cfg.dpdk.nb_ports; 576 unsigned socketid = rte_lcore_to_socket_id(rte_lcore_id()); 577 struct rte_mempool *mbuf_pool = pktmbuf_pool[socketid]; 578 uint16_t i; 579 580 for (i = 0; i < nb_ports; i++) { 581 uint16_t port_id = ff_global_cfg.dpdk.portid_list[i]; 582 struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id]; 583 uint16_t nb_queues = pconf->nb_lcores; 584 585 struct rte_eth_dev_info dev_info; 586 rte_eth_dev_info_get(port_id, &dev_info); 587 588 if (nb_queues > dev_info.max_rx_queues) { 589 rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_rx_queues[%d]\n", 590 nb_queues, 591 dev_info.max_rx_queues); 592 } 593 594 if (nb_queues > dev_info.max_tx_queues) { 595 rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_tx_queues[%d]\n", 596 nb_queues, 597 dev_info.max_tx_queues); 598 } 599 600 struct ether_addr addr; 601 rte_eth_macaddr_get(port_id, &addr); 602 printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 603 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", 604 (unsigned)port_id, 605 addr.addr_bytes[0], addr.addr_bytes[1], 606 addr.addr_bytes[2], addr.addr_bytes[3], 607 addr.addr_bytes[4], addr.addr_bytes[5]); 608 609 rte_memcpy(pconf->mac, 610 addr.addr_bytes, ETHER_ADDR_LEN); 611 612 /* Clear txq_flags - we do not need multi-mempool and refcnt */ 613 dev_info.default_txconf.txq_flags = ETH_TXQ_FLAGS_NOMULTMEMP | 614 ETH_TXQ_FLAGS_NOREFCOUNT; 615 616 /* Disable features that are not supported by port's HW */ 617 if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) { 618 dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMUDP; 619 } 620 621 if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)) { 622 dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMTCP; 623 } 624 625 if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM)) { 626 dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMSCTP; 627 } 628 629 if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)) { 630 dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOVLANOFFL; 631 } 632 633 if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) && 634 !(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO)) { 635 dev_info.default_txconf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS; 636 } 637 638 struct rte_eth_conf port_conf = {0}; 639 640 /* Set RSS mode */ 641 port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; 642 port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_PROTO_MASK; 643 port_conf.rx_adv_conf.rss_conf.rss_key = default_rsskey_40bytes; 644 port_conf.rx_adv_conf.rss_conf.rss_key_len = 40; 645 646 /* Set Rx VLAN stripping */ 647 if (ff_global_cfg.dpdk.vlan_strip) { 648 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) { 649 port_conf.rxmode.hw_vlan_strip = 1; 650 } 651 } 652 653 /* Enable HW CRC stripping */ 654 port_conf.rxmode.hw_strip_crc = 1; 655 656 /* FIXME: Enable TCP LRO ?*/ 657 #if 0 658 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) { 659 printf("LRO is supported\n"); 660 port_conf.rxmode.enable_lro = 1; 661 pconf->hw_features.rx_lro = 1; 662 } 663 #endif 664 665 /* Set Rx checksum checking */ 666 if ((dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) && 667 (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) && 668 (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)) { 669 printf("RX checksum offload supported\n"); 670 port_conf.rxmode.hw_ip_checksum = 1; 671 pconf->hw_features.rx_csum = 1; 672 } 673 674 if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) { 675 printf("TX ip checksum offload supported\n"); 676 pconf->hw_features.tx_csum_ip = 1; 677 } 678 679 if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) && 680 (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)) { 681 printf("TX TCP&UDP checksum offload supported\n"); 682 pconf->hw_features.tx_csum_l4 = 1; 683 } 684 685 if (ff_global_cfg.dpdk.tso) { 686 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) { 687 printf("TSO is supported\n"); 688 pconf->hw_features.tx_tso = 1; 689 } 690 } else { 691 printf("TSO is disabled\n"); 692 } 693 694 if (dev_info.reta_size) { 695 /* reta size must be power of 2 */ 696 assert((dev_info.reta_size & (dev_info.reta_size - 1)) == 0); 697 698 rss_reta_size[port_id] = dev_info.reta_size; 699 printf("port[%d]: rss table size: %d\n", port_id, 700 dev_info.reta_size); 701 } 702 703 if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 704 continue; 705 } 706 707 int ret = rte_eth_dev_configure(port_id, nb_queues, nb_queues, &port_conf); 708 if (ret != 0) { 709 return ret; 710 } 711 uint16_t q; 712 for (q = 0; q < nb_queues; q++) { 713 ret = rte_eth_tx_queue_setup(port_id, q, TX_QUEUE_SIZE, 714 socketid, &dev_info.default_txconf); 715 if (ret < 0) { 716 return ret; 717 } 718 719 ret = rte_eth_rx_queue_setup(port_id, q, RX_QUEUE_SIZE, 720 socketid, &dev_info.default_rxconf, mbuf_pool); 721 if (ret < 0) { 722 return ret; 723 } 724 } 725 726 ret = rte_eth_dev_start(port_id); 727 if (ret < 0) { 728 return ret; 729 } 730 731 if (nb_queues > 1) { 732 /* set HW rss hash function to Toeplitz. */ 733 if (!rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_HASH)) { 734 struct rte_eth_hash_filter_info info = {0}; 735 info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG; 736 info.info.global_conf.hash_func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; 737 738 if (rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, 739 RTE_ETH_FILTER_SET, &info) < 0) { 740 rte_exit(EXIT_FAILURE, "port[%d] set hash func failed\n", 741 port_id); 742 } 743 } 744 745 set_rss_table(port_id, dev_info.reta_size, nb_queues); 746 } 747 748 /* Enable RX in promiscuous mode for the Ethernet device. */ 749 if (ff_global_cfg.dpdk.promiscuous) { 750 rte_eth_promiscuous_enable(port_id); 751 ret = rte_eth_promiscuous_get(port_id); 752 if (ret == 1) { 753 printf("set port %u to promiscuous mode ok\n", port_id); 754 } else { 755 printf("set port %u to promiscuous mode error\n", port_id); 756 } 757 } 758 759 /* Enable pcap dump */ 760 if (pconf->pcap) { 761 ff_enable_pcap(pconf->pcap); 762 } 763 } 764 765 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 766 check_all_ports_link_status(); 767 } 768 769 return 0; 770 } 771 772 static int 773 init_clock(void) 774 { 775 rte_timer_subsystem_init(); 776 uint64_t hz = rte_get_timer_hz(); 777 uint64_t intrs = MS_PER_S/ff_global_cfg.freebsd.hz; 778 uint64_t tsc = (hz + MS_PER_S - 1) / MS_PER_S*intrs; 779 780 rte_timer_init(&freebsd_clock); 781 rte_timer_reset(&freebsd_clock, tsc, PERIODICAL, 782 rte_lcore_id(), &ff_hardclock_job, NULL); 783 784 ff_update_current_ts(); 785 786 return 0; 787 } 788 789 int 790 ff_dpdk_init(int argc, char **argv) 791 { 792 if (ff_global_cfg.dpdk.nb_procs < 1 || 793 ff_global_cfg.dpdk.nb_procs > RTE_MAX_LCORE || 794 ff_global_cfg.dpdk.proc_id >= ff_global_cfg.dpdk.nb_procs || 795 ff_global_cfg.dpdk.proc_id < 0) { 796 printf("param num_procs[%d] or proc_id[%d] error!\n", 797 ff_global_cfg.dpdk.nb_procs, 798 ff_global_cfg.dpdk.proc_id); 799 exit(1); 800 } 801 802 int ret = rte_eal_init(argc, argv); 803 if (ret < 0) { 804 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); 805 } 806 807 numa_on = ff_global_cfg.dpdk.numa_on; 808 809 init_lcore_conf(); 810 811 init_mem_pool(); 812 813 init_dispatch_ring(); 814 815 init_msg_ring(); 816 817 enable_kni = ff_global_cfg.kni.enable; 818 if (enable_kni) { 819 init_kni(); 820 } 821 822 ret = init_port_start(); 823 if (ret < 0) { 824 rte_exit(EXIT_FAILURE, "init_port_start failed\n"); 825 } 826 827 init_clock(); 828 829 return 0; 830 } 831 832 static void 833 ff_veth_input(const struct ff_dpdk_if_context *ctx, struct rte_mbuf *pkt) 834 { 835 uint8_t rx_csum = ctx->hw_features.rx_csum; 836 if (rx_csum) { 837 if (pkt->ol_flags & (PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD)) { 838 rte_pktmbuf_free(pkt); 839 return; 840 } 841 } 842 843 /* 844 * FIXME: should we save pkt->vlan_tci 845 * if (pkt->ol_flags & PKT_RX_VLAN_PKT) 846 */ 847 848 void *data = rte_pktmbuf_mtod(pkt, void*); 849 uint16_t len = rte_pktmbuf_data_len(pkt); 850 851 void *hdr = ff_mbuf_gethdr(pkt, pkt->pkt_len, data, len, rx_csum); 852 if (hdr == NULL) { 853 rte_pktmbuf_free(pkt); 854 return; 855 } 856 857 struct rte_mbuf *pn = pkt->next; 858 void *prev = hdr; 859 while(pn != NULL) { 860 data = rte_pktmbuf_mtod(pn, void*); 861 len = rte_pktmbuf_data_len(pn); 862 863 void *mb = ff_mbuf_get(prev, data, len); 864 if (mb == NULL) { 865 ff_mbuf_free(hdr); 866 rte_pktmbuf_free(pkt); 867 return; 868 } 869 pn = pn->next; 870 prev = mb; 871 } 872 873 ff_veth_process_packet(ctx->ifp, hdr); 874 } 875 876 static enum FilterReturn 877 protocol_filter(const void *data, uint16_t len) 878 { 879 if(len < ETHER_HDR_LEN) 880 return FILTER_UNKNOWN; 881 882 const struct ether_hdr *hdr; 883 hdr = (const struct ether_hdr *)data; 884 885 if(ntohs(hdr->ether_type) == ETHER_TYPE_ARP) 886 return FILTER_ARP; 887 888 if (!enable_kni) { 889 return FILTER_UNKNOWN; 890 } 891 892 if(ntohs(hdr->ether_type) != ETHER_TYPE_IPv4) 893 return FILTER_UNKNOWN; 894 895 return ff_kni_proto_filter(data + ETHER_HDR_LEN, 896 len - ETHER_HDR_LEN); 897 } 898 899 static inline void 900 pktmbuf_deep_attach(struct rte_mbuf *mi, const struct rte_mbuf *m) 901 { 902 struct rte_mbuf *md; 903 void *src, *dst; 904 905 dst = rte_pktmbuf_mtod(mi, void *); 906 src = rte_pktmbuf_mtod(m, void *); 907 908 mi->data_len = m->data_len; 909 rte_memcpy(dst, src, m->data_len); 910 911 mi->port = m->port; 912 mi->vlan_tci = m->vlan_tci; 913 mi->vlan_tci_outer = m->vlan_tci_outer; 914 mi->tx_offload = m->tx_offload; 915 mi->hash = m->hash; 916 mi->ol_flags = m->ol_flags; 917 mi->packet_type = m->packet_type; 918 } 919 920 /* copied from rte_pktmbuf_clone */ 921 static inline struct rte_mbuf * 922 pktmbuf_deep_clone(const struct rte_mbuf *md, 923 struct rte_mempool *mp) 924 { 925 struct rte_mbuf *mc, *mi, **prev; 926 uint32_t pktlen; 927 uint8_t nseg; 928 929 if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL)) 930 return NULL; 931 932 mi = mc; 933 prev = &mi->next; 934 pktlen = md->pkt_len; 935 nseg = 0; 936 937 do { 938 nseg++; 939 pktmbuf_deep_attach(mi, md); 940 *prev = mi; 941 prev = &mi->next; 942 } while ((md = md->next) != NULL && 943 (mi = rte_pktmbuf_alloc(mp)) != NULL); 944 945 *prev = NULL; 946 mc->nb_segs = nseg; 947 mc->pkt_len = pktlen; 948 949 /* Allocation of new indirect segment failed */ 950 if (unlikely (mi == NULL)) { 951 rte_pktmbuf_free(mc); 952 return NULL; 953 } 954 955 __rte_mbuf_sanity_check(mc, 1); 956 return mc; 957 } 958 959 static inline void 960 process_packets(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **bufs, 961 uint16_t count, const struct ff_dpdk_if_context *ctx, int pkts_from_ring) 962 { 963 struct lcore_conf *qconf = &lcore_conf; 964 uint16_t nb_queues = qconf->nb_queue_list[port_id]; 965 966 uint16_t i; 967 for (i = 0; i < count; i++) { 968 struct rte_mbuf *rtem = bufs[i]; 969 970 if (unlikely(qconf->pcap[port_id] != NULL)) { 971 if (!pkts_from_ring) { 972 ff_dump_packets(qconf->pcap[port_id], rtem); 973 } 974 } 975 976 void *data = rte_pktmbuf_mtod(rtem, void*); 977 uint16_t len = rte_pktmbuf_data_len(rtem); 978 979 if (!pkts_from_ring && packet_dispatcher) { 980 int ret = (*packet_dispatcher)(data, len, queue_id, nb_queues); 981 if (ret < 0 || ret >= nb_queues) { 982 rte_pktmbuf_free(rtem); 983 continue; 984 } 985 986 if (ret != queue_id) { 987 ret = rte_ring_enqueue(dispatch_ring[port_id][ret], rtem); 988 if (ret < 0) 989 rte_pktmbuf_free(rtem); 990 991 continue; 992 } 993 } 994 995 enum FilterReturn filter = protocol_filter(data, len); 996 if (filter == FILTER_ARP) { 997 struct rte_mempool *mbuf_pool; 998 struct rte_mbuf *mbuf_clone; 999 if (!pkts_from_ring) { 1000 uint16_t j; 1001 for(j = 0; j < nb_queues; ++j) { 1002 if(j == queue_id) 1003 continue; 1004 1005 unsigned socket_id = 0; 1006 if (numa_on) { 1007 uint16_t lcore_id = qconf->port_cfgs[port_id].lcore_list[j]; 1008 socket_id = rte_lcore_to_socket_id(lcore_id); 1009 } 1010 mbuf_pool = pktmbuf_pool[socket_id]; 1011 mbuf_clone = pktmbuf_deep_clone(rtem, mbuf_pool); 1012 if(mbuf_clone) { 1013 int ret = rte_ring_enqueue(dispatch_ring[port_id][j], 1014 mbuf_clone); 1015 if (ret < 0) 1016 rte_pktmbuf_free(mbuf_clone); 1017 } 1018 } 1019 } 1020 1021 if (enable_kni && rte_eal_process_type() == RTE_PROC_PRIMARY) { 1022 mbuf_pool = pktmbuf_pool[qconf->socket_id]; 1023 mbuf_clone = pktmbuf_deep_clone(rtem, mbuf_pool); 1024 if(mbuf_clone) { 1025 ff_kni_enqueue(port_id, mbuf_clone); 1026 } 1027 } 1028 1029 ff_veth_input(ctx, rtem); 1030 } else if (enable_kni && 1031 ((filter == FILTER_KNI && kni_accept) || 1032 (filter == FILTER_UNKNOWN && !kni_accept)) ) { 1033 ff_kni_enqueue(port_id, rtem); 1034 } else { 1035 ff_veth_input(ctx, rtem); 1036 } 1037 } 1038 } 1039 1040 static inline int 1041 process_dispatch_ring(uint16_t port_id, uint16_t queue_id, 1042 struct rte_mbuf **pkts_burst, const struct ff_dpdk_if_context *ctx) 1043 { 1044 /* read packet from ring buf and to process */ 1045 uint16_t nb_rb; 1046 nb_rb = rte_ring_dequeue_burst(dispatch_ring[port_id][queue_id], 1047 (void **)pkts_burst, MAX_PKT_BURST, NULL); 1048 1049 if(nb_rb > 0) { 1050 process_packets(port_id, queue_id, pkts_burst, nb_rb, ctx, 1); 1051 } 1052 1053 return 0; 1054 } 1055 1056 static inline void 1057 handle_sysctl_msg(struct ff_msg *msg) 1058 { 1059 int ret = ff_sysctl(msg->sysctl.name, msg->sysctl.namelen, 1060 msg->sysctl.old, msg->sysctl.oldlenp, msg->sysctl.new, 1061 msg->sysctl.newlen); 1062 1063 if (ret < 0) { 1064 msg->result = errno; 1065 } else { 1066 msg->result = 0; 1067 } 1068 } 1069 1070 static inline void 1071 handle_ioctl_msg(struct ff_msg *msg) 1072 { 1073 int fd, ret; 1074 fd = ff_socket(AF_INET, SOCK_DGRAM, 0); 1075 if (fd < 0) { 1076 ret = -1; 1077 goto done; 1078 } 1079 1080 ret = ff_ioctl(fd, msg->ioctl.cmd, msg->ioctl.data); 1081 1082 ff_close(fd); 1083 1084 done: 1085 if (ret < 0) { 1086 msg->result = errno; 1087 } else { 1088 msg->result = 0; 1089 } 1090 } 1091 1092 static inline void 1093 handle_route_msg(struct ff_msg *msg) 1094 { 1095 int ret = ff_rtioctl(msg->route.fib, msg->route.data, 1096 &msg->route.len, msg->route.maxlen); 1097 if (ret < 0) { 1098 msg->result = errno; 1099 } else { 1100 msg->result = 0; 1101 } 1102 } 1103 1104 static struct ff_top_args ff_status; 1105 static inline void 1106 handle_top_msg(struct ff_msg *msg) 1107 { 1108 msg->top = ff_status; 1109 msg->result = 0; 1110 } 1111 1112 #ifdef FF_NETGRAPH 1113 static inline void 1114 handle_ngctl_msg(struct ff_msg *msg) 1115 { 1116 int ret = ff_ngctl(msg->ngctl.cmd, msg->ngctl.data); 1117 if (ret < 0) { 1118 msg->result = errno; 1119 } else { 1120 msg->result = 0; 1121 msg->ngctl.ret = ret; 1122 } 1123 } 1124 #endif 1125 1126 #ifdef FF_IPFW 1127 static inline void 1128 handle_ipfw_msg(struct ff_msg *msg) 1129 { 1130 int fd, ret; 1131 fd = ff_socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 1132 if (fd < 0) { 1133 ret = -1; 1134 goto done; 1135 } 1136 1137 switch (msg->ipfw.cmd) { 1138 case FF_IPFW_GET: 1139 ret = ff_getsockopt(fd, msg->ipfw.level, 1140 msg->ipfw.optname, msg->ipfw.optval, 1141 msg->ipfw.optlen); 1142 break; 1143 case FF_IPFW_SET: 1144 ret = ff_setsockopt(fd, msg->ipfw.level, 1145 msg->ipfw.optname, msg->ipfw.optval, 1146 *(msg->ipfw.optlen)); 1147 break; 1148 default: 1149 ret = -1; 1150 errno = ENOTSUP; 1151 break; 1152 } 1153 1154 ff_close(fd); 1155 1156 done: 1157 if (ret < 0) { 1158 msg->result = errno; 1159 } else { 1160 msg->result = 0; 1161 } 1162 } 1163 #endif 1164 1165 static inline void 1166 handle_default_msg(struct ff_msg *msg) 1167 { 1168 msg->result = ENOTSUP; 1169 } 1170 1171 static inline void 1172 handle_msg(struct ff_msg *msg, uint16_t proc_id) 1173 { 1174 switch (msg->msg_type) { 1175 case FF_SYSCTL: 1176 handle_sysctl_msg(msg); 1177 break; 1178 case FF_IOCTL: 1179 handle_ioctl_msg(msg); 1180 break; 1181 case FF_ROUTE: 1182 handle_route_msg(msg); 1183 break; 1184 case FF_TOP: 1185 handle_top_msg(msg); 1186 break; 1187 #ifdef FF_NETGRAPH 1188 case FF_NGCTL: 1189 handle_ngctl_msg(msg); 1190 break; 1191 #endif 1192 #ifdef FF_IPFW 1193 case FF_IPFW_CTL: 1194 handle_ipfw_msg(msg); 1195 break; 1196 #endif 1197 default: 1198 handle_default_msg(msg); 1199 break; 1200 } 1201 rte_ring_enqueue(msg_ring[proc_id].ring[1], msg); 1202 } 1203 1204 static inline int 1205 process_msg_ring(uint16_t proc_id) 1206 { 1207 void *msg; 1208 int ret = rte_ring_dequeue(msg_ring[proc_id].ring[0], &msg); 1209 1210 if (unlikely(ret == 0)) { 1211 handle_msg((struct ff_msg *)msg, proc_id); 1212 } 1213 1214 return 0; 1215 } 1216 1217 /* Send burst of packets on an output interface */ 1218 static inline int 1219 send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port) 1220 { 1221 struct rte_mbuf **m_table; 1222 int ret; 1223 uint16_t queueid; 1224 1225 queueid = qconf->tx_queue_id[port]; 1226 m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; 1227 1228 if (unlikely(qconf->pcap[port] != NULL)) { 1229 uint16_t i; 1230 for (i = 0; i < n; i++) { 1231 ff_dump_packets(qconf->pcap[port], m_table[i]); 1232 } 1233 } 1234 1235 ret = rte_eth_tx_burst(port, queueid, m_table, n); 1236 if (unlikely(ret < n)) { 1237 do { 1238 rte_pktmbuf_free(m_table[ret]); 1239 } while (++ret < n); 1240 } 1241 1242 return 0; 1243 } 1244 1245 /* Enqueue a single packet, and send burst if queue is filled */ 1246 static inline int 1247 send_single_packet(struct rte_mbuf *m, uint8_t port) 1248 { 1249 uint16_t len; 1250 struct lcore_conf *qconf; 1251 1252 qconf = &lcore_conf; 1253 len = qconf->tx_mbufs[port].len; 1254 qconf->tx_mbufs[port].m_table[len] = m; 1255 len++; 1256 1257 /* enough pkts to be sent */ 1258 if (unlikely(len == MAX_PKT_BURST)) { 1259 send_burst(qconf, MAX_PKT_BURST, port); 1260 len = 0; 1261 } 1262 1263 qconf->tx_mbufs[port].len = len; 1264 return 0; 1265 } 1266 1267 int 1268 ff_dpdk_if_send(struct ff_dpdk_if_context *ctx, void *m, 1269 int total) 1270 { 1271 struct rte_mempool *mbuf_pool = pktmbuf_pool[lcore_conf.socket_id]; 1272 struct rte_mbuf *head = rte_pktmbuf_alloc(mbuf_pool); 1273 if (head == NULL) { 1274 ff_mbuf_free(m); 1275 return -1; 1276 } 1277 1278 head->pkt_len = total; 1279 head->nb_segs = 0; 1280 1281 int off = 0; 1282 struct rte_mbuf *cur = head, *prev = NULL; 1283 while(total > 0) { 1284 if (cur == NULL) { 1285 cur = rte_pktmbuf_alloc(mbuf_pool); 1286 if (cur == NULL) { 1287 rte_pktmbuf_free(head); 1288 ff_mbuf_free(m); 1289 return -1; 1290 } 1291 } 1292 1293 void *data = rte_pktmbuf_mtod(cur, void*); 1294 int len = total > RTE_MBUF_DEFAULT_DATAROOM ? RTE_MBUF_DEFAULT_DATAROOM : total; 1295 int ret = ff_mbuf_copydata(m, data, off, len); 1296 if (ret < 0) { 1297 rte_pktmbuf_free(head); 1298 ff_mbuf_free(m); 1299 return -1; 1300 } 1301 1302 if (prev != NULL) { 1303 prev->next = cur; 1304 } 1305 prev = cur; 1306 1307 cur->data_len = len; 1308 off += len; 1309 total -= len; 1310 head->nb_segs++; 1311 cur = NULL; 1312 } 1313 1314 struct ff_tx_offload offload = {0}; 1315 ff_mbuf_tx_offload(m, &offload); 1316 1317 void *data = rte_pktmbuf_mtod(head, void*); 1318 1319 if (offload.ip_csum) { 1320 /* ipv6 not supported yet */ 1321 struct ipv4_hdr *iph; 1322 int iph_len; 1323 iph = (struct ipv4_hdr *)(data + ETHER_HDR_LEN); 1324 iph_len = (iph->version_ihl & 0x0f) << 2; 1325 1326 head->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4; 1327 head->l2_len = ETHER_HDR_LEN; 1328 head->l3_len = iph_len; 1329 } 1330 1331 if (ctx->hw_features.tx_csum_l4) { 1332 struct ipv4_hdr *iph; 1333 int iph_len; 1334 iph = (struct ipv4_hdr *)(data + ETHER_HDR_LEN); 1335 iph_len = (iph->version_ihl & 0x0f) << 2; 1336 1337 if (offload.tcp_csum) { 1338 head->ol_flags |= PKT_TX_TCP_CKSUM; 1339 head->l2_len = ETHER_HDR_LEN; 1340 head->l3_len = iph_len; 1341 } 1342 1343 /* 1344 * TCP segmentation offload. 1345 * 1346 * - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag 1347 * implies PKT_TX_TCP_CKSUM) 1348 * - set the flag PKT_TX_IPV4 or PKT_TX_IPV6 1349 * - if it's IPv4, set the PKT_TX_IP_CKSUM flag and 1350 * write the IP checksum to 0 in the packet 1351 * - fill the mbuf offload information: l2_len, 1352 * l3_len, l4_len, tso_segsz 1353 * - calculate the pseudo header checksum without taking ip_len 1354 * in account, and set it in the TCP header. Refer to 1355 * rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum() that can be 1356 * used as helpers. 1357 */ 1358 if (offload.tso_seg_size) { 1359 struct tcp_hdr *tcph; 1360 int tcph_len; 1361 tcph = (struct tcp_hdr *)((char *)iph + iph_len); 1362 tcph_len = (tcph->data_off & 0xf0) >> 2; 1363 tcph->cksum = rte_ipv4_phdr_cksum(iph, PKT_TX_TCP_SEG); 1364 1365 head->ol_flags |= PKT_TX_TCP_SEG; 1366 head->l4_len = tcph_len; 1367 head->tso_segsz = offload.tso_seg_size; 1368 } 1369 1370 if (offload.udp_csum) { 1371 head->ol_flags |= PKT_TX_UDP_CKSUM; 1372 head->l2_len = ETHER_HDR_LEN; 1373 head->l3_len = iph_len; 1374 } 1375 } 1376 1377 ff_mbuf_free(m); 1378 1379 return send_single_packet(head, ctx->port_id); 1380 } 1381 1382 static int 1383 main_loop(void *arg) 1384 { 1385 struct loop_routine *lr = (struct loop_routine *)arg; 1386 1387 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 1388 uint64_t prev_tsc, diff_tsc, cur_tsc, usch_tsc, div_tsc, usr_tsc, sys_tsc, end_tsc; 1389 int i, j, nb_rx, idle; 1390 uint16_t port_id, queue_id; 1391 struct lcore_conf *qconf; 1392 const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / 1393 US_PER_S * BURST_TX_DRAIN_US; 1394 struct ff_dpdk_if_context *ctx; 1395 1396 prev_tsc = 0; 1397 usch_tsc = 0; 1398 1399 qconf = &lcore_conf; 1400 1401 while (1) { 1402 cur_tsc = rte_rdtsc(); 1403 if (unlikely(freebsd_clock.expire < cur_tsc)) { 1404 rte_timer_manage(); 1405 } 1406 1407 idle = 1; 1408 sys_tsc = 0; 1409 usr_tsc = 0; 1410 1411 /* 1412 * TX burst queue drain 1413 */ 1414 diff_tsc = cur_tsc - prev_tsc; 1415 if (unlikely(diff_tsc > drain_tsc)) { 1416 for (i = 0; i < qconf->nb_tx_port; i++) { 1417 port_id = qconf->tx_port_id[i]; 1418 if (qconf->tx_mbufs[port_id].len == 0) 1419 continue; 1420 1421 idle = 0; 1422 1423 send_burst(qconf, 1424 qconf->tx_mbufs[port_id].len, 1425 port_id); 1426 qconf->tx_mbufs[port_id].len = 0; 1427 } 1428 1429 prev_tsc = cur_tsc; 1430 } 1431 1432 /* 1433 * Read packet from RX queues 1434 */ 1435 for (i = 0; i < qconf->nb_rx_queue; ++i) { 1436 port_id = qconf->rx_queue_list[i].port_id; 1437 queue_id = qconf->rx_queue_list[i].queue_id; 1438 ctx = veth_ctx[port_id]; 1439 1440 if (enable_kni && rte_eal_process_type() == RTE_PROC_PRIMARY) { 1441 ff_kni_process(port_id, queue_id, pkts_burst, MAX_PKT_BURST); 1442 } 1443 1444 process_dispatch_ring(port_id, queue_id, pkts_burst, ctx); 1445 1446 nb_rx = rte_eth_rx_burst(port_id, queue_id, pkts_burst, 1447 MAX_PKT_BURST); 1448 if (nb_rx == 0) 1449 continue; 1450 1451 idle = 0; 1452 1453 /* Prefetch first packets */ 1454 for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1455 rte_prefetch0(rte_pktmbuf_mtod( 1456 pkts_burst[j], void *)); 1457 } 1458 1459 /* Prefetch and handle already prefetched packets */ 1460 for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1461 rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 1462 j + PREFETCH_OFFSET], void *)); 1463 process_packets(port_id, queue_id, &pkts_burst[j], 1, ctx, 0); 1464 } 1465 1466 /* Handle remaining prefetched packets */ 1467 for (; j < nb_rx; j++) { 1468 process_packets(port_id, queue_id, &pkts_burst[j], 1, ctx, 0); 1469 } 1470 } 1471 1472 process_msg_ring(qconf->proc_id); 1473 1474 div_tsc = rte_rdtsc(); 1475 1476 if (likely(lr->loop != NULL && (!idle || cur_tsc - usch_tsc > drain_tsc))) { 1477 usch_tsc = cur_tsc; 1478 lr->loop(lr->arg); 1479 } 1480 1481 end_tsc = rte_rdtsc(); 1482 1483 if (usch_tsc == cur_tsc) { 1484 usr_tsc = end_tsc - div_tsc; 1485 } 1486 1487 if (!idle) { 1488 sys_tsc = div_tsc - cur_tsc; 1489 ff_status.sys_tsc += sys_tsc; 1490 } 1491 1492 ff_status.usr_tsc += usr_tsc; 1493 ff_status.work_tsc += end_tsc - cur_tsc; 1494 ff_status.idle_tsc += end_tsc - cur_tsc - usr_tsc - sys_tsc; 1495 1496 ff_status.loops++; 1497 } 1498 1499 return 0; 1500 } 1501 1502 int 1503 ff_dpdk_if_up(void) { 1504 int i; 1505 struct lcore_conf *qconf = &lcore_conf; 1506 for (i = 0; i < qconf->nb_tx_port; i++) { 1507 uint16_t port_id = qconf->tx_port_id[i]; 1508 1509 struct ff_port_cfg *pconf = &qconf->port_cfgs[port_id]; 1510 veth_ctx[port_id] = ff_veth_attach(pconf); 1511 if (veth_ctx[port_id] == NULL) { 1512 rte_exit(EXIT_FAILURE, "ff_veth_attach failed"); 1513 } 1514 } 1515 1516 return 0; 1517 } 1518 1519 void 1520 ff_dpdk_run(loop_func_t loop, void *arg) { 1521 struct loop_routine *lr = rte_malloc(NULL, 1522 sizeof(struct loop_routine), 0); 1523 lr->loop = loop; 1524 lr->arg = arg; 1525 rte_eal_mp_remote_launch(main_loop, lr, CALL_MASTER); 1526 rte_eal_mp_wait_lcore(); 1527 rte_free(lr); 1528 } 1529 1530 void 1531 ff_dpdk_pktmbuf_free(void *m) 1532 { 1533 rte_pktmbuf_free((struct rte_mbuf *)m); 1534 } 1535 1536 static uint32_t 1537 toeplitz_hash(unsigned keylen, const uint8_t *key, 1538 unsigned datalen, const uint8_t *data) 1539 { 1540 uint32_t hash = 0, v; 1541 u_int i, b; 1542 1543 /* XXXRW: Perhaps an assertion about key length vs. data length? */ 1544 1545 v = (key[0]<<24) + (key[1]<<16) + (key[2] <<8) + key[3]; 1546 for (i = 0; i < datalen; i++) { 1547 for (b = 0; b < 8; b++) { 1548 if (data[i] & (1<<(7-b))) 1549 hash ^= v; 1550 v <<= 1; 1551 if ((i + 4) < keylen && 1552 (key[i+4] & (1<<(7-b)))) 1553 v |= 1; 1554 } 1555 } 1556 return (hash); 1557 } 1558 1559 int 1560 ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr, 1561 uint16_t sport, uint16_t dport) 1562 { 1563 struct lcore_conf *qconf = &lcore_conf; 1564 struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc); 1565 uint16_t nb_queues = qconf->nb_queue_list[ctx->port_id]; 1566 1567 if (nb_queues <= 1) { 1568 return 1; 1569 } 1570 1571 uint16_t reta_size = rss_reta_size[ctx->port_id]; 1572 uint16_t queueid = qconf->tx_queue_id[ctx->port_id]; 1573 1574 uint8_t data[sizeof(saddr) + sizeof(daddr) + sizeof(sport) + 1575 sizeof(dport)]; 1576 1577 unsigned datalen = 0; 1578 1579 bcopy(&saddr, &data[datalen], sizeof(saddr)); 1580 datalen += sizeof(saddr); 1581 1582 bcopy(&daddr, &data[datalen], sizeof(daddr)); 1583 datalen += sizeof(daddr); 1584 1585 bcopy(&sport, &data[datalen], sizeof(sport)); 1586 datalen += sizeof(sport); 1587 1588 bcopy(&dport, &data[datalen], sizeof(dport)); 1589 datalen += sizeof(dport); 1590 1591 uint32_t hash = toeplitz_hash(sizeof(default_rsskey_40bytes), 1592 default_rsskey_40bytes, datalen, data); 1593 1594 return ((hash & (reta_size - 1)) % nb_queues) == queueid; 1595 } 1596 1597 void 1598 ff_regist_packet_dispatcher(dispatch_func_t func) 1599 { 1600 packet_dispatcher = func; 1601 } 1602 1603 uint64_t 1604 ff_get_tsc_ns() 1605 { 1606 uint64_t cur_tsc = rte_rdtsc(); 1607 uint64_t hz = rte_get_tsc_hz(); 1608 return ((double)cur_tsc/(double)hz) * NS_PER_S; 1609 } 1610 1611