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