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 = ETH_MQ_RX_NONE, 111 .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 112 .split_hdr_size = 0, 113 }, 114 .txmode = { 115 .mq_mode = ETH_MQ_TX_NONE, 116 }, 117 .lpbk_mode = 0, 118 }; 119 120 static uint8_t lacpdu_rx_count[RTE_MAX_ETHPORTS] = {0, }; 121 122 #define FOR_EACH(_i, _item, _array, _size) \ 123 for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++) 124 125 /* Macro for iterating over every port that can be used as a slave 126 * in this test. 127 * _i variable used as an index in test_params->slave_ports 128 * _slave pointer to &test_params->slave_ports[_idx] 129 */ 130 #define FOR_EACH_PORT(_i, _port) \ 131 FOR_EACH(_i, _port, test_params.slave_ports, \ 132 RTE_DIM(test_params.slave_ports)) 133 134 /* Macro for iterating over every port that can be used as a slave 135 * in this test and satisfy given condition. 136 * 137 * _i variable used as an index in test_params->slave_ports 138 * _slave pointer to &test_params->slave_ports[_idx] 139 * _condition condition that need to be checked 140 */ 141 #define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \ 142 if (!!(_condition)) 143 144 /* Macro for iterating over every port that is currently a slave of a bonded 145 * device. 146 * _i variable used as an index in test_params->slave_ports 147 * _slave pointer to &test_params->slave_ports[_idx] 148 * */ 149 #define FOR_EACH_SLAVE(_i, _slave) \ 150 FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0) 151 152 /* 153 * Returns packets from slaves TX queue. 154 * slave slave port 155 * buffer for packets 156 * size size of buffer 157 * return number of packets or negative error number 158 */ 159 static int 160 slave_get_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size) 161 { 162 return rte_ring_dequeue_burst(slave->tx_queue, (void **)buf, 163 size, NULL); 164 } 165 166 /* 167 * Injects given packets into slaves RX queue. 168 * slave slave port 169 * buffer for packets 170 * size number of packets to be injected 171 * return number of queued packets or negative error number 172 */ 173 static int 174 slave_put_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size) 175 { 176 return rte_ring_enqueue_burst(slave->rx_queue, (void **)buf, 177 size, NULL); 178 } 179 180 static uint16_t 181 bond_rx(struct rte_mbuf **buf, uint16_t size) 182 { 183 return rte_eth_rx_burst(test_params.bonded_port_id, 0, buf, size); 184 } 185 186 static uint16_t 187 bond_tx(struct rte_mbuf **buf, uint16_t size) 188 { 189 return rte_eth_tx_burst(test_params.bonded_port_id, 0, buf, size); 190 } 191 192 static void 193 free_pkts(struct rte_mbuf **pkts, uint16_t count) 194 { 195 uint16_t i; 196 197 for (i = 0; i < count; i++) { 198 if (pkts[i] != NULL) 199 rte_pktmbuf_free(pkts[i]); 200 } 201 } 202 203 static int 204 configure_ethdev(uint16_t port_id, uint8_t start) 205 { 206 TEST_ASSERT(rte_eth_dev_configure(port_id, 1, 1, &default_pmd_conf) == 0, 207 "Failed to configure device %u", port_id); 208 209 TEST_ASSERT(rte_eth_rx_queue_setup(port_id, 0, RX_RING_SIZE, 210 rte_eth_dev_socket_id(port_id), NULL, test_params.mbuf_pool) == 0, 211 "Failed to setup rx queue."); 212 213 TEST_ASSERT(rte_eth_tx_queue_setup(port_id, 0, TX_RING_SIZE, 214 rte_eth_dev_socket_id(port_id), NULL) == 0, 215 "Failed to setup tx queue."); 216 217 if (start) { 218 TEST_ASSERT(rte_eth_dev_start(port_id) == 0, 219 "Failed to start device (%d).", port_id); 220 } 221 return 0; 222 } 223 224 static int 225 add_slave(struct slave_conf *slave, uint8_t start) 226 { 227 struct rte_ether_addr addr, addr_check; 228 int retval; 229 230 /* Some sanity check */ 231 RTE_VERIFY(test_params.slave_ports <= slave && 232 slave - test_params.slave_ports < (int)RTE_DIM(test_params.slave_ports)); 233 RTE_VERIFY(slave->bonded == 0); 234 RTE_VERIFY(slave->port_id != INVALID_PORT_ID); 235 236 rte_ether_addr_copy(&slave_mac_default, &addr); 237 addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id; 238 239 rte_eth_dev_mac_addr_remove(slave->port_id, &addr); 240 241 TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave->port_id, &addr, 0), 242 "Failed to set slave MAC address"); 243 244 TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bonded_port_id, 245 slave->port_id), 246 "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)", 247 (uint8_t)(slave - test_params.slave_ports), slave->port_id, 248 test_params.bonded_port_id); 249 250 slave->bonded = 1; 251 if (start) { 252 TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave->port_id), 253 "Failed to start slave %u", slave->port_id); 254 } 255 256 retval = rte_eth_macaddr_get(slave->port_id, &addr_check); 257 TEST_ASSERT_SUCCESS(retval, "Failed to get slave mac address: %s", 258 strerror(-retval)); 259 TEST_ASSERT_EQUAL(rte_is_same_ether_addr(&addr, &addr_check), 1, 260 "Slave MAC address is not as expected"); 261 262 RTE_VERIFY(slave->lacp_parnter_state == 0); 263 return 0; 264 } 265 266 static int 267 remove_slave(struct slave_conf *slave) 268 { 269 ptrdiff_t slave_idx = slave - test_params.slave_ports; 270 271 RTE_VERIFY(test_params.slave_ports <= slave && 272 slave_idx < (ptrdiff_t)RTE_DIM(test_params.slave_ports)); 273 274 RTE_VERIFY(slave->bonded == 1); 275 RTE_VERIFY(slave->port_id != INVALID_PORT_ID); 276 277 TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0, 278 "Slave %u tx queue not empty while removing from bonding.", 279 slave->port_id); 280 281 TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0, 282 "Slave %u tx queue not empty while removing from bonding.", 283 slave->port_id); 284 285 TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params.bonded_port_id, 286 slave->port_id), 0, 287 "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)", 288 (uint8_t)slave_idx, slave->port_id, 289 test_params.bonded_port_id); 290 291 slave->bonded = 0; 292 slave->lacp_parnter_state = 0; 293 return 0; 294 } 295 296 static void 297 lacp_recv_cb(uint16_t slave_id, struct rte_mbuf *lacp_pkt) 298 { 299 struct rte_ether_hdr *hdr; 300 struct slow_protocol_frame *slow_hdr; 301 302 RTE_VERIFY(lacp_pkt != NULL); 303 304 hdr = rte_pktmbuf_mtod(lacp_pkt, struct rte_ether_hdr *); 305 RTE_VERIFY(hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW)); 306 307 slow_hdr = rte_pktmbuf_mtod(lacp_pkt, struct slow_protocol_frame *); 308 RTE_VERIFY(slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_LACP); 309 310 lacpdu_rx_count[slave_id]++; 311 rte_pktmbuf_free(lacp_pkt); 312 } 313 314 static int 315 initialize_bonded_device_with_slaves(uint16_t slave_count, uint8_t external_sm) 316 { 317 uint8_t i; 318 int ret; 319 320 RTE_VERIFY(test_params.bonded_port_id != INVALID_PORT_ID); 321 322 for (i = 0; i < slave_count; i++) { 323 TEST_ASSERT_SUCCESS(add_slave(&test_params.slave_ports[i], 1), 324 "Failed to add port %u to bonded device.\n", 325 test_params.slave_ports[i].port_id); 326 } 327 328 /* Reset mode 4 configuration */ 329 rte_eth_bond_8023ad_setup(test_params.bonded_port_id, NULL); 330 ret = rte_eth_promiscuous_disable(test_params.bonded_port_id); 331 TEST_ASSERT_SUCCESS(ret, 332 "Failed disable promiscuous mode for port %d: %s", 333 test_params.bonded_port_id, rte_strerror(-ret)); 334 335 if (external_sm) { 336 struct rte_eth_bond_8023ad_conf conf; 337 338 rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf); 339 conf.slowrx_cb = lacp_recv_cb; 340 rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf); 341 342 } 343 344 TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id), 345 "Failed to start bonded device"); 346 347 return TEST_SUCCESS; 348 } 349 350 static int 351 remove_slaves_and_stop_bonded_device(void) 352 { 353 struct slave_conf *slave; 354 int retval; 355 uint16_t slaves[RTE_MAX_ETHPORTS]; 356 uint16_t i; 357 358 TEST_ASSERT_SUCCESS(rte_eth_dev_stop(test_params.bonded_port_id), 359 "Failed to stop bonded port %u", 360 test_params.bonded_port_id); 361 362 FOR_EACH_SLAVE(i, slave) 363 remove_slave(slave); 364 365 retval = rte_eth_bond_slaves_get(test_params.bonded_port_id, slaves, 366 RTE_DIM(slaves)); 367 368 TEST_ASSERT_EQUAL(retval, 0, 369 "Expected bonded device %u have 0 slaves but returned %d.", 370 test_params.bonded_port_id, retval); 371 372 FOR_EACH_PORT(i, slave) { 373 TEST_ASSERT_SUCCESS(rte_eth_dev_stop(slave->port_id), 374 "Failed to stop bonded port %u", 375 slave->port_id); 376 377 TEST_ASSERT(slave->bonded == 0, 378 "Port id=%u is still marked as enslaved.", slave->port_id); 379 } 380 381 return TEST_SUCCESS; 382 } 383 384 static int 385 test_setup(void) 386 { 387 int retval, nb_mbuf_per_pool; 388 char name[RTE_ETH_NAME_MAX_LEN]; 389 struct slave_conf *port; 390 const uint8_t socket_id = rte_socket_id(); 391 uint16_t i; 392 393 if (test_params.mbuf_pool == NULL) { 394 nb_mbuf_per_pool = TEST_RX_DESC_MAX + DEF_PKT_BURST + 395 TEST_TX_DESC_MAX + MAX_PKT_BURST; 396 test_params.mbuf_pool = rte_pktmbuf_pool_create("TEST_MODE4", 397 nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0, 398 RTE_MBUF_DEFAULT_BUF_SIZE, socket_id); 399 400 TEST_ASSERT(test_params.mbuf_pool != NULL, 401 "rte_mempool_create failed\n"); 402 } 403 404 /* Create / initialize ring eth devs. */ 405 FOR_EACH_PORT(i, port) { 406 port = &test_params.slave_ports[i]; 407 408 if (port->rx_queue == NULL) { 409 retval = snprintf(name, RTE_DIM(name), SLAVE_RX_QUEUE_FMT, i); 410 TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long"); 411 port->rx_queue = rte_ring_create(name, RX_RING_SIZE, socket_id, 0); 412 TEST_ASSERT(port->rx_queue != NULL, 413 "Failed to allocate rx ring '%s': %s", name, 414 rte_strerror(rte_errno)); 415 } 416 417 if (port->tx_queue == NULL) { 418 retval = snprintf(name, RTE_DIM(name), SLAVE_TX_QUEUE_FMT, i); 419 TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long"); 420 port->tx_queue = rte_ring_create(name, TX_RING_SIZE, socket_id, 0); 421 TEST_ASSERT_NOT_NULL(port->tx_queue, 422 "Failed to allocate tx ring '%s': %s", name, 423 rte_strerror(rte_errno)); 424 } 425 426 if (port->port_id == INVALID_PORT_ID) { 427 retval = snprintf(name, RTE_DIM(name), SLAVE_DEV_NAME_FMT, i); 428 TEST_ASSERT(retval < (int)RTE_DIM(name) - 1, "Name too long"); 429 retval = rte_eth_from_rings(name, &port->rx_queue, 1, 430 &port->tx_queue, 1, socket_id); 431 TEST_ASSERT(retval >= 0, 432 "Failed to create ring ethdev '%s'\n", name); 433 434 port->port_id = rte_eth_dev_count_avail() - 1; 435 } 436 437 retval = configure_ethdev(port->port_id, 1); 438 TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n", 439 name); 440 } 441 442 if (test_params.bonded_port_id == INVALID_PORT_ID) { 443 retval = rte_eth_bond_create(BONDED_DEV_NAME, BONDING_MODE_8023AD, 444 socket_id); 445 446 TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s", 447 BONDED_DEV_NAME); 448 449 test_params.bonded_port_id = retval; 450 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bonded_port_id, 0), 451 "Failed to configure bonded ethdev %s", BONDED_DEV_NAME); 452 } else if (rte_eth_bond_mode_get(test_params.bonded_port_id) != 453 BONDING_MODE_8023AD) { 454 TEST_ASSERT(rte_eth_bond_mode_set(test_params.bonded_port_id, 455 BONDING_MODE_8023AD) == 0, 456 "Failed to set ethdev %d to mode %d", 457 test_params.bonded_port_id, BONDING_MODE_8023AD); 458 } 459 460 return 0; 461 } 462 463 static void 464 testsuite_teardown(void) 465 { 466 struct slave_conf *port; 467 uint8_t i; 468 469 /* Only stop ports. 470 * Any cleanup/reset state is done when particular test is 471 * started. */ 472 473 rte_eth_dev_stop(test_params.bonded_port_id); 474 475 FOR_EACH_PORT(i, port) 476 rte_eth_dev_stop(port->port_id); 477 } 478 479 /* 480 * Check if given LACP packet. If it is, make make replay packet to force 481 * COLLECTING state. 482 * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow 483 * frame but not LACP 484 */ 485 static int 486 make_lacp_reply(struct slave_conf *slave, struct rte_mbuf *pkt) 487 { 488 struct rte_ether_hdr *hdr; 489 struct slow_protocol_frame *slow_hdr; 490 struct lacpdu *lacp; 491 492 /* look for LACP */ 493 hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 494 if (hdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW)) 495 return 1; 496 497 slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *); 498 /* ignore packets of other types */ 499 if (slow_hdr->slow_protocol.subtype != SLOW_SUBTYPE_LACP) 500 return 2; 501 502 slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *); 503 504 /* Change source address to partner address */ 505 rte_ether_addr_copy(&parnter_mac_default, &slow_hdr->eth_hdr.s_addr); 506 slow_hdr->eth_hdr.s_addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = 507 slave->port_id; 508 509 lacp = (struct lacpdu *) &slow_hdr->slow_protocol; 510 /* Save last received state */ 511 slave->lacp_parnter_state = lacp->actor.state; 512 /* Change it into LACP replay by matching parameters. */ 513 memcpy(&lacp->partner.port_params, &lacp->actor.port_params, 514 sizeof(struct port_params)); 515 516 lacp->partner.state = lacp->actor.state; 517 518 rte_ether_addr_copy(&parnter_system, &lacp->actor.port_params.system); 519 lacp->actor.state = STATE_LACP_ACTIVE | 520 STATE_SYNCHRONIZATION | 521 STATE_AGGREGATION | 522 STATE_COLLECTING | 523 STATE_DISTRIBUTING; 524 525 return 0; 526 } 527 528 /* 529 * Reads packets from given slave, search for LACP packet and reply them. 530 * 531 * Receives burst of packets from slave. Looks for LACP packet. Drops 532 * all other packets. Prepares response LACP and sends it back. 533 * 534 * return number of LACP received and replied, -1 on error. 535 */ 536 static int 537 bond_handshake_reply(struct slave_conf *slave) 538 { 539 int retval; 540 struct rte_mbuf *rx_buf[MAX_PKT_BURST]; 541 struct rte_mbuf *lacp_tx_buf[MAX_PKT_BURST]; 542 uint16_t lacp_tx_buf_cnt = 0, i; 543 544 retval = slave_get_pkts(slave, rx_buf, RTE_DIM(rx_buf)); 545 TEST_ASSERT(retval >= 0, "Getting slave %u packets failed.", 546 slave->port_id); 547 548 for (i = 0; i < (uint16_t)retval; i++) { 549 if (make_lacp_reply(slave, rx_buf[i]) == 0) { 550 /* reply with actor's LACP */ 551 lacp_tx_buf[lacp_tx_buf_cnt++] = rx_buf[i]; 552 } else 553 rte_pktmbuf_free(rx_buf[i]); 554 } 555 556 if (lacp_tx_buf_cnt == 0) 557 return 0; 558 559 retval = slave_put_pkts(slave, lacp_tx_buf, lacp_tx_buf_cnt); 560 if (retval <= lacp_tx_buf_cnt) { 561 /* retval might be negative */ 562 for (i = RTE_MAX(0, retval); retval < lacp_tx_buf_cnt; retval++) 563 rte_pktmbuf_free(lacp_tx_buf[i]); 564 } 565 566 TEST_ASSERT_EQUAL(retval, lacp_tx_buf_cnt, 567 "Failed to equeue lacp packets into slave %u tx queue.", 568 slave->port_id); 569 570 return lacp_tx_buf_cnt; 571 } 572 573 /* 574 * Function check if given slave tx queue contains packets that make mode 4 575 * handshake complete. It will drain slave queue. 576 * return 0 if handshake not completed, 1 if handshake was complete, 577 */ 578 static int 579 bond_handshake_done(struct slave_conf *slave) 580 { 581 const uint8_t expected_state = STATE_LACP_ACTIVE | STATE_SYNCHRONIZATION | 582 STATE_AGGREGATION | STATE_COLLECTING | STATE_DISTRIBUTING; 583 584 return slave->lacp_parnter_state == expected_state; 585 } 586 587 static unsigned 588 bond_get_update_timeout_ms(void) 589 { 590 struct rte_eth_bond_8023ad_conf conf; 591 592 if (rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf) < 0) { 593 RTE_LOG(DEBUG, EAL, "Failed to get bonding configuration: " 594 "%s at %d\n", __func__, __LINE__); 595 RTE_TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); 596 return 0; 597 } 598 599 return conf.update_timeout_ms; 600 } 601 602 /* 603 * Exchanges LACP packets with partner to achieve dynamic port configuration. 604 * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise. 605 */ 606 static int 607 bond_handshake(void) 608 { 609 struct slave_conf *slave; 610 struct rte_mbuf *buf[MAX_PKT_BURST]; 611 uint16_t nb_pkts; 612 uint8_t all_slaves_done, i, j; 613 uint8_t status[RTE_DIM(test_params.slave_ports)] = { 0 }; 614 const unsigned delay = bond_get_update_timeout_ms(); 615 616 /* Exchange LACP frames */ 617 all_slaves_done = 0; 618 for (i = 0; i < 30 && all_slaves_done == 0; ++i) { 619 rte_delay_ms(delay); 620 621 all_slaves_done = 1; 622 FOR_EACH_SLAVE(j, slave) { 623 /* If response already send, skip slave */ 624 if (status[j] != 0) 625 continue; 626 627 if (bond_handshake_reply(slave) < 0) { 628 all_slaves_done = 0; 629 break; 630 } 631 632 status[j] = bond_handshake_done(slave); 633 if (status[j] == 0) 634 all_slaves_done = 0; 635 } 636 637 nb_pkts = bond_tx(NULL, 0); 638 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly"); 639 640 nb_pkts = bond_rx(buf, RTE_DIM(buf)); 641 free_pkts(buf, nb_pkts); 642 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly"); 643 } 644 /* If response didn't send - report failure */ 645 TEST_ASSERT_EQUAL(all_slaves_done, 1, "Bond handshake failed\n"); 646 647 /* If flags doesn't match - report failure */ 648 return all_slaves_done == 1 ? TEST_SUCCESS : TEST_FAILED; 649 } 650 651 #define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports) 652 static int 653 test_mode4_lacp(void) 654 { 655 int retval; 656 657 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 658 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 659 660 /* Test LACP handshake function */ 661 retval = bond_handshake(); 662 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 663 664 retval = remove_slaves_and_stop_bonded_device(); 665 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 666 667 return TEST_SUCCESS; 668 } 669 static int 670 test_mode4_agg_mode_selection(void) 671 { 672 int retval; 673 /* Test and verify for Stable mode */ 674 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 675 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 676 677 678 retval = rte_eth_bond_8023ad_agg_selection_set( 679 test_params.bonded_port_id, AGG_STABLE); 680 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bond aggregation mode"); 681 retval = bond_handshake(); 682 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 683 684 685 retval = rte_eth_bond_8023ad_agg_selection_get( 686 test_params.bonded_port_id); 687 TEST_ASSERT_EQUAL(retval, AGG_STABLE, 688 "Wrong agg mode received from bonding device"); 689 690 retval = remove_slaves_and_stop_bonded_device(); 691 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 692 693 694 /* test and verify for Bandwidth mode */ 695 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 696 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 697 698 699 retval = rte_eth_bond_8023ad_agg_selection_set( 700 test_params.bonded_port_id, 701 AGG_BANDWIDTH); 702 TEST_ASSERT_SUCCESS(retval, 703 "Failed to initialize bond aggregation mode"); 704 retval = bond_handshake(); 705 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 706 707 retval = rte_eth_bond_8023ad_agg_selection_get( 708 test_params.bonded_port_id); 709 TEST_ASSERT_EQUAL(retval, AGG_BANDWIDTH, 710 "Wrong agg mode received from bonding device"); 711 712 retval = remove_slaves_and_stop_bonded_device(); 713 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 714 715 /* test and verify selection for count mode */ 716 retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0); 717 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 718 719 720 retval = rte_eth_bond_8023ad_agg_selection_set( 721 test_params.bonded_port_id, AGG_COUNT); 722 TEST_ASSERT_SUCCESS(retval, 723 "Failed to initialize bond aggregation mode"); 724 retval = bond_handshake(); 725 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 726 727 retval = rte_eth_bond_8023ad_agg_selection_get( 728 test_params.bonded_port_id); 729 TEST_ASSERT_EQUAL(retval, AGG_COUNT, 730 "Wrong agg mode received from bonding device"); 731 732 retval = remove_slaves_and_stop_bonded_device(); 733 TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); 734 735 return TEST_SUCCESS; 736 } 737 738 static int 739 generate_packets(struct rte_ether_addr *src_mac, 740 struct rte_ether_addr *dst_mac, uint16_t count, struct rte_mbuf **buf) 741 { 742 uint16_t pktlen = PACKET_BURST_GEN_PKT_LEN; 743 uint8_t vlan_enable = 0; 744 uint16_t vlan_id = 0; 745 uint8_t ip4_type = 1; /* 0 - ipv6 */ 746 747 uint16_t src_port = 10, dst_port = 20; 748 749 uint32_t ip_src[4] = { [0 ... 2] = 0xDEADBEEF, [3] = RTE_IPV4(192, 168, 0, 1) }; 750 uint32_t ip_dst[4] = { [0 ... 2] = 0xFEEDFACE, [3] = RTE_IPV4(192, 168, 0, 2) }; 751 752 struct rte_ether_hdr pkt_eth_hdr; 753 struct rte_udp_hdr pkt_udp_hdr; 754 union { 755 struct rte_ipv4_hdr v4; 756 struct rte_ipv6_hdr v6; 757 } pkt_ip_hdr; 758 759 int retval; 760 761 initialize_eth_header(&pkt_eth_hdr, src_mac, dst_mac, ip4_type, 762 vlan_enable, vlan_id); 763 764 if (ip4_type) 765 initialize_ipv4_header(&pkt_ip_hdr.v4, ip_src[3], ip_dst[3], pktlen); 766 else 767 initialize_ipv6_header(&pkt_ip_hdr.v6, (uint8_t *)ip_src, 768 (uint8_t *)&ip_dst, pktlen); 769 770 initialize_udp_header(&pkt_udp_hdr, src_port, dst_port, 16); 771 772 retval = generate_packet_burst(test_params.mbuf_pool, buf, 773 &pkt_eth_hdr, vlan_enable, &pkt_ip_hdr, 1, &pkt_udp_hdr, 774 count, pktlen, 1); 775 776 if (retval > 0 && retval != count) 777 free_pkts(&buf[count - retval], retval); 778 779 TEST_ASSERT_EQUAL(retval, count, "Failed to generate %u packets", 780 count); 781 782 return count; 783 } 784 785 static int 786 generate_and_put_packets(struct slave_conf *slave, 787 struct rte_ether_addr *src_mac, 788 struct rte_ether_addr *dst_mac, uint16_t count) 789 { 790 struct rte_mbuf *pkts[MAX_PKT_BURST]; 791 int retval; 792 793 retval = generate_packets(src_mac, dst_mac, count, pkts); 794 if (retval != (int)count) 795 return retval; 796 797 retval = slave_put_pkts(slave, pkts, count); 798 if (retval > 0 && retval != count) 799 free_pkts(&pkts[retval], count - retval); 800 801 TEST_ASSERT_EQUAL(retval, count, 802 "Failed to enqueue packets into slave %u RX queue", slave->port_id); 803 804 return TEST_SUCCESS; 805 } 806 807 static int 808 test_mode4_rx(void) 809 { 810 struct slave_conf *slave; 811 uint16_t i, j; 812 813 uint16_t expected_pkts_cnt; 814 struct rte_mbuf *pkts[MAX_PKT_BURST]; 815 int retval; 816 unsigned delay; 817 818 struct rte_ether_hdr *hdr; 819 820 struct rte_ether_addr src_mac = { 821 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; 822 struct rte_ether_addr dst_mac; 823 struct rte_ether_addr bonded_mac; 824 825 retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT, 826 0); 827 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 828 829 retval = bond_handshake(); 830 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 831 832 retval = rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac); 833 TEST_ASSERT_SUCCESS(retval, "Failed to get mac address: %s", 834 strerror(-retval)); 835 rte_ether_addr_copy(&bonded_mac, &dst_mac); 836 837 /* Assert that dst address is not bonding address. Do not set the 838 * least significant bit of the zero byte as this would create a 839 * multicast address. 840 */ 841 dst_mac.addr_bytes[0] += 2; 842 843 /* First try with promiscuous mode enabled. 844 * Add 2 packets to each slave. First with bonding MAC address, second with 845 * different. Check if we received all of them. */ 846 retval = rte_eth_promiscuous_enable(test_params.bonded_port_id); 847 TEST_ASSERT_SUCCESS(retval, 848 "Failed to enable promiscuous mode for port %d: %s", 849 test_params.bonded_port_id, rte_strerror(-retval)); 850 851 expected_pkts_cnt = 0; 852 FOR_EACH_SLAVE(i, slave) { 853 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); 854 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 855 slave->port_id); 856 857 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); 858 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 859 slave->port_id); 860 861 /* Expect 2 packets per slave */ 862 expected_pkts_cnt += 2; 863 } 864 865 retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, 866 RTE_DIM(pkts)); 867 868 if (retval == expected_pkts_cnt) { 869 int cnt[2] = { 0, 0 }; 870 871 for (i = 0; i < expected_pkts_cnt; i++) { 872 hdr = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); 873 cnt[rte_is_same_ether_addr(&hdr->d_addr, 874 &bonded_mac)]++; 875 } 876 877 free_pkts(pkts, expected_pkts_cnt); 878 879 /* For division by 2 expected_pkts_cnt must be even */ 880 RTE_VERIFY((expected_pkts_cnt & 1) == 0); 881 TEST_ASSERT(cnt[0] == expected_pkts_cnt / 2 && 882 cnt[1] == expected_pkts_cnt / 2, 883 "Expected %u packets with the same MAC and %u with different but " 884 "got %u with the same and %u with different MAC", 885 expected_pkts_cnt / 2, expected_pkts_cnt / 2, cnt[1], cnt[0]); 886 } else if (retval > 0) 887 free_pkts(pkts, retval); 888 889 TEST_ASSERT_EQUAL(retval, expected_pkts_cnt, 890 "Expected %u packets but received only %d", expected_pkts_cnt, retval); 891 892 /* Now, disable promiscuous mode. When promiscuous mode is disabled we 893 * expect to receive only packets that are directed to bonding port. */ 894 retval = rte_eth_promiscuous_disable(test_params.bonded_port_id); 895 TEST_ASSERT_SUCCESS(retval, 896 "Failed to disable promiscuous mode for port %d: %s", 897 test_params.bonded_port_id, rte_strerror(-retval)); 898 899 expected_pkts_cnt = 0; 900 FOR_EACH_SLAVE(i, slave) { 901 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); 902 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 903 slave->port_id); 904 905 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); 906 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", 907 slave->port_id); 908 909 /* Expect only one packet per slave */ 910 expected_pkts_cnt += 1; 911 } 912 913 retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, 914 RTE_DIM(pkts)); 915 916 if (retval == expected_pkts_cnt) { 917 int eq_cnt = 0; 918 919 for (i = 0; i < expected_pkts_cnt; i++) { 920 hdr = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); 921 eq_cnt += rte_is_same_ether_addr(&hdr->d_addr, 922 &bonded_mac); 923 } 924 925 free_pkts(pkts, expected_pkts_cnt); 926 TEST_ASSERT_EQUAL(eq_cnt, expected_pkts_cnt, "Packet address mismatch"); 927 } else if (retval > 0) 928 free_pkts(pkts, retval); 929 930 TEST_ASSERT_EQUAL(retval, expected_pkts_cnt, 931 "Expected %u packets but received only %d", expected_pkts_cnt, retval); 932 933 /* Link down test: simulate link down for first slave. */ 934 delay = bond_get_update_timeout_ms(); 935 936 uint8_t slave_down_id = INVALID_PORT_ID; 937 938 /* Find first slave and make link down on it*/ 939 FOR_EACH_SLAVE(i, slave) { 940 rte_eth_dev_set_link_down(slave->port_id); 941 slave_down_id = slave->port_id; 942 break; 943 } 944 945 RTE_VERIFY(slave_down_id != INVALID_PORT_ID); 946 947 /* Give some time to rearrange bonding */ 948 for (i = 0; i < 3; i++) { 949 rte_delay_ms(delay); 950 bond_handshake(); 951 } 952 953 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed"); 954 955 /* Put packet to each slave */ 956 FOR_EACH_SLAVE(i, slave) { 957 void *pkt = NULL; 958 959 dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id; 960 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); 961 TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst."); 962 963 src_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id; 964 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); 965 TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst."); 966 967 retval = bond_rx(pkts, RTE_DIM(pkts)); 968 969 /* Clean anything */ 970 if (retval > 0) 971 free_pkts(pkts, retval); 972 973 while (rte_ring_dequeue(slave->rx_queue, (void **)&pkt) == 0) 974 rte_pktmbuf_free(pkt); 975 976 if (slave_down_id == slave->port_id) 977 TEST_ASSERT_EQUAL(retval, 0, "Packets received unexpectedly."); 978 else 979 TEST_ASSERT_NOT_EQUAL(retval, 0, 980 "Expected to receive some packets on slave %u.", 981 slave->port_id); 982 rte_eth_dev_start(slave->port_id); 983 984 for (j = 0; j < 5; j++) { 985 TEST_ASSERT(bond_handshake_reply(slave) >= 0, 986 "Handshake after link up"); 987 988 if (bond_handshake_done(slave) == 1) 989 break; 990 } 991 992 TEST_ASSERT(j < 5, "Failed to aggregate slave after link up"); 993 } 994 995 remove_slaves_and_stop_bonded_device(); 996 return TEST_SUCCESS; 997 } 998 999 static int 1000 test_mode4_tx_burst(void) 1001 { 1002 struct slave_conf *slave; 1003 uint16_t i, j; 1004 1005 uint16_t exp_pkts_cnt, pkts_cnt = 0; 1006 struct rte_mbuf *pkts[MAX_PKT_BURST]; 1007 int retval; 1008 unsigned delay; 1009 1010 struct rte_ether_addr dst_mac = { 1011 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; 1012 struct rte_ether_addr bonded_mac; 1013 1014 retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0); 1015 TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); 1016 1017 retval = bond_handshake(); 1018 TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); 1019 1020 retval = rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac); 1021 TEST_ASSERT_SUCCESS(retval, "Failed to get mac address: %s", 1022 strerror(-retval)); 1023 /* Prepare burst */ 1024 for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) { 1025 dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = pkts_cnt; 1026 retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]); 1027 1028 if (retval != 1) 1029 free_pkts(pkts, pkts_cnt); 1030 1031 TEST_ASSERT_EQUAL(retval, 1, "Failed to generate packet %u", pkts_cnt); 1032 } 1033 exp_pkts_cnt = pkts_cnt; 1034 1035 /* Transmit packets on bonded device */ 1036 retval = bond_tx(pkts, pkts_cnt); 1037 if (retval > 0 && retval < pkts_cnt) 1038 free_pkts(&pkts[retval], pkts_cnt - retval); 1039 1040 TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed"); 1041 1042 /* Check if packets were transmitted properly. Every slave should have 1043 * at least one packet, and sum must match. Under normal operation 1044 * there should be no LACP nor MARKER frames. */ 1045 pkts_cnt = 0; 1046 FOR_EACH_SLAVE(i, slave) { 1047 uint16_t normal_cnt, slow_cnt; 1048 1049 retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts)); 1050 normal_cnt = 0; 1051 slow_cnt = 0; 1052 1053 for (j = 0; j < retval; j++) { 1054 if (make_lacp_reply(slave, pkts[j]) == 1) 1055 normal_cnt++; 1056 else 1057 slow_cnt++; 1058 } 1059 1060 free_pkts(pkts, normal_cnt + slow_cnt); 1061 TEST_ASSERT_EQUAL(slow_cnt, 0, 1062 "slave %u unexpectedly transmitted %d SLOW packets", slave->port_id, 1063 slow_cnt); 1064 1065 TEST_ASSERT_NOT_EQUAL(normal_cnt, 0, 1066 "slave %u did not transmitted any packets", slave->port_id); 1067 1068 pkts_cnt += normal_cnt; 1069 } 1070 1071 TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt, 1072 "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt); 1073 1074 /* Link down test: 1075 * simulate link down for first slave. */ 1076 delay = bond_get_update_timeout_ms(); 1077 1078 uint8_t slave_down_id = INVALID_PORT_ID; 1079 1080 FOR_EACH_SLAVE(i, slave) { 1081 rte_eth_dev_set_link_down(slave->port_id); 1082 slave_down_id = slave->port_id; 1083 break; 1084 } 1085 1086 RTE_VERIFY(slave_down_id != INVALID_PORT_ID); 1087 1088 /* Give some time to rearrange bonding. */ 1089 for (i = 0; i < 3; i++) { 1090 bond_handshake(); 1091 rte_delay_ms(delay); 1092 } 1093 1094 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed"); 1095 1096 /* Prepare burst. */ 1097 for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) { 1098 dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = pkts_cnt; 1099 retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]); 1100 1101 if (retval != 1) 1102 free_pkts(pkts, pkts_cnt); 1103 1104 TEST_ASSERT_EQUAL(retval, 1, "Failed to generate test packet %u", 1105 pkts_cnt); 1106 } 1107 exp_pkts_cnt = pkts_cnt; 1108 1109 /* Transmit packets on bonded device. */ 1110 retval = bond_tx(pkts, pkts_cnt); 1111 if (retval > 0 && retval < pkts_cnt) 1112 free_pkts(&pkts[retval], pkts_cnt - retval); 1113 1114 TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed"); 1115 1116 /* Check if packets was transmitted properly. Every slave should have 1117 * at least one packet, and sum must match. Under normal operation 1118 * there should be no LACP nor MARKER frames. */ 1119 pkts_cnt = 0; 1120 FOR_EACH_SLAVE(i, slave) { 1121 uint16_t normal_cnt, slow_cnt; 1122 1123 retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts)); 1124 normal_cnt = 0; 1125 slow_cnt = 0; 1126 1127 for (j = 0; j < retval; j++) { 1128 if (make_lacp_reply(slave, pkts[j]) == 1) 1129 normal_cnt++; 1130 else 1131 slow_cnt++; 1132 } 1133 1134 free_pkts(pkts, normal_cnt + slow_cnt); 1135 1136 if (slave_down_id == slave->port_id) { 1137 TEST_ASSERT_EQUAL(normal_cnt + slow_cnt, 0, 1138 "slave %u enexpectedly transmitted %u packets", 1139 normal_cnt + slow_cnt, slave->port_id); 1140 } else { 1141 TEST_ASSERT_EQUAL(slow_cnt, 0, 1142 "slave %u unexpectedly transmitted %d SLOW packets", 1143 slave->port_id, slow_cnt); 1144 1145 TEST_ASSERT_NOT_EQUAL(normal_cnt, 0, 1146 "slave %u did not transmitted any packets", slave->port_id); 1147 } 1148 1149 pkts_cnt += normal_cnt; 1150 } 1151 1152 TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt, 1153 "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt); 1154 1155 return remove_slaves_and_stop_bonded_device(); 1156 } 1157 1158 static void 1159 init_marker(struct rte_mbuf *pkt, struct slave_conf *slave) 1160 { 1161 struct marker_header *marker_hdr = rte_pktmbuf_mtod(pkt, 1162 struct marker_header *); 1163 1164 /* Copy multicast destination address */ 1165 rte_ether_addr_copy(&slow_protocol_mac_addr, 1166 &marker_hdr->eth_hdr.d_addr); 1167 1168 /* Init source address */ 1169 rte_ether_addr_copy(&parnter_mac_default, &marker_hdr->eth_hdr.s_addr); 1170 marker_hdr->eth_hdr.s_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