1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <stdint.h> 10 #include <inttypes.h> 11 #include <errno.h> 12 #include <rte_cycles.h> 13 #include <sys/queue.h> 14 15 #include <rte_byteorder.h> 16 #include <rte_common.h> 17 #include <rte_debug.h> 18 #include <rte_ethdev.h> 19 #include <rte_log.h> 20 #include <rte_lcore.h> 21 #include <rte_memory.h> 22 23 #include <rte_string_fns.h> 24 25 #include <rte_eth_ring.h> 26 #include <rte_errno.h> 27 #include <rte_eth_bond.h> 28 #include <rte_eth_bond_8023ad.h> 29 30 #include "packet_burst_generator.h" 31 32 #include "test.h" 33 34 #define SLAVE_COUNT (4) 35 36 #define RX_RING_SIZE 1024 37 #define TX_RING_SIZE 1024 38 39 #define MBUF_CACHE_SIZE (250) 40 #define BURST_SIZE (32) 41 42 #define TEST_RX_DESC_MAX (2048) 43 #define TEST_TX_DESC_MAX (2048) 44 #define MAX_PKT_BURST (32) 45 #define DEF_PKT_BURST (16) 46 47 #define BONDED_DEV_NAME ("net_bonding_m4_bond_dev") 48 49 #define SLAVE_DEV_NAME_FMT ("net_virt_%d") 50 #define SLAVE_RX_QUEUE_FMT ("net_virt_%d_rx") 51 #define SLAVE_TX_QUEUE_FMT ("net_virt_%d_tx") 52 53 #define INVALID_SOCKET_ID (-1) 54 #define INVALID_PORT_ID (0xFF) 55 #define INVALID_BONDING_MODE (-1) 56 57 static const struct rte_ether_addr slave_mac_default = { 58 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } 59 }; 60 61 static const struct rte_ether_addr parnter_mac_default = { 62 { 0x22, 0xBB, 0xFF, 0xBB, 0x00, 0x00 } 63 }; 64 65 static const struct rte_ether_addr parnter_system = { 66 { 0x33, 0xFF, 0xBB, 0xFF, 0x00, 0x00 } 67 }; 68 69 static const struct rte_ether_addr slow_protocol_mac_addr = { 70 { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 } 71 }; 72 73 struct slave_conf { 74 struct rte_ring *rx_queue; 75 struct rte_ring *tx_queue; 76 uint16_t port_id; 77 uint8_t bonded : 1; 78 79 uint8_t lacp_parnter_state; 80 }; 81 82 struct ether_vlan_hdr { 83 struct rte_ether_hdr pkt_eth_hdr; 84 struct rte_vlan_hdr vlan_hdr; 85 }; 86 87 struct link_bonding_unittest_params { 88 uint8_t bonded_port_id; 89 struct slave_conf slave_ports[SLAVE_COUNT]; 90 91 struct rte_mempool *mbuf_pool; 92 }; 93 94 #define TEST_DEFAULT_SLAVE_COUNT RTE_DIM(test_params.slave_ports) 95 #define TEST_RX_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT 96 #define TEST_TX_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT 97 #define TEST_MARKER_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT 98 #define TEST_EXPIRED_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT 99 #define TEST_PROMISC_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT 100 101 static struct link_bonding_unittest_params test_params = { 102 .bonded_port_id = INVALID_PORT_ID, 103 .slave_ports = { [0 ... SLAVE_COUNT - 1] = { .port_id = INVALID_PORT_ID} }, 104 105 .mbuf_pool = NULL, 106 }; 107 108 static struct rte_eth_conf default_pmd_conf = { 109 .rxmode = { 110 .mq_mode = RTE_ETH_MQ_RX_NONE, 111 }, 112 .txmode = { 113 .mq_mode = RTE_ETH_MQ_TX_NONE, 114 }, 115 .lpbk_mode = 0, 116 }; 117 118 static uint8_t lacpdu_rx_count[RTE_MAX_ETHPORTS] = {0, }; 119 120 #define FOR_EACH(_i, _item, _array, _size) \ 121 for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++) 122 123 /* Macro for iterating over every port that can be used as a slave 124 * in this test. 125 * _i variable used as an index in test_params->slave_ports 126 * _slave pointer to &test_params->slave_ports[_idx] 127 */ 128 #define FOR_EACH_PORT(_i, _port) \ 129 FOR_EACH(_i, _port, test_params.slave_ports, \ 130 RTE_DIM(test_params.slave_ports)) 131 132 /* Macro for iterating over every port that can be used as a slave 133 * in this test and satisfy given condition. 134 * 135 * _i variable used as an index in test_params->slave_ports 136 * _slave pointer to &test_params->slave_ports[_idx] 137 * _condition condition that need to be checked 138 */ 139 #define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \ 140 if (!!(_condition)) 141 142 /* Macro for iterating over every port that is currently a slave of a bonded 143 * device. 144 * _i variable used as an index in test_params->slave_ports 145 * _slave pointer to &test_params->slave_ports[_idx] 146 * */ 147 #define FOR_EACH_SLAVE(_i, _slave) \ 148 FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0) 149 150 /* 151 * Returns packets from slaves TX queue. 152 * slave slave port 153 * buffer for packets 154 * size size of buffer 155 * return number of packets or negative error number 156 */ 157 static int 158 slave_get_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size) 159 { 160 return rte_ring_dequeue_burst(slave->tx_queue, (void **)buf, 161 size, NULL); 162 } 163 164 /* 165 * Injects given packets into slaves RX queue. 166 * slave slave port 167 * buffer for packets 168 * size number of packets to be injected 169 * return number of queued packets or negative error number 170 */ 171 static int 172 slave_put_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size) 173 { 174 return rte_ring_enqueue_burst(slave->rx_queue, (void **)buf, 175 size, NULL); 176 } 177 178 static uint16_t 179 bond_rx(struct rte_mbuf **buf, uint16_t size) 180 { 181 return rte_eth_rx_burst(test_params.bonded_port_id, 0, buf, size); 182 } 183 184 static uint16_t 185 bond_tx(struct rte_mbuf **buf, uint16_t size) 186 { 187 return rte_eth_tx_burst(test_params.bonded_port_id, 0, buf, size); 188 } 189 190 static void 191 free_pkts(struct rte_mbuf **pkts, uint16_t count) 192 { 193 uint16_t i; 194 195 for (i = 0; i < count; i++) { 196 rte_pktmbuf_free(pkts[i]); 197 } 198 } 199 200 static int 201 configure_ethdev(uint16_t port_id, uint8_t start) 202 { 203 TEST_ASSERT(rte_eth_dev_configure(port_id, 1, 1, &default_pmd_conf) == 0, 204 "Failed to configure device %u", port_id); 205 206 TEST_ASSERT(rte_eth_rx_queue_setup(port_id, 0, RX_RING_SIZE, 207 rte_eth_dev_socket_id(port_id), NULL, test_params.mbuf_pool) == 0, 208 "Failed to setup rx queue."); 209 210 TEST_ASSERT(rte_eth_tx_queue_setup(port_id, 0, TX_RING_SIZE, 211 rte_eth_dev_socket_id(port_id), NULL) == 0, 212 "Failed to setup tx queue."); 213 214 if (start) { 215 TEST_ASSERT(rte_eth_dev_start(port_id) == 0, 216 "Failed to start device (%d).", port_id); 217 } 218 return 0; 219 } 220 221 static int 222 add_slave(struct slave_conf *slave, uint8_t start) 223 { 224 struct rte_ether_addr addr, addr_check; 225 int retval; 226 227 /* Some sanity check */ 228 RTE_VERIFY(test_params.slave_ports <= slave && 229 slave - test_params.slave_ports < (int)RTE_DIM(test_params.slave_ports)); 230 RTE_VERIFY(slave->bonded == 0); 231 RTE_VERIFY(slave->port_id != INVALID_PORT_ID); 232 233 rte_ether_addr_copy(&slave_mac_default, &addr); 234 addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id; 235 236 rte_eth_dev_mac_addr_remove(slave->port_id, &addr); 237 238 TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave->port_id, &addr, 0), 239 "Failed to set slave MAC address"); 240 241 TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bonded_port_id, 242 slave->port_id), 243 "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)", 244 (uint8_t)(slave - test_params.slave_ports), slave->port_id, 245 test_params.bonded_port_id); 246 247 slave->bonded = 1; 248 if (start) { 249 TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave->port_id), 250 "Failed to start slave %u", slave->port_id); 251 } 252 253 retval = rte_eth_macaddr_get(slave->port_id, &addr_check); 254 TEST_ASSERT_SUCCESS(retval, "Failed to get slave mac address: %s", 255 strerror(-retval)); 256 TEST_ASSERT_EQUAL(rte_is_same_ether_addr(&addr, &addr_check), 1, 257 "Slave MAC address is not as expected"); 258 259 RTE_VERIFY(slave->lacp_parnter_state == 0); 260 return 0; 261 } 262 263 static int 264 remove_slave(struct slave_conf *slave) 265 { 266 ptrdiff_t slave_idx = slave - test_params.slave_ports; 267 268 RTE_VERIFY(test_params.slave_ports <= slave && 269 slave_idx < (ptrdiff_t)RTE_DIM(test_params.slave_ports)); 270 271 RTE_VERIFY(slave->bonded == 1); 272 RTE_VERIFY(slave->port_id != INVALID_PORT_ID); 273 274 TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0, 275 "Slave %u tx queue not empty while removing from bonding.", 276 slave->port_id); 277 278 TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0, 279 "Slave %u tx queue not empty while removing from bonding.", 280 slave->port_id); 281 282 TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params.bonded_port_id, 283 slave->port_id), 0, 284 "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)", 285 (uint8_t)slave_idx, slave->port_id, 286 test_params.bonded_port_id); 287 288 slave->bonded = 0; 289 slave->lacp_parnter_state = 0; 290 return 0; 291 } 292 293 static void 294 lacp_recv_cb(uint16_t slave_id, struct rte_mbuf *lacp_pkt) 295 { 296 struct rte_ether_hdr *hdr; 297 struct slow_protocol_frame *slow_hdr; 298 299 RTE_VERIFY(lacp_pkt != NULL); 300 301 hdr = rte_pktmbuf_mtod(lacp_pkt, struct rte_ether_hdr *); 302 RTE_VERIFY(hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW)); 303 304 slow_hdr = rte_pktmbuf_mtod(lacp_pkt, struct slow_protocol_frame *); 305 RTE_VERIFY(slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_LACP); 306 307 lacpdu_rx_count[slave_id]++; 308 rte_pktmbuf_free(lacp_pkt); 309 } 310 311 static int 312 initialize_bonded_device_with_slaves(uint16_t slave_count, uint8_t external_sm) 313 { 314 uint8_t i; 315 int ret; 316 317 RTE_VERIFY(test_params.bonded_port_id != INVALID_PORT_ID); 318 319 for (i = 0; i < slave_count; i++) { 320 TEST_ASSERT_SUCCESS(add_slave(&test_params.slave_ports[i], 1), 321 "Failed to add port %u to bonded device.\n", 322 test_params.slave_ports[i].port_id); 323 } 324 325 /* Reset mode 4 configuration */ 326 rte_eth_bond_8023ad_setup(test_params.bonded_port_id, NULL); 327 ret = rte_eth_promiscuous_disable(test_params.bonded_port_id); 328 TEST_ASSERT_SUCCESS(ret, 329 "Failed disable promiscuous mode for port %d: %s", 330 test_params.bonded_port_id, rte_strerror(-ret)); 331 332 if (external_sm) { 333 struct rte_eth_bond_8023ad_conf conf; 334 335 rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf); 336 conf.slowrx_cb = lacp_recv_cb; 337 rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf); 338 339 } 340 341 TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id), 342 "Failed to start bonded device"); 343 344 return TEST_SUCCESS; 345 } 346 347 static int 348 remove_slaves_and_stop_bonded_device(void) 349 { 350 struct slave_conf *slave; 351 int retval; 352 uint16_t slaves[RTE_MAX_ETHPORTS]; 353 uint16_t i; 354 355 TEST_ASSERT_SUCCESS(rte_eth_dev_stop(test_params.bonded_port_id), 356 "Failed to stop bonded port %u", 357 test_params.bonded_port_id); 358 359 FOR_EACH_SLAVE(i, slave) 360 remove_slave(slave); 361 362 retval = rte_eth_bond_slaves_get(test_params.bonded_port_id, slaves, 363 RTE_DIM(slaves)); 364 365 TEST_ASSERT_EQUAL(retval, 0, 366 "Expected bonded device %u have 0 slaves but returned %d.", 367 test_params.bonded_port_id, retval); 368 369 FOR_EACH_PORT(i, slave) { 370 TEST_ASSERT_SUCCESS(rte_eth_dev_stop(slave->port_id), 371 "Failed to stop bonded port %u", 372 slave->port_id); 373 374 TEST_ASSERT(slave->bonded == 0, 375 "Port id=%u is still marked as enslaved.", slave->port_id); 376 } 377 378 return TEST_SUCCESS; 379 } 380 381 static int 382 test_setup(void) 383 { 384 int retval, nb_mbuf_per_pool; 385 char name[RTE_ETH_NAME_MAX_LEN]; 386 struct slave_conf *port; 387 const uint8_t socket_id = rte_socket_id(); 388 uint16_t i; 389 390 if (test_params.mbuf_pool == NULL) { 391 nb_mbuf_per_pool = TEST_RX_DESC_MAX + DEF_PKT_BURST + 392 TEST_TX_DESC_MAX + MAX_PKT_BURST; 393 test_params.mbuf_pool = rte_pktmbuf_pool_create("TEST_MODE4", 394 nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0, 395 RTE_MBUF_DEFAULT_BUF_SIZE, socket_id); 396 397 TEST_ASSERT(test_params.mbuf_pool != NULL, 398 "rte_mempool_create failed\n"); 399 } 400 401 /* Create / initialize ring eth devs. */ 402 FOR_EACH_PORT(i, port) { 403 port = &test_params.slave_ports[i]; 404 405 if (port->rx_queue == NULL) { 406 retval = snprintf(name, RTE_DIM(name), SLAVE_RX_QUEUE_FMT, i); 407 TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long"); 408 port->rx_queue = rte_ring_create(name, RX_RING_SIZE, socket_id, 0); 409 TEST_ASSERT(port->rx_queue != NULL, 410 "Failed to allocate rx ring '%s': %s", name, 411 rte_strerror(rte_errno)); 412 } 413 414 if (port->tx_queue == NULL) { 415 retval = snprintf(name, RTE_DIM(name), SLAVE_TX_QUEUE_FMT, i); 416 TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long"); 417 port->tx_queue = rte_ring_create(name, TX_RING_SIZE, socket_id, 0); 418 TEST_ASSERT_NOT_NULL(port->tx_queue, 419 "Failed to allocate tx ring '%s': %s", name, 420 rte_strerror(rte_errno)); 421 } 422 423 if (port->port_id == INVALID_PORT_ID) { 424 retval = snprintf(name, RTE_DIM(name), SLAVE_DEV_NAME_FMT, i); 425 TEST_ASSERT(retval < (int)RTE_DIM(name) - 1, "Name too long"); 426 retval = rte_eth_from_rings(name, &port->rx_queue, 1, 427 &port->tx_queue, 1, socket_id); 428 TEST_ASSERT(retval >= 0, 429 "Failed to create ring ethdev '%s'\n", name); 430 431 port->port_id = rte_eth_dev_count_avail() - 1; 432 } 433 434 retval = configure_ethdev(port->port_id, 1); 435 TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n", 436 name); 437 } 438 439 if (test_params.bonded_port_id == INVALID_PORT_ID) { 440 retval = rte_eth_bond_create(BONDED_DEV_NAME, BONDING_MODE_8023AD, 441 socket_id); 442 443 TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s", 444 BONDED_DEV_NAME); 445 446 test_params.bonded_port_id = retval; 447 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bonded_port_id, 0), 448 "Failed to configure bonded ethdev %s", BONDED_DEV_NAME); 449 } else if (rte_eth_bond_mode_get(test_params.bonded_port_id) != 450 BONDING_MODE_8023AD) { 451 TEST_ASSERT(rte_eth_bond_mode_set(test_params.bonded_port_id, 452 BONDING_MODE_8023AD) == 0, 453 "Failed to set ethdev %d to mode %d", 454 test_params.bonded_port_id, BONDING_MODE_8023AD); 455 } 456 457 return 0; 458 } 459 460 static void 461 testsuite_teardown(void) 462 { 463 struct slave_conf *port; 464 uint8_t i; 465 466 /* Only stop ports. 467 * Any cleanup/reset state is done when particular test is 468 * started. */ 469 470 rte_eth_dev_stop(test_params.bonded_port_id); 471 472 FOR_EACH_PORT(i, port) 473 rte_eth_dev_stop(port->port_id); 474 } 475 476 /* 477 * Check if given LACP packet. If it is, make make replay packet to force 478 * COLLECTING state. 479 * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow 480 * frame but not LACP 481 */ 482 static int 483 make_lacp_reply(struct slave_conf *slave, struct rte_mbuf *pkt) 484 { 485 struct rte_ether_hdr *hdr; 486 struct slow_protocol_frame *slow_hdr; 487 struct lacpdu *lacp; 488 489 /* look for LACP */ 490 hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 491 if (hdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW)) 492 return 1; 493 494 slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *); 495 /* ignore packets of other types */ 496 if (slow_hdr->slow_protocol.subtype != SLOW_SUBTYPE_LACP) 497 return 2; 498 499 slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *); 500 501 /* Change source address to partner address */ 502 rte_ether_addr_copy(&parnter_mac_default, &slow_hdr->eth_hdr.src_addr); 503 slow_hdr->eth_hdr.src_addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = 504 slave->port_id; 505 506 lacp = (struct lacpdu *) &slow_hdr->slow_protocol; 507 /* Save last received state */ 508 slave->lacp_parnter_state = lacp->actor.state; 509 /* Change it into LACP replay by matching parameters. */ 510 memcpy(&lacp->partner.port_params, &lacp->actor.port_params, 511 sizeof(struct port_params)); 512 513 lacp->partner.state = lacp->actor.state; 514 515 rte_ether_addr_copy(&parnter_system, &lacp->actor.port_params.system); 516 lacp->actor.state = STATE_LACP_ACTIVE | 517 STATE_SYNCHRONIZATION | 518 STATE_AGGREGATION | 519 STATE_COLLECTING | 520 STATE_DISTRIBUTING; 521 522 return 0; 523 } 524 525 /* 526 * Reads packets from given slave, search for LACP packet and reply them. 527 * 528 * Receives burst of packets from slave. Looks for LACP packet. Drops 529 * all other packets. Prepares response LACP and sends it back. 530 * 531 * return number of LACP received and replied, -1 on error. 532 */ 533 static int 534 bond_handshake_reply(struct slave_conf *slave) 535 { 536 int retval; 537 struct rte_mbuf *rx_buf[MAX_PKT_BURST]; 538 struct rte_mbuf *lacp_tx_buf[MAX_PKT_BURST]; 539 uint16_t lacp_tx_buf_cnt = 0, i; 540 541 retval = slave_get_pkts(slave, rx_buf, RTE_DIM(rx_buf)); 542 TEST_ASSERT(retval >= 0, "Getting slave %u packets failed.", 543 slave->port_id); 544 545 for (i = 0; i < (uint16_t)retval; i++) { 546 if (make_lacp_reply(slave, rx_buf[i]) == 0) { 547 /* reply with actor's LACP */ 548 lacp_tx_buf[lacp_tx_buf_cnt++] = rx_buf[i]; 549 } else 550 rte_pktmbuf_free(rx_buf[i]); 551 } 552 553 if (lacp_tx_buf_cnt == 0) 554 return 0; 555 556 retval = slave_put_pkts(slave, lacp_tx_buf, lacp_tx_buf_cnt); 557 if (retval <= lacp_tx_buf_cnt) { 558 /* retval might be negative */ 559 for (i = RTE_MAX(0, retval); retval < lacp_tx_buf_cnt; retval++) 560 rte_pktmbuf_free(lacp_tx_buf[i]); 561 } 562 563 TEST_ASSERT_EQUAL(retval, lacp_tx_buf_cnt, 564 "Failed to equeue lacp packets into slave %u tx queue.", 565 slave->port_id); 566 567 return lacp_tx_buf_cnt; 568 } 569 570 /* 571 * Function check if given slave tx queue contains packets that make mode 4 572 * handshake complete. It will drain slave queue. 573 * return 0 if handshake not completed, 1 if handshake was complete, 574 */ 575 static int 576 bond_handshake_done(struct slave_conf *slave) 577 { 578 const uint8_t expected_state = STATE_LACP_ACTIVE | STATE_SYNCHRONIZATION | 579 STATE_AGGREGATION | STATE_COLLECTING | STATE_DISTRIBUTING; 580 581 return slave->lacp_parnter_state == expected_state; 582 } 583 584 static unsigned 585 bond_get_update_timeout_ms(void) 586 { 587 struct rte_eth_bond_8023ad_conf conf; 588 589 if (rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf) < 0) { 590 RTE_LOG(DEBUG, EAL, "Failed to get bonding configuration: " 591 "%s at %d\n", __func__, __LINE__); 592 RTE_TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); 593 return 0; 594 } 595 596 return conf.update_timeout_ms; 597 } 598 599 /* 600 * Exchanges LACP packets with partner to achieve dynamic port configuration. 601 * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise. 602 */ 603 static int 604 bond_handshake(void) 605 { 606 struct slave_conf *slave; 607 struct rte_mbuf *buf[MAX_PKT_BURST]; 608 uint16_t nb_pkts; 609 uint8_t all_slaves_done, i, j; 610 uint8_t status[RTE_DIM(test_params.slave_ports)] = { 0 }; 611 const unsigned delay = bond_get_update_timeout_ms(); 612 613 /* Exchange LACP frames */ 614 all_slaves_done = 0; 615 for (i = 0; i < 30 && all_slaves_done == 0; ++i) { 616 rte_delay_ms(delay); 617 618 all_slaves_done = 1; 619 FOR_EACH_SLAVE(j, slave) { 620 /* If response already send, skip slave */ 621 if (status[j] != 0) 622 continue; 623 624 if (bond_handshake_reply(slave) < 0) { 625 all_slaves_done = 0; 626 break; 627 } 628 629 status[j] = bond_handshake_done(slave); 630 if (status[j] == 0) 631 all_slaves_done = 0; 632 } 633 634 nb_pkts = bond_tx(NULL, 0); 635 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly"); 636 637 nb_pkts = bond_rx(buf, RTE_DIM(buf)); 638 free_pkts(buf, nb_pkts); 639 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly"); 640 } 641 /* If response didn't send - report failure */ 642 TEST_ASSERT_EQUAL(all_slaves_done, 1, "Bond handshake failed\n"); 643 644 /* If flags doesn't match - report failure */ 645 return all_slaves_done == 1 ? TEST_SUCCESS : TEST_FAILED; 646 } 647 648 #define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports) 649 static int 650 test_mode4_lacp(void) 651 { 652 int retval; 653 654 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 655 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 656 657 /* Test LACP handshake function */ 658 retval = bond_handshake(); 659 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 660 661 retval = remove_slaves_and_stop_bonded_device(); 662 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 663 664 return TEST_SUCCESS; 665 } 666 static int 667 test_mode4_agg_mode_selection(void) 668 { 669 int retval; 670 /* Test and verify for Stable mode */ 671 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 672 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 673 674 675 retval = rte_eth_bond_8023ad_agg_selection_set( 676 test_params.bonded_port_id, AGG_STABLE); 677 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bond aggregation mode"); 678 retval = bond_handshake(); 679 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 680 681 682 retval = rte_eth_bond_8023ad_agg_selection_get( 683 test_params.bonded_port_id); 684 TEST_ASSERT_EQUAL(retval, AGG_STABLE, 685 "Wrong agg mode received from bonding device"); 686 687 retval = remove_slaves_and_stop_bonded_device(); 688 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 689 690 691 /* test and verify for Bandwidth mode */ 692 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 693 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 694 695 696 retval = rte_eth_bond_8023ad_agg_selection_set( 697 test_params.bonded_port_id, 698 AGG_BANDWIDTH); 699 TEST_ASSERT_SUCCESS(retval, 700 "Failed to initialize bond aggregation mode"); 701 retval = bond_handshake(); 702 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 703 704 retval = rte_eth_bond_8023ad_agg_selection_get( 705 test_params.bonded_port_id); 706 TEST_ASSERT_EQUAL(retval, AGG_BANDWIDTH, 707 "Wrong agg mode received from bonding device"); 708 709 retval = remove_slaves_and_stop_bonded_device(); 710 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 711 712 /* test and verify selection for count mode */ 713 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 714 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 715 716 717 retval = rte_eth_bond_8023ad_agg_selection_set( 718 test_params.bonded_port_id, AGG_COUNT); 719 TEST_ASSERT_SUCCESS(retval, 720 "Failed to initialize bond aggregation mode"); 721 retval = bond_handshake(); 722 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 723 724 retval = rte_eth_bond_8023ad_agg_selection_get( 725 test_params.bonded_port_id); 726 TEST_ASSERT_EQUAL(retval, AGG_COUNT, 727 "Wrong agg mode received from bonding device"); 728 729 retval = remove_slaves_and_stop_bonded_device(); 730 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 731 732 return TEST_SUCCESS; 733 } 734 735 static int 736 generate_packets(struct rte_ether_addr *src_mac, 737 struct rte_ether_addr *dst_mac, uint16_t count, struct rte_mbuf **buf) 738 { 739 uint16_t pktlen = PACKET_BURST_GEN_PKT_LEN; 740 uint8_t vlan_enable = 0; 741 uint16_t vlan_id = 0; 742 uint8_t ip4_type = 1; /* 0 - ipv6 */ 743 744 uint16_t src_port = 10, dst_port = 20; 745 746 uint32_t ip_src[4] = { [0 ... 2] = 0xDEADBEEF, [3] = RTE_IPV4(192, 168, 0, 1) }; 747 uint32_t ip_dst[4] = { [0 ... 2] = 0xFEEDFACE, [3] = RTE_IPV4(192, 168, 0, 2) }; 748 749 struct rte_ether_hdr pkt_eth_hdr; 750 struct rte_udp_hdr pkt_udp_hdr; 751 union { 752 struct rte_ipv4_hdr v4; 753 struct rte_ipv6_hdr v6; 754 } pkt_ip_hdr; 755 756 int retval; 757 758 initialize_eth_header(&pkt_eth_hdr, src_mac, dst_mac, ip4_type, 759 vlan_enable, vlan_id); 760 761 if (ip4_type) 762 initialize_ipv4_header(&pkt_ip_hdr.v4, ip_src[3], ip_dst[3], pktlen); 763 else 764 initialize_ipv6_header(&pkt_ip_hdr.v6, (uint8_t *)ip_src, 765 (uint8_t *)&ip_dst, pktlen); 766 767 initialize_udp_header(&pkt_udp_hdr, src_port, dst_port, 16); 768 769 retval = generate_packet_burst(test_params.mbuf_pool, buf, 770 &pkt_eth_hdr, vlan_enable, &pkt_ip_hdr, 1, &pkt_udp_hdr, 771 count, pktlen, 1); 772 773 if (retval > 0 && retval != count) 774 free_pkts(&buf[count - retval], retval); 775 776 TEST_ASSERT_EQUAL(retval, count, "Failed to generate %u packets", 777 count); 778 779 return count; 780 } 781 782 static int 783 generate_and_put_packets(struct slave_conf *slave, 784 struct rte_ether_addr *src_mac, 785 struct rte_ether_addr *dst_mac, uint16_t count) 786 { 787 struct rte_mbuf *pkts[MAX_PKT_BURST]; 788 int retval; 789 790 retval = generate_packets(src_mac, dst_mac, count, pkts); 791 if (retval != (int)count) 792 return retval; 793 794 retval = slave_put_pkts(slave, pkts, count); 795 if (retval > 0 && retval != count) 796 free_pkts(&pkts[retval], count - retval); 797 798 TEST_ASSERT_EQUAL(retval, count, 799 "Failed to enqueue packets into slave %u RX queue", slave->port_id); 800 801 return TEST_SUCCESS; 802 } 803 804 static int 805 test_mode4_rx(void) 806 { 807 struct slave_conf *slave; 808 uint16_t i, j; 809 810 uint16_t expected_pkts_cnt; 811 struct rte_mbuf *pkts[MAX_PKT_BURST]; 812 int retval; 813 unsigned delay; 814 815 struct rte_ether_hdr *hdr; 816 817 struct rte_ether_addr src_mac = { 818 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; 819 struct rte_ether_addr dst_mac; 820 struct rte_ether_addr bonded_mac; 821 822 retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT, 823 0); 824 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 825 826 retval = bond_handshake(); 827 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 828 829 retval = rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac); 830 TEST_ASSERT_SUCCESS(retval, "Failed to get mac address: %s", 831 strerror(-retval)); 832 rte_ether_addr_copy(&bonded_mac, &dst_mac); 833 834 /* Assert that dst address is not bonding address. Do not set the 835 * least significant bit of the zero byte as this would create a 836 * multicast address. 837 */ 838 dst_mac.addr_bytes[0] += 2; 839 840 /* First try with promiscuous mode enabled. 841 * Add 2 packets to each slave. First with bonding MAC address, second with 842 * different. Check if we received all of them. */ 843 retval = rte_eth_promiscuous_enable(test_params.bonded_port_id); 844 TEST_ASSERT_SUCCESS(retval, 845 "Failed to enable promiscuous mode for port %d: %s", 846 test_params.bonded_port_id, rte_strerror(-retval)); 847 848 expected_pkts_cnt = 0; 849 FOR_EACH_SLAVE(i, slave) { 850 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); 851 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 852 slave->port_id); 853 854 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); 855 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 856 slave->port_id); 857 858 /* Expect 2 packets per slave */ 859 expected_pkts_cnt += 2; 860 } 861 862 retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, 863 RTE_DIM(pkts)); 864 865 if (retval == expected_pkts_cnt) { 866 int cnt[2] = { 0, 0 }; 867 868 for (i = 0; i < expected_pkts_cnt; i++) { 869 hdr = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); 870 cnt[rte_is_same_ether_addr(&hdr->dst_addr, 871 &bonded_mac)]++; 872 } 873 874 free_pkts(pkts, expected_pkts_cnt); 875 876 /* For division by 2 expected_pkts_cnt must be even */ 877 RTE_VERIFY((expected_pkts_cnt & 1) == 0); 878 TEST_ASSERT(cnt[0] == expected_pkts_cnt / 2 && 879 cnt[1] == expected_pkts_cnt / 2, 880 "Expected %u packets with the same MAC and %u with different but " 881 "got %u with the same and %u with different MAC", 882 expected_pkts_cnt / 2, expected_pkts_cnt / 2, cnt[1], cnt[0]); 883 } else if (retval > 0) 884 free_pkts(pkts, retval); 885 886 TEST_ASSERT_EQUAL(retval, expected_pkts_cnt, 887 "Expected %u packets but received only %d", expected_pkts_cnt, retval); 888 889 /* Now, disable promiscuous mode. When promiscuous mode is disabled we 890 * expect to receive only packets that are directed to bonding port. */ 891 retval = rte_eth_promiscuous_disable(test_params.bonded_port_id); 892 TEST_ASSERT_SUCCESS(retval, 893 "Failed to disable promiscuous mode for port %d: %s", 894 test_params.bonded_port_id, rte_strerror(-retval)); 895 896 expected_pkts_cnt = 0; 897 FOR_EACH_SLAVE(i, slave) { 898 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); 899 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 900 slave->port_id); 901 902 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); 903 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 904 slave->port_id); 905 906 /* Expect only one packet per slave */ 907 expected_pkts_cnt += 1; 908 } 909 910 retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, 911 RTE_DIM(pkts)); 912 913 if (retval == expected_pkts_cnt) { 914 int eq_cnt = 0; 915 916 for (i = 0; i < expected_pkts_cnt; i++) { 917 hdr = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); 918 eq_cnt += rte_is_same_ether_addr(&hdr->dst_addr, 919 &bonded_mac); 920 } 921 922 free_pkts(pkts, expected_pkts_cnt); 923 TEST_ASSERT_EQUAL(eq_cnt, expected_pkts_cnt, "Packet address mismatch"); 924 } else if (retval > 0) 925 free_pkts(pkts, retval); 926 927 TEST_ASSERT_EQUAL(retval, expected_pkts_cnt, 928 "Expected %u packets but received only %d", expected_pkts_cnt, retval); 929 930 /* Link down test: simulate link down for first slave. */ 931 delay = bond_get_update_timeout_ms(); 932 933 uint8_t slave_down_id = INVALID_PORT_ID; 934 935 /* Find first slave and make link down on it*/ 936 FOR_EACH_SLAVE(i, slave) { 937 rte_eth_dev_set_link_down(slave->port_id); 938 slave_down_id = slave->port_id; 939 break; 940 } 941 942 RTE_VERIFY(slave_down_id != INVALID_PORT_ID); 943 944 /* Give some time to rearrange bonding */ 945 for (i = 0; i < 3; i++) { 946 rte_delay_ms(delay); 947 bond_handshake(); 948 } 949 950 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed"); 951 952 /* Put packet to each slave */ 953 FOR_EACH_SLAVE(i, slave) { 954 void *pkt = NULL; 955 956 dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id; 957 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); 958 TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst."); 959 960 src_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id; 961 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); 962 TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst."); 963 964 retval = bond_rx(pkts, RTE_DIM(pkts)); 965 966 /* Clean anything */ 967 if (retval > 0) 968 free_pkts(pkts, retval); 969 970 while (rte_ring_dequeue(slave->rx_queue, (void **)&pkt) == 0) 971 rte_pktmbuf_free(pkt); 972 973 if (slave_down_id == slave->port_id) 974 TEST_ASSERT_EQUAL(retval, 0, "Packets received unexpectedly."); 975 else 976 TEST_ASSERT_NOT_EQUAL(retval, 0, 977 "Expected to receive some packets on slave %u.", 978 slave->port_id); 979 rte_eth_dev_start(slave->port_id); 980 981 for (j = 0; j < 5; j++) { 982 TEST_ASSERT(bond_handshake_reply(slave) >= 0, 983 "Handshake after link up"); 984 985 if (bond_handshake_done(slave) == 1) 986 break; 987 } 988 989 TEST_ASSERT(j < 5, "Failed to aggregate slave after link up"); 990 } 991 992 remove_slaves_and_stop_bonded_device(); 993 return TEST_SUCCESS; 994 } 995 996 static int 997 test_mode4_tx_burst(void) 998 { 999 struct slave_conf *slave; 1000 uint16_t i, j; 1001 1002 uint16_t exp_pkts_cnt, pkts_cnt = 0; 1003 struct rte_mbuf *pkts[MAX_PKT_BURST]; 1004 int retval; 1005 unsigned delay; 1006 1007 struct rte_ether_addr dst_mac = { 1008 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; 1009 struct rte_ether_addr bonded_mac; 1010 1011 retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0); 1012 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 1013 1014 retval = bond_handshake(); 1015 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 1016 1017 retval = rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac); 1018 TEST_ASSERT_SUCCESS(retval, "Failed to get mac address: %s", 1019 strerror(-retval)); 1020 /* Prepare burst */ 1021 for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) { 1022 dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = pkts_cnt; 1023 retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]); 1024 1025 if (retval != 1) 1026 free_pkts(pkts, pkts_cnt); 1027 1028 TEST_ASSERT_EQUAL(retval, 1, "Failed to generate packet %u", pkts_cnt); 1029 } 1030 exp_pkts_cnt = pkts_cnt; 1031 1032 /* Transmit packets on bonded device */ 1033 retval = bond_tx(pkts, pkts_cnt); 1034 if (retval > 0 && retval < pkts_cnt) 1035 free_pkts(&pkts[retval], pkts_cnt - retval); 1036 1037 TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed"); 1038 1039 /* Check if packets were transmitted properly. Every slave should have 1040 * at least one packet, and sum must match. Under normal operation 1041 * there should be no LACP nor MARKER frames. */ 1042 pkts_cnt = 0; 1043 FOR_EACH_SLAVE(i, slave) { 1044 uint16_t normal_cnt, slow_cnt; 1045 1046 retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts)); 1047 normal_cnt = 0; 1048 slow_cnt = 0; 1049 1050 for (j = 0; j < retval; j++) { 1051 if (make_lacp_reply(slave, pkts[j]) == 1) 1052 normal_cnt++; 1053 else 1054 slow_cnt++; 1055 } 1056 1057 free_pkts(pkts, normal_cnt + slow_cnt); 1058 TEST_ASSERT_EQUAL(slow_cnt, 0, 1059 "slave %u unexpectedly transmitted %d SLOW packets", slave->port_id, 1060 slow_cnt); 1061 1062 TEST_ASSERT_NOT_EQUAL(normal_cnt, 0, 1063 "slave %u did not transmitted any packets", slave->port_id); 1064 1065 pkts_cnt += normal_cnt; 1066 } 1067 1068 TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt, 1069 "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt); 1070 1071 /* Link down test: 1072 * simulate link down for first slave. */ 1073 delay = bond_get_update_timeout_ms(); 1074 1075 uint8_t slave_down_id = INVALID_PORT_ID; 1076 1077 FOR_EACH_SLAVE(i, slave) { 1078 rte_eth_dev_set_link_down(slave->port_id); 1079 slave_down_id = slave->port_id; 1080 break; 1081 } 1082 1083 RTE_VERIFY(slave_down_id != INVALID_PORT_ID); 1084 1085 /* Give some time to rearrange bonding. */ 1086 for (i = 0; i < 3; i++) { 1087 bond_handshake(); 1088 rte_delay_ms(delay); 1089 } 1090 1091 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed"); 1092 1093 /* Prepare burst. */ 1094 for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) { 1095 dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = pkts_cnt; 1096 retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]); 1097 1098 if (retval != 1) 1099 free_pkts(pkts, pkts_cnt); 1100 1101 TEST_ASSERT_EQUAL(retval, 1, "Failed to generate test packet %u", 1102 pkts_cnt); 1103 } 1104 exp_pkts_cnt = pkts_cnt; 1105 1106 /* Transmit packets on bonded device. */ 1107 retval = bond_tx(pkts, pkts_cnt); 1108 if (retval > 0 && retval < pkts_cnt) 1109 free_pkts(&pkts[retval], pkts_cnt - retval); 1110 1111 TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed"); 1112 1113 /* Check if packets was transmitted properly. Every slave should have 1114 * at least one packet, and sum must match. Under normal operation 1115 * there should be no LACP nor MARKER frames. */ 1116 pkts_cnt = 0; 1117 FOR_EACH_SLAVE(i, slave) { 1118 uint16_t normal_cnt, slow_cnt; 1119 1120 retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts)); 1121 normal_cnt = 0; 1122 slow_cnt = 0; 1123 1124 for (j = 0; j < retval; j++) { 1125 if (make_lacp_reply(slave, pkts[j]) == 1) 1126 normal_cnt++; 1127 else 1128 slow_cnt++; 1129 } 1130 1131 free_pkts(pkts, normal_cnt + slow_cnt); 1132 1133 if (slave_down_id == slave->port_id) { 1134 TEST_ASSERT_EQUAL(normal_cnt + slow_cnt, 0, 1135 "slave %u enexpectedly transmitted %u packets", 1136 normal_cnt + slow_cnt, slave->port_id); 1137 } else { 1138 TEST_ASSERT_EQUAL(slow_cnt, 0, 1139 "slave %u unexpectedly transmitted %d SLOW packets", 1140 slave->port_id, slow_cnt); 1141 1142 TEST_ASSERT_NOT_EQUAL(normal_cnt, 0, 1143 "slave %u did not transmitted any packets", slave->port_id); 1144 } 1145 1146 pkts_cnt += normal_cnt; 1147 } 1148 1149 TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt, 1150 "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt); 1151 1152 return remove_slaves_and_stop_bonded_device(); 1153 } 1154 1155 static void 1156 init_marker(struct rte_mbuf *pkt, struct slave_conf *slave) 1157 { 1158 struct marker_header *marker_hdr = rte_pktmbuf_mtod(pkt, 1159 struct marker_header *); 1160 1161 /* Copy multicast destination address */ 1162 rte_ether_addr_copy(&slow_protocol_mac_addr, 1163 &marker_hdr->eth_hdr.dst_addr); 1164 1165 /* Init source address */ 1166 rte_ether_addr_copy(&parnter_mac_default, 1167 &marker_hdr->eth_hdr.src_addr); 1168 marker_hdr->eth_hdr.src_addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = 1169 slave->port_id; 1170 1171 marker_hdr->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW); 1172 1173 marker_hdr->marker.subtype = SLOW_SUBTYPE_MARKER; 1174 marker_hdr->marker.version_number = 1; 1175 marker_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_INFO; 1176 marker_hdr->marker.info_length = 1177 offsetof(struct marker, reserved_90) - 1178 offsetof(struct marker, requester_port); 1179 RTE_VERIFY(marker_hdr->marker.info_length == 16); 1180 marker_hdr->marker.requester_port = slave->port_id + 1; 1181 marker_hdr->marker.tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION; 1182 marker_hdr->marker.terminator_length = 0; 1183 } 1184 1185 static int 1186 test_mode4_marker(void) 1187 { 1188 struct slave_conf *slave; 1189 struct rte_mbuf *pkts[MAX_PKT_BURST]; 1190 struct rte_mbuf *marker_pkt; 1191 struct marker_header *marker_hdr; 1192 1193 unsigned delay; 1194 int retval; 1195 uint16_t nb_pkts; 1196 uint8_t i, j; 1197 const uint16_t ethtype_slow_be = rte_be_to_cpu_16(RTE_ETHER_TYPE_SLOW); 1198 1199 retval = initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT, 1200 0); 1201 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 1202 1203 /* Test LACP handshake function */ 1204 retval = bond_handshake(); 1205 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 1206 1207 delay = bond_get_update_timeout_ms(); 1208 FOR_EACH_SLAVE(i, slave) { 1209 marker_pkt = rte_pktmbuf_alloc(test_params.mbuf_pool); 1210 TEST_ASSERT_NOT_NULL(marker_pkt, "Failed to allocate marker packet"); 1211 init_marker(marker_pkt, slave); 1212 1213 retval = slave_put_pkts(slave, &marker_pkt, 1); 1214 if (retval != 1) 1215 rte_pktmbuf_free(marker_pkt); 1216 1217 TEST_ASSERT_EQUAL(retval, 1, 1218 "Failed to send marker packet to slave %u", slave->port_id); 1219 1220 for (j = 0; j < 20; ++j) { 1221 rte_delay_ms(delay); 1222 retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, 1223 RTE_DIM(pkts)); 1224 1225 if (retval > 0) 1226 free_pkts(pkts, retval); 1227 1228 TEST_ASSERT_EQUAL(retval, 0, "Received packets unexpectedly"); 1229 1230 retval = rte_eth_tx_burst(test_params.bonded_port_id, 0, NULL, 0); 1231 TEST_ASSERT_EQUAL(retval, 0, 1232 "Requested TX of 0 packets but %d transmitted", retval); 1233 1234 /* Check if LACP packet was send by state machines 1235 First and only packet must be a maker response */ 1236 retval = slave_get_pkts(slave, pkts, MAX_PKT_BURST); 1237 if (retval == 0) 1238 continue; 1239 if (retval > 1) 1240 free_pkts(pkts, retval); 1241 1242 TEST_ASSERT_EQUAL(retval, 1, "failed to get slave packets"); 1243 nb_pkts = retval; 1244 1245 marker_hdr = rte_pktmbuf_mtod(pkts[0], struct marker_header *); 1246 /* Check if it's slow packet*/ 1247 if (marker_hdr->eth_hdr.ether_type != ethtype_slow_be) 1248 retval = -1; 1249 /* Check if it's marker packet */ 1250 else if (marker_hdr->marker.subtype != SLOW_SUBTYPE_MARKER) 1251 retval = -2; 1252 else if (marker_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_RESP) 1253 retval = -3; 1254 1255 free_pkts(pkts, nb_pkts); 1256 1257 TEST_ASSERT_NOT_EQUAL(retval, -1, "Unexpected protocol type"); 1258 TEST_ASSERT_NOT_EQUAL(retval, -2, "Unexpected sub protocol type"); 1259 TEST_ASSERT_NOT_EQUAL(retval, -3, "Unexpected marker type"); 1260 break; 1261 } 1262 1263 TEST_ASSERT(j < 20, "Marker response not found"); 1264 } 1265 1266 retval = remove_slaves_and_stop_bonded_device(); 1267 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 1268 1269 return TEST_SUCCESS; 1270 } 1271 1272 static int 1273 test_mode4_expired(void) 1274 { 1275 struct slave_conf *slave, *exp_slave = NULL; 1276 struct rte_mbuf *pkts[MAX_PKT_BURST]; 1277 int retval; 1278 uint32_t old_delay; 1279 1280 uint8_t i; 1281 uint16_t j; 1282 1283 struct rte_eth_bond_8023ad_conf conf; 1284 1285 retval = initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT, 1286 0); 1287 /* Set custom timeouts to make test last shorter. */ 1288 rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf); 1289 conf.fast_periodic_ms = 100; 1290 conf.slow_periodic_ms = 600; 1291 conf.short_timeout_ms = 300; 1292 conf.long_timeout_ms = 900; 1293 conf.aggregate_wait_timeout_ms = 200; 1294 conf.tx_period_ms = 100; 1295 old_delay = conf.update_timeout_ms; 1296 conf.update_timeout_ms = 10; 1297 rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf); 1298 1299 /* Wait for new settings to be applied. */ 1300 for (i = 0; i < old_delay/conf.update_timeout_ms * 2; i++) { 1301 FOR_EACH_SLAVE(j, slave) 1302 bond_handshake_reply(slave); 1303 1304 rte_delay_ms(conf.update_timeout_ms); 1305 } 1306 1307 retval = bond_handshake(); 1308 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 1309 1310 /* Find first slave */ 1311 FOR_EACH_SLAVE(i, slave) { 1312 exp_slave = slave; 1313 break; 1314 } 1315 1316 RTE_VERIFY(exp_slave != NULL); 1317 1318 /* When one of partners do not send or respond to LACP frame in 1319 * conf.long_timeout_ms time, internal state machines should detect this 1320 * and transit to expired state. */ 1321 for (j = 0; j < conf.long_timeout_ms/conf.update_timeout_ms + 2; j++) { 1322 rte_delay_ms(conf.update_timeout_ms); 1323 1324 retval = bond_tx(NULL, 0); 1325 TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets", 1326 retval); 1327 1328 FOR_EACH_SLAVE(i, slave) { 1329 retval = bond_handshake_reply(slave); 1330 TEST_ASSERT(retval >= 0, "Handshake failed"); 1331 1332 /* Remove replay for slave that suppose to be expired. */ 1333 if (slave == exp_slave) { 1334 while (rte_ring_count(slave->rx_queue) > 0) { 1335 void *pkt = NULL; 1336 1337 rte_ring_dequeue(slave->rx_queue, &pkt); 1338 rte_pktmbuf_free(pkt); 1339 } 1340 } 1341 } 1342 1343 retval = bond_rx(pkts, RTE_DIM(pkts)); 1344 if (retval > 0) 1345 free_pkts(pkts, retval); 1346 1347 TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets", 1348 retval); 1349 } 1350 1351 /* After test only expected slave should be in EXPIRED state */ 1352 FOR_EACH_SLAVE(i, slave) { 1353 if (slave == exp_slave) 1354 TEST_ASSERT(slave->lacp_parnter_state & STATE_EXPIRED, 1355 "Slave %u should be in expired.", slave->port_id); 1356 else 1357 TEST_ASSERT_EQUAL(bond_handshake_done(slave), 1, 1358 "Slave %u should be operational.", slave->port_id); 1359 } 1360 1361 retval = remove_slaves_and_stop_bonded_device(); 1362 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 1363 1364 return TEST_SUCCESS; 1365 } 1366 1367 static int 1368 test_mode4_ext_ctrl(void) 1369 { 1370 /* 1371 * configure bonded interface without the external sm enabled 1372 * . try to transmit lacpdu (should fail) 1373 * . try to set collecting and distributing flags (should fail) 1374 * reconfigure w/external sm 1375 * . transmit one lacpdu on each slave using new api 1376 * . make sure each slave receives one lacpdu using the callback api 1377 * . transmit one data pdu on each slave (should fail) 1378 * . enable distribution and collection, send one data pdu each again 1379 */ 1380 1381 int retval; 1382 struct slave_conf *slave = NULL; 1383 uint8_t i; 1384 1385 struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT]; 1386 struct rte_ether_addr src_mac, dst_mac; 1387 struct lacpdu_header lacpdu = { 1388 .lacpdu = { 1389 .subtype = SLOW_SUBTYPE_LACP, 1390 }, 1391 }; 1392 1393 rte_ether_addr_copy(&parnter_system, &src_mac); 1394 rte_ether_addr_copy(&slow_protocol_mac_addr, &dst_mac); 1395 1396 initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac, 1397 RTE_ETHER_TYPE_SLOW, 0, 0); 1398 1399 for (i = 0; i < SLAVE_COUNT; i++) { 1400 lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool); 1401 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *), 1402 &lacpdu, sizeof(lacpdu)); 1403 rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu); 1404 } 1405 1406 retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0); 1407 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 1408 1409 FOR_EACH_SLAVE(i, slave) { 1410 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_slowtx( 1411 test_params.bonded_port_id, 1412 slave->port_id, lacp_tx_buf[i]), 1413 "Slave should not allow manual LACP xmit"); 1414 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_collect( 1415 test_params.bonded_port_id, 1416 slave->port_id, 1), 1417 "Slave should not allow external state controls"); 1418 } 1419 1420 free_pkts(lacp_tx_buf, RTE_DIM(lacp_tx_buf)); 1421 1422 retval = remove_slaves_and_stop_bonded_device(); 1423 TEST_ASSERT_SUCCESS(retval, "Bonded device cleanup failed."); 1424 1425 return TEST_SUCCESS; 1426 } 1427 1428 1429 static int 1430 test_mode4_ext_lacp(void) 1431 { 1432 int retval; 1433 struct slave_conf *slave = NULL; 1434 uint8_t all_slaves_done = 0, i; 1435 uint16_t nb_pkts; 1436 const unsigned int delay = bond_get_update_timeout_ms(); 1437 1438 struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT]; 1439 struct rte_mbuf *buf[SLAVE_COUNT]; 1440 struct rte_ether_addr src_mac, dst_mac; 1441 struct lacpdu_header lacpdu = { 1442 .lacpdu = { 1443 .subtype = SLOW_SUBTYPE_LACP, 1444 }, 1445 }; 1446 1447 rte_ether_addr_copy(&parnter_system, &src_mac); 1448 rte_ether_addr_copy(&slow_protocol_mac_addr, &dst_mac); 1449 1450 initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac, 1451 RTE_ETHER_TYPE_SLOW, 0, 0); 1452 1453 for (i = 0; i < SLAVE_COUNT; i++) { 1454 lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool); 1455 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *), 1456 &lacpdu, sizeof(lacpdu)); 1457 rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu); 1458 } 1459 1460 retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 1); 1461 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 1462 1463 memset(lacpdu_rx_count, 0, sizeof(lacpdu_rx_count)); 1464 1465 /* Wait for new settings to be applied. */ 1466 for (i = 0; i < 30; ++i) 1467 rte_delay_ms(delay); 1468 1469 FOR_EACH_SLAVE(i, slave) { 1470 retval = rte_eth_bond_8023ad_ext_slowtx( 1471 test_params.bonded_port_id, 1472 slave->port_id, lacp_tx_buf[i]); 1473 TEST_ASSERT_SUCCESS(retval, 1474 "Slave should allow manual LACP xmit"); 1475 } 1476 1477 nb_pkts = bond_tx(NULL, 0); 1478 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly"); 1479 1480 FOR_EACH_SLAVE(i, slave) { 1481 nb_pkts = slave_get_pkts(slave, buf, RTE_DIM(buf)); 1482 TEST_ASSERT_EQUAL(nb_pkts, 1, "found %u packets on slave %d\n", 1483 nb_pkts, i); 1484 slave_put_pkts(slave, buf, nb_pkts); 1485 } 1486 1487 nb_pkts = bond_rx(buf, RTE_DIM(buf)); 1488 free_pkts(buf, nb_pkts); 1489 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly"); 1490 1491 /* wait for the periodic callback to run */ 1492 for (i = 0; i < 30 && all_slaves_done == 0; ++i) { 1493 uint8_t s, total = 0; 1494 1495 rte_delay_ms(delay); 1496 FOR_EACH_SLAVE(s, slave) { 1497 total += lacpdu_rx_count[slave->port_id]; 1498 } 1499 1500 if (total >= SLAVE_COUNT) 1501 all_slaves_done = 1; 1502 } 1503 1504 FOR_EACH_SLAVE(i, slave) { 1505 TEST_ASSERT_EQUAL(lacpdu_rx_count[slave->port_id], 1, 1506 "Slave port %u should have received 1 lacpdu (count=%u)", 1507 slave->port_id, 1508 lacpdu_rx_count[slave->port_id]); 1509 } 1510 1511 retval = remove_slaves_and_stop_bonded_device(); 1512 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 1513 1514 return TEST_SUCCESS; 1515 } 1516 1517 static int 1518 check_environment(void) 1519 { 1520 struct slave_conf *port; 1521 uint8_t i, env_state; 1522 uint16_t slaves[RTE_DIM(test_params.slave_ports)]; 1523 int slaves_count; 1524 1525 env_state = 0; 1526 FOR_EACH_PORT(i, port) { 1527 if (rte_ring_count(port->rx_queue) != 0) 1528 env_state |= 0x01; 1529 1530 if (rte_ring_count(port->tx_queue) != 0) 1531 env_state |= 0x02; 1532 1533 if (port->bonded != 0) 1534 env_state |= 0x04; 1535 1536 if (port->lacp_parnter_state != 0) 1537 env_state |= 0x08; 1538 1539 if (env_state != 0) 1540 break; 1541 } 1542 1543 slaves_count = rte_eth_bond_slaves_get(test_params.bonded_port_id, 1544 slaves, RTE_DIM(slaves)); 1545 1546 if (slaves_count != 0) 1547 env_state |= 0x10; 1548 1549 TEST_ASSERT_EQUAL(env_state, 0, 1550 "Environment not clean (port %u):%s%s%s%s%s", 1551 port->port_id, 1552 env_state & 0x01 ? " slave rx queue not clean" : "", 1553 env_state & 0x02 ? " slave tx queue not clean" : "", 1554 env_state & 0x04 ? " port marked as enslaved" : "", 1555 env_state & 0x80 ? " slave state is not reset" : "", 1556 env_state & 0x10 ? " slave count not equal 0" : "."); 1557 1558 1559 return TEST_SUCCESS; 1560 } 1561 1562 static int 1563 test_mode4_executor(int (*test_func)(void)) 1564 { 1565 struct slave_conf *port; 1566 int test_result; 1567 uint8_t i; 1568 void *pkt; 1569 1570 /* Check if environment is clean. Fail to launch a test if there was 1571 * a critical error before that prevented to reset environment. */ 1572 TEST_ASSERT_SUCCESS(check_environment(), 1573 "Refusing to launch test in dirty environment."); 1574 1575 RTE_VERIFY(test_func != NULL); 1576 test_result = (*test_func)(); 1577 1578 /* If test succeed check if environment wast left in good condition. */ 1579 if (test_result == TEST_SUCCESS) 1580 test_result = check_environment(); 1581 1582 /* Reset environment in case test failed to do that. */ 1583 if (test_result != TEST_SUCCESS) { 1584 TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(), 1585 "Failed to stop bonded device"); 1586 1587 FOR_EACH_PORT(i, port) { 1588 while (rte_ring_count(port->rx_queue) != 0) { 1589 if (rte_ring_dequeue(port->rx_queue, &pkt) == 0) 1590 rte_pktmbuf_free(pkt); 1591 } 1592 1593 while (rte_ring_count(port->tx_queue) != 0) { 1594 if (rte_ring_dequeue(port->tx_queue, &pkt) == 0) 1595 rte_pktmbuf_free(pkt); 1596 } 1597 } 1598 } 1599 1600 return test_result; 1601 } 1602 1603 static int 1604 test_mode4_agg_mode_selection_wrapper(void){ 1605 return test_mode4_executor(&test_mode4_agg_mode_selection); 1606 } 1607 1608 static int 1609 test_mode4_lacp_wrapper(void) 1610 { 1611 return test_mode4_executor(&test_mode4_lacp); 1612 } 1613 1614 static int 1615 test_mode4_marker_wrapper(void) 1616 { 1617 return test_mode4_executor(&test_mode4_marker); 1618 } 1619 1620 static int 1621 test_mode4_rx_wrapper(void) 1622 { 1623 return test_mode4_executor(&test_mode4_rx); 1624 } 1625 1626 static int 1627 test_mode4_tx_burst_wrapper(void) 1628 { 1629 return test_mode4_executor(&test_mode4_tx_burst); 1630 } 1631 1632 static int 1633 test_mode4_expired_wrapper(void) 1634 { 1635 return test_mode4_executor(&test_mode4_expired); 1636 } 1637 1638 static int 1639 test_mode4_ext_ctrl_wrapper(void) 1640 { 1641 return test_mode4_executor(&test_mode4_ext_ctrl); 1642 } 1643 1644 static int 1645 test_mode4_ext_lacp_wrapper(void) 1646 { 1647 return test_mode4_executor(&test_mode4_ext_lacp); 1648 } 1649 1650 static struct unit_test_suite link_bonding_mode4_test_suite = { 1651 .suite_name = "Link Bonding mode 4 Unit Test Suite", 1652 .setup = test_setup, 1653 .teardown = testsuite_teardown, 1654 .unit_test_cases = { 1655 TEST_CASE_NAMED("test_mode4_agg_mode_selection", 1656 test_mode4_agg_mode_selection_wrapper), 1657 TEST_CASE_NAMED("test_mode4_lacp", test_mode4_lacp_wrapper), 1658 TEST_CASE_NAMED("test_mode4_rx", test_mode4_rx_wrapper), 1659 TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper), 1660 TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper), 1661 TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper), 1662 TEST_CASE_NAMED("test_mode4_ext_ctrl", 1663 test_mode4_ext_ctrl_wrapper), 1664 TEST_CASE_NAMED("test_mode4_ext_lacp", 1665 test_mode4_ext_lacp_wrapper), 1666 1667 TEST_CASES_END() /**< NULL terminate unit test array */ 1668 } 1669 }; 1670 1671 static int 1672 test_link_bonding_mode4(void) 1673 { 1674 return unit_test_suite_runner(&link_bonding_mode4_test_suite); 1675 } 1676 1677 REGISTER_TEST_COMMAND(link_bonding_mode4_autotest, test_link_bonding_mode4); 1678