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