1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015 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 #include <rte_bus_vdev.h> 23 24 #include <rte_string_fns.h> 25 #include <rte_errno.h> 26 #include <rte_eth_bond.h> 27 28 #include "test.h" 29 30 #define MEMBER_COUNT (4) 31 32 #define RXTX_RING_SIZE 1024 33 #define RXTX_QUEUE_COUNT 4 34 35 #define BONDING_DEV_NAME ("net_bonding_rss") 36 37 #define MEMBER_DEV_NAME_FMT ("net_null%d") 38 #define MEMBER_RXTX_QUEUE_FMT ("rssconf_member%d_q%d") 39 40 #define NUM_MBUFS 8191 41 #define MBUF_SIZE (1600 + RTE_PKTMBUF_HEADROOM) 42 #define MBUF_CACHE_SIZE 250 43 #define BURST_SIZE 32 44 45 #define INVALID_SOCKET_ID (-1) 46 #define INVALID_PORT_ID (0xFF) 47 #define INVALID_BONDING_MODE (-1) 48 49 struct member_conf { 50 uint16_t port_id; 51 struct rte_eth_dev_info dev_info; 52 53 struct rte_eth_rss_conf rss_conf; 54 uint8_t rss_key[40]; 55 struct rte_eth_rss_reta_entry64 reta_conf[512 / RTE_ETH_RETA_GROUP_SIZE]; 56 57 uint8_t is_member; 58 struct rte_ring *rxtx_queue[RXTX_QUEUE_COUNT]; 59 }; 60 61 struct link_bonding_rssconf_unittest_params { 62 uint8_t bond_port_id; 63 struct rte_eth_dev_info bond_dev_info; 64 struct rte_eth_rss_reta_entry64 bond_reta_conf[512 / RTE_ETH_RETA_GROUP_SIZE]; 65 struct member_conf member_ports[MEMBER_COUNT]; 66 67 struct rte_mempool *mbuf_pool; 68 }; 69 70 static struct link_bonding_rssconf_unittest_params test_params = { 71 .bond_port_id = INVALID_PORT_ID, 72 .member_ports = { 73 [0 ... MEMBER_COUNT - 1] = { .port_id = INVALID_PORT_ID, .is_member = 0} 74 }, 75 .mbuf_pool = NULL, 76 }; 77 78 /** 79 * Default port configuration with RSS turned off 80 */ 81 static struct rte_eth_conf default_pmd_conf = { 82 .rxmode = { 83 .mq_mode = RTE_ETH_MQ_RX_NONE, 84 }, 85 .txmode = { 86 .mq_mode = RTE_ETH_MQ_TX_NONE, 87 }, 88 .lpbk_mode = 0, 89 }; 90 91 static struct rte_eth_conf rss_pmd_conf = { 92 .rxmode = { 93 .mq_mode = RTE_ETH_MQ_RX_RSS, 94 }, 95 .txmode = { 96 .mq_mode = RTE_ETH_MQ_TX_NONE, 97 }, 98 .rx_adv_conf = { 99 .rss_conf = { 100 .rss_key = NULL, 101 .rss_hf = RTE_ETH_RSS_IPV6, 102 }, 103 }, 104 .lpbk_mode = 0, 105 }; 106 107 #define FOR_EACH(_i, _item, _array, _size) \ 108 for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++) 109 110 /* Macro for iterating over every port that can be used as a member 111 * in this test. 112 * _i variable used as an index in test_params->member_ports 113 * _member pointer to &test_params->member_ports[_idx] 114 */ 115 #define FOR_EACH_PORT(_i, _port) \ 116 FOR_EACH(_i, _port, test_params.member_ports, \ 117 RTE_DIM(test_params.member_ports)) 118 119 static int 120 configure_ethdev(uint16_t port_id, struct rte_eth_conf *eth_conf, 121 uint8_t start) 122 { 123 int rxq, txq; 124 125 TEST_ASSERT(rte_eth_dev_configure(port_id, RXTX_QUEUE_COUNT, 126 RXTX_QUEUE_COUNT, eth_conf) == 0, "Failed to configure device %u", 127 port_id); 128 129 int ret = rte_eth_dev_set_mtu(port_id, 1550); 130 RTE_TEST_ASSERT(ret == 0 || ret == -ENOTSUP, 131 "rte_eth_dev_set_mtu for port %d failed", port_id); 132 133 for (rxq = 0; rxq < RXTX_QUEUE_COUNT; rxq++) { 134 TEST_ASSERT(rte_eth_rx_queue_setup(port_id, rxq, RXTX_RING_SIZE, 135 rte_eth_dev_socket_id(port_id), NULL, 136 test_params.mbuf_pool) == 0, "Failed to setup rx queue."); 137 } 138 139 for (txq = 0; txq < RXTX_QUEUE_COUNT; txq++) { 140 TEST_ASSERT(rte_eth_tx_queue_setup(port_id, txq, RXTX_RING_SIZE, 141 rte_eth_dev_socket_id(port_id), NULL) == 0, 142 "Failed to setup tx queue."); 143 } 144 145 if (start) { 146 TEST_ASSERT(rte_eth_dev_start(port_id) == 0, 147 "Failed to start device (%d).", port_id); 148 } 149 150 return 0; 151 } 152 153 /** 154 * Remove all members from bonding 155 */ 156 static int 157 remove_members(void) 158 { 159 unsigned n; 160 struct member_conf *port; 161 162 FOR_EACH_PORT(n, port) { 163 port = &test_params.member_ports[n]; 164 if (port->is_member) { 165 TEST_ASSERT_SUCCESS(rte_eth_bond_member_remove( 166 test_params.bond_port_id, port->port_id), 167 "Cannot remove member %d from bonding", port->port_id); 168 port->is_member = 0; 169 } 170 } 171 172 return 0; 173 } 174 175 static int 176 remove_members_and_stop_bonding_device(void) 177 { 178 TEST_ASSERT_SUCCESS(remove_members(), "Removing members"); 179 TEST_ASSERT_SUCCESS(rte_eth_dev_stop(test_params.bond_port_id), 180 "Failed to stop port %u", test_params.bond_port_id); 181 return TEST_SUCCESS; 182 } 183 184 /** 185 * Add all members to bonding 186 */ 187 static int 188 bond_members(void) 189 { 190 unsigned n; 191 struct member_conf *port; 192 193 FOR_EACH_PORT(n, port) { 194 port = &test_params.member_ports[n]; 195 if (!port->is_member) { 196 TEST_ASSERT_SUCCESS(rte_eth_bond_member_add(test_params.bond_port_id, 197 port->port_id), "Cannot attach member %d to the bonding", 198 port->port_id); 199 port->is_member = 1; 200 } 201 } 202 203 return 0; 204 } 205 206 /** 207 * Set all RETA values in port_id to value 208 */ 209 static int 210 reta_set(uint16_t port_id, uint8_t value, int reta_size) 211 { 212 struct rte_eth_rss_reta_entry64 reta_conf[512/RTE_ETH_RETA_GROUP_SIZE]; 213 int i, j; 214 215 for (i = 0; i < reta_size / RTE_ETH_RETA_GROUP_SIZE; i++) { 216 /* select all fields to set */ 217 reta_conf[i].mask = ~0LL; 218 for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) 219 reta_conf[i].reta[j] = value; 220 } 221 222 return rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size); 223 } 224 225 /** 226 * Check if members RETA is synchronized with bonding port. Returns 1 if member 227 * port is synced with bonding port. 228 */ 229 static int 230 reta_check_synced(struct member_conf *port) 231 { 232 unsigned i; 233 234 for (i = 0; i < test_params.bond_dev_info.reta_size; 235 i++) { 236 237 int index = i / RTE_ETH_RETA_GROUP_SIZE; 238 int shift = i % RTE_ETH_RETA_GROUP_SIZE; 239 240 if (port->reta_conf[index].reta[shift] != 241 test_params.bond_reta_conf[index].reta[shift]) 242 return 0; 243 244 } 245 246 return 1; 247 } 248 249 /** 250 * Fetch bonding ports RETA 251 */ 252 static int 253 bond_reta_fetch(void) { 254 unsigned j; 255 256 for (j = 0; j < test_params.bond_dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE; 257 j++) 258 test_params.bond_reta_conf[j].mask = ~0LL; 259 260 TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(test_params.bond_port_id, 261 test_params.bond_reta_conf, test_params.bond_dev_info.reta_size), 262 "Cannot take bonding ports RSS configuration"); 263 return 0; 264 } 265 266 /** 267 * Fetch members RETA 268 */ 269 static int 270 member_reta_fetch(struct member_conf *port) { 271 unsigned j; 272 273 for (j = 0; j < port->dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE; j++) 274 port->reta_conf[j].mask = ~0LL; 275 276 TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(port->port_id, 277 port->reta_conf, port->dev_info.reta_size), 278 "Cannot take bonding ports RSS configuration"); 279 return 0; 280 } 281 282 /** 283 * Remove and add member to check if members configuration is synced with 284 * the bonding ports values after adding new member. 285 */ 286 static int 287 member_remove_and_add(void) 288 { 289 struct member_conf *port = &(test_params.member_ports[0]); 290 291 /* 1. Remove first member from bonding */ 292 TEST_ASSERT_SUCCESS(rte_eth_bond_member_remove(test_params.bond_port_id, 293 port->port_id), "Cannot remove member #d from bonding"); 294 295 /* 2. Change removed (ex-)member and bonding configuration to different 296 * values 297 */ 298 reta_set(test_params.bond_port_id, 1, test_params.bond_dev_info.reta_size); 299 bond_reta_fetch(); 300 301 reta_set(port->port_id, 2, port->dev_info.reta_size); 302 member_reta_fetch(port); 303 304 TEST_ASSERT(reta_check_synced(port) == 0, 305 "Removed member didn't should be synchronized with bonding port"); 306 307 /* 3. Add (ex-)member and check if configuration changed*/ 308 TEST_ASSERT_SUCCESS(rte_eth_bond_member_add(test_params.bond_port_id, 309 port->port_id), "Cannot add member"); 310 311 bond_reta_fetch(); 312 member_reta_fetch(port); 313 314 return reta_check_synced(port); 315 } 316 317 /** 318 * Test configuration propagation over members. 319 */ 320 static int 321 test_propagate(void) 322 { 323 unsigned i; 324 uint8_t n; 325 struct member_conf *port; 326 uint8_t bond_rss_key[40]; 327 struct rte_eth_rss_conf bond_rss_conf = {0}; 328 329 int retval = 0; 330 uint64_t rss_hf = 0; 331 uint64_t default_rss_hf = 0; 332 333 retval = rte_eth_dev_info_get(test_params.bond_port_id, 334 &test_params.bond_dev_info); 335 TEST_ASSERT((retval == 0), 336 "Error during getting device (port %u) info: %s\n", 337 test_params.bond_port_id, strerror(-retval)); 338 339 /* 340 * Test hash function propagation 341 */ 342 for (i = 0; i < sizeof(test_params.bond_dev_info.flow_type_rss_offloads)*8; 343 i++) { 344 345 rss_hf = test_params.bond_dev_info.flow_type_rss_offloads & (1<<i); 346 if (rss_hf) { 347 bond_rss_conf.rss_key = NULL; 348 bond_rss_conf.rss_hf = rss_hf; 349 350 retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 351 &bond_rss_conf); 352 TEST_ASSERT_SUCCESS(retval, "Cannot set members hash function"); 353 354 FOR_EACH_PORT(n, port) { 355 port = &test_params.member_ports[n]; 356 357 retval = rte_eth_dev_rss_hash_conf_get(port->port_id, 358 &port->rss_conf); 359 TEST_ASSERT_SUCCESS(retval, 360 "Cannot take members RSS configuration"); 361 362 TEST_ASSERT(port->rss_conf.rss_hf == rss_hf, 363 "Hash function not propagated for member %d", 364 port->port_id); 365 } 366 367 default_rss_hf = rss_hf; 368 } 369 370 } 371 372 /* 373 * Test key propagation 374 */ 375 for (i = 1; i < 10; i++) { 376 377 /* Set all keys to zero */ 378 FOR_EACH_PORT(n, port) { 379 port = &test_params.member_ports[n]; 380 memset(port->rss_conf.rss_key, 0, 40); 381 retval = rte_eth_dev_rss_hash_update(port->port_id, 382 &port->rss_conf); 383 TEST_ASSERT_SUCCESS(retval, "Cannot set members RSS keys"); 384 } 385 386 memset(bond_rss_key, i, sizeof(bond_rss_key)); 387 bond_rss_conf.rss_hf = default_rss_hf, 388 bond_rss_conf.rss_key = bond_rss_key; 389 bond_rss_conf.rss_key_len = 40; 390 391 retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 392 &bond_rss_conf); 393 TEST_ASSERT_SUCCESS(retval, "Cannot set bonding port RSS keys"); 394 395 FOR_EACH_PORT(n, port) { 396 port = &test_params.member_ports[n]; 397 398 retval = rte_eth_dev_rss_hash_conf_get(port->port_id, 399 &(port->rss_conf)); 400 401 TEST_ASSERT_SUCCESS(retval, 402 "Cannot take members RSS configuration"); 403 404 /* compare keys */ 405 retval = memcmp(port->rss_conf.rss_key, bond_rss_key, 406 sizeof(bond_rss_key)); 407 TEST_ASSERT(retval == 0, "Key value not propagated for member %d", 408 port->port_id); 409 } 410 } 411 412 /* 413 * Test RETA propagation 414 */ 415 for (i = 0; i < RXTX_QUEUE_COUNT; i++) { 416 417 /* Set all keys to zero */ 418 FOR_EACH_PORT(n, port) { 419 port = &test_params.member_ports[n]; 420 retval = reta_set(port->port_id, (i + 1) % RXTX_QUEUE_COUNT, 421 port->dev_info.reta_size); 422 TEST_ASSERT_SUCCESS(retval, "Cannot set members RETA"); 423 } 424 425 TEST_ASSERT_SUCCESS(reta_set(test_params.bond_port_id, 426 i % RXTX_QUEUE_COUNT, test_params.bond_dev_info.reta_size), 427 "Cannot set bonding port RETA"); 428 429 bond_reta_fetch(); 430 431 FOR_EACH_PORT(n, port) { 432 port = &test_params.member_ports[n]; 433 434 member_reta_fetch(port); 435 TEST_ASSERT(reta_check_synced(port) == 1, "RETAs inconsistent"); 436 } 437 } 438 439 return TEST_SUCCESS; 440 } 441 442 /** 443 * Test propagation logic, when RX_RSS mq_mode is turned on for bonding port 444 */ 445 static int 446 test_rss(void) 447 { 448 /** 449 * Configure bonding port in RSS mq mode 450 */ 451 int ret; 452 453 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id, 454 &rss_pmd_conf, 0), "Failed to configure bonding device\n"); 455 456 ret = rte_eth_dev_info_get(test_params.bond_port_id, 457 &test_params.bond_dev_info); 458 TEST_ASSERT((ret == 0), 459 "Error during getting device (port %u) info: %s\n", 460 test_params.bond_port_id, strerror(-ret)); 461 462 TEST_ASSERT_SUCCESS(bond_members(), "Bonding members failed"); 463 464 TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id), 465 "Failed to start bonding port (%d).", test_params.bond_port_id); 466 467 TEST_ASSERT_SUCCESS(test_propagate(), "Propagation test failed"); 468 469 TEST_ASSERT(member_remove_and_add() == 1, "remove and add members success."); 470 471 remove_members_and_stop_bonding_device(); 472 473 return TEST_SUCCESS; 474 } 475 476 477 /** 478 * Test RSS configuration over bonding and members. 479 */ 480 static int 481 test_rss_config_lazy(void) 482 { 483 struct rte_eth_rss_conf bond_rss_conf = {0}; 484 struct member_conf *port; 485 uint8_t rss_key[40]; 486 uint64_t rss_hf; 487 int retval; 488 uint16_t i; 489 uint8_t n; 490 491 retval = rte_eth_dev_info_get(test_params.bond_port_id, 492 &test_params.bond_dev_info); 493 TEST_ASSERT((retval == 0), "Error during getting device (port %u) info: %s\n", 494 test_params.bond_port_id, strerror(-retval)); 495 496 rss_hf = test_params.bond_dev_info.flow_type_rss_offloads; 497 if (rss_hf != 0) { 498 bond_rss_conf.rss_key = NULL; 499 bond_rss_conf.rss_hf = rss_hf; 500 retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 501 &bond_rss_conf); 502 TEST_ASSERT(retval != 0, "Succeeded in setting bonding port hash function"); 503 } 504 505 /* Set all keys to zero for all members */ 506 FOR_EACH_PORT(n, port) { 507 port = &test_params.member_ports[n]; 508 retval = rte_eth_dev_rss_hash_conf_get(port->port_id, 509 &port->rss_conf); 510 TEST_ASSERT_SUCCESS(retval, "Cannot get members RSS configuration"); 511 memset(port->rss_key, 0, sizeof(port->rss_key)); 512 port->rss_conf.rss_key = port->rss_key; 513 port->rss_conf.rss_key_len = sizeof(port->rss_key); 514 retval = rte_eth_dev_rss_hash_update(port->port_id, 515 &port->rss_conf); 516 TEST_ASSERT(retval != 0, "Succeeded in setting members RSS keys"); 517 } 518 519 /* Set RSS keys for bonding port */ 520 memset(rss_key, 1, sizeof(rss_key)); 521 bond_rss_conf.rss_hf = rss_hf; 522 bond_rss_conf.rss_key = rss_key; 523 bond_rss_conf.rss_key_len = sizeof(rss_key); 524 525 retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 526 &bond_rss_conf); 527 TEST_ASSERT(retval != 0, "Succeeded in setting bonding port RSS keys"); 528 529 /* Test RETA propagation */ 530 for (i = 0; i < RXTX_QUEUE_COUNT; i++) { 531 FOR_EACH_PORT(n, port) { 532 port = &test_params.member_ports[n]; 533 retval = reta_set(port->port_id, (i + 1) % RXTX_QUEUE_COUNT, 534 port->dev_info.reta_size); 535 TEST_ASSERT(retval != 0, "Succeeded in setting members RETA"); 536 } 537 538 retval = reta_set(test_params.bond_port_id, i % RXTX_QUEUE_COUNT, 539 test_params.bond_dev_info.reta_size); 540 TEST_ASSERT(retval != 0, "Succeeded in setting bonding port RETA"); 541 } 542 543 return TEST_SUCCESS; 544 } 545 546 /** 547 * Test RSS function logic, when RX_RSS mq_mode is turned off for bonding port 548 */ 549 static int 550 test_rss_lazy(void) 551 { 552 int ret; 553 554 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id, 555 &default_pmd_conf, 0), "Failed to configure bonding device\n"); 556 557 ret = rte_eth_dev_info_get(test_params.bond_port_id, 558 &test_params.bond_dev_info); 559 TEST_ASSERT((ret == 0), 560 "Error during getting device (port %u) info: %s\n", 561 test_params.bond_port_id, strerror(-ret)); 562 563 TEST_ASSERT_SUCCESS(bond_members(), "Bonding members failed"); 564 565 TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id), 566 "Failed to start bonding port (%d).", test_params.bond_port_id); 567 568 TEST_ASSERT_SUCCESS(test_rss_config_lazy(), "Succeeded in setting RSS hash when RX_RSS mq_mode is turned off"); 569 570 remove_members_and_stop_bonding_device(); 571 572 return TEST_SUCCESS; 573 } 574 575 static int 576 test_setup(void) 577 { 578 unsigned n; 579 int retval; 580 int port_id; 581 char name[256]; 582 struct member_conf *port; 583 struct rte_ether_addr mac_addr = { .addr_bytes = {0} }; 584 585 if (test_params.mbuf_pool == NULL) { 586 587 test_params.mbuf_pool = rte_pktmbuf_pool_create( 588 "RSS_MBUF_POOL", NUM_MBUFS * MEMBER_COUNT, 589 MBUF_CACHE_SIZE, 0, MBUF_SIZE, rte_socket_id()); 590 591 TEST_ASSERT(test_params.mbuf_pool != NULL, 592 "rte_pktmbuf_pool_create failed\n"); 593 } 594 595 /* Create / initialize ring eth devs. */ 596 FOR_EACH_PORT(n, port) { 597 port = &test_params.member_ports[n]; 598 599 port_id = rte_eth_dev_count_avail(); 600 snprintf(name, sizeof(name), MEMBER_DEV_NAME_FMT, port_id); 601 602 retval = rte_vdev_init(name, "size=64,copy=0"); 603 TEST_ASSERT_SUCCESS(retval, "Failed to create null device '%s'\n", 604 name); 605 606 port->port_id = port_id; 607 608 port->rss_conf.rss_key = port->rss_key; 609 port->rss_conf.rss_key_len = 40; 610 611 retval = configure_ethdev(port->port_id, &default_pmd_conf, 0); 612 TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n", 613 name); 614 615 /* assign a non-zero MAC */ 616 mac_addr.addr_bytes[5] = 0x10 + port->port_id; 617 rte_eth_dev_default_mac_addr_set(port->port_id, &mac_addr); 618 619 retval = rte_eth_dev_info_get(port->port_id, &port->dev_info); 620 TEST_ASSERT((retval == 0), 621 "Error during getting device (port %u) info: %s\n", 622 test_params.bond_port_id, strerror(-retval)); 623 } 624 625 if (test_params.bond_port_id == INVALID_PORT_ID) { 626 retval = rte_eth_bond_create(BONDING_DEV_NAME, 0, rte_socket_id()); 627 628 TEST_ASSERT(retval >= 0, "Failed to create bonding ethdev %s", 629 BONDING_DEV_NAME); 630 631 test_params.bond_port_id = retval; 632 633 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id, 634 &default_pmd_conf, 0), "Failed to configure bonding device\n"); 635 636 retval = rte_eth_dev_info_get(test_params.bond_port_id, 637 &test_params.bond_dev_info); 638 TEST_ASSERT((retval == 0), 639 "Error during getting device (port %u) info: %s\n", 640 test_params.bond_port_id, strerror(-retval)); 641 } 642 643 return TEST_SUCCESS; 644 } 645 646 static void 647 testsuite_teardown(void) 648 { 649 struct member_conf *port; 650 uint8_t i; 651 652 /* Only stop ports. 653 * Any cleanup/reset state is done when particular test is 654 * started. */ 655 656 rte_eth_dev_stop(test_params.bond_port_id); 657 658 FOR_EACH_PORT(i, port) 659 rte_eth_dev_stop(port->port_id); 660 } 661 662 static int 663 check_environment(void) 664 { 665 return TEST_SUCCESS; 666 } 667 668 static int 669 test_rssconf_executor(int (*test_func)(void)) 670 { 671 int test_result; 672 673 /* Check if environment is clean. Fail to launch a test if there was 674 * a critical error before that prevented to reset environment. */ 675 TEST_ASSERT_SUCCESS(check_environment(), 676 "Refusing to launch test in dirty environment."); 677 678 RTE_VERIFY(test_func != NULL); 679 test_result = (*test_func)(); 680 681 /* If test succeed check if environment wast left in good condition. */ 682 if (test_result == TEST_SUCCESS) 683 test_result = check_environment(); 684 685 /* Reset environment in case test failed to do that. */ 686 if (test_result != TEST_SUCCESS) { 687 TEST_ASSERT_SUCCESS(remove_members_and_stop_bonding_device(), 688 "Failed to stop bonding device"); 689 } 690 691 return test_result; 692 } 693 694 static int 695 test_setup_wrapper(void) 696 { 697 return test_rssconf_executor(&test_setup); 698 } 699 700 static int 701 test_rss_wrapper(void) 702 { 703 return test_rssconf_executor(&test_rss); 704 } 705 706 static int 707 test_rss_lazy_wrapper(void) 708 { 709 return test_rssconf_executor(&test_rss_lazy); 710 } 711 712 static struct unit_test_suite link_bonding_rssconf_test_suite = { 713 .suite_name = "RSS Dynamic Configuration for Bonding Unit Test Suite", 714 .teardown = testsuite_teardown, 715 .unit_test_cases = { 716 TEST_CASE_NAMED("test_setup", test_setup_wrapper), 717 TEST_CASE_NAMED("test_rss", test_rss_wrapper), 718 TEST_CASE_NAMED("test_rss_lazy", test_rss_lazy_wrapper), 719 720 TEST_CASES_END() 721 } 722 }; 723 724 static int 725 test_link_bonding_rssconf(void) 726 { 727 return unit_test_suite_runner(&link_bonding_rssconf_test_suite); 728 } 729 730 REGISTER_DRIVER_TEST(link_bonding_rssconf_autotest, test_link_bonding_rssconf); 731