1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2a9de470cSBruce Richardson * Copyright(c) 2015 Intel Corporation 3a9de470cSBruce Richardson */ 4a9de470cSBruce Richardson 5a9de470cSBruce Richardson #include <string.h> 6a9de470cSBruce Richardson #include <stdarg.h> 7a9de470cSBruce Richardson #include <stdio.h> 8a9de470cSBruce Richardson #include <stdlib.h> 9a9de470cSBruce Richardson #include <stdint.h> 10a9de470cSBruce Richardson #include <inttypes.h> 11a9de470cSBruce Richardson #include <errno.h> 12a9de470cSBruce Richardson #include <rte_cycles.h> 13a9de470cSBruce Richardson #include <sys/queue.h> 14a9de470cSBruce Richardson 15a9de470cSBruce Richardson #include <rte_byteorder.h> 16a9de470cSBruce Richardson #include <rte_common.h> 17a9de470cSBruce Richardson #include <rte_debug.h> 18a9de470cSBruce Richardson #include <rte_ethdev.h> 19a9de470cSBruce Richardson #include <rte_log.h> 20a9de470cSBruce Richardson #include <rte_lcore.h> 21a9de470cSBruce Richardson #include <rte_memory.h> 22a9de470cSBruce Richardson #include <rte_bus_vdev.h> 23a9de470cSBruce Richardson 24a9de470cSBruce Richardson #include <rte_string_fns.h> 25a9de470cSBruce Richardson #include <rte_errno.h> 26a9de470cSBruce Richardson #include <rte_eth_bond.h> 27a9de470cSBruce Richardson 28a9de470cSBruce Richardson #include "test.h" 29a9de470cSBruce Richardson 3015e34522SLong Wu #define MEMBER_COUNT (4) 31a9de470cSBruce Richardson 32a9de470cSBruce Richardson #define RXTX_RING_SIZE 1024 33a9de470cSBruce Richardson #define RXTX_QUEUE_COUNT 4 34a9de470cSBruce Richardson 354f840086SLong Wu #define BONDING_DEV_NAME ("net_bonding_rss") 36a9de470cSBruce Richardson 3715e34522SLong Wu #define MEMBER_DEV_NAME_FMT ("net_null%d") 3815e34522SLong Wu #define MEMBER_RXTX_QUEUE_FMT ("rssconf_member%d_q%d") 39a9de470cSBruce Richardson 40a9de470cSBruce Richardson #define NUM_MBUFS 8191 41a9de470cSBruce Richardson #define MBUF_SIZE (1600 + RTE_PKTMBUF_HEADROOM) 42a9de470cSBruce Richardson #define MBUF_CACHE_SIZE 250 43a9de470cSBruce Richardson #define BURST_SIZE 32 44a9de470cSBruce Richardson 45a9de470cSBruce Richardson #define INVALID_SOCKET_ID (-1) 46a9de470cSBruce Richardson #define INVALID_PORT_ID (0xFF) 47a9de470cSBruce Richardson #define INVALID_BONDING_MODE (-1) 48a9de470cSBruce Richardson 4915e34522SLong Wu struct member_conf { 50a9de470cSBruce Richardson uint16_t port_id; 51a9de470cSBruce Richardson struct rte_eth_dev_info dev_info; 52a9de470cSBruce Richardson 53a9de470cSBruce Richardson struct rte_eth_rss_conf rss_conf; 54a9de470cSBruce Richardson uint8_t rss_key[40]; 55295968d1SFerruh Yigit struct rte_eth_rss_reta_entry64 reta_conf[512 / RTE_ETH_RETA_GROUP_SIZE]; 56a9de470cSBruce Richardson 5715e34522SLong Wu uint8_t is_member; 58a9de470cSBruce Richardson struct rte_ring *rxtx_queue[RXTX_QUEUE_COUNT]; 59a9de470cSBruce Richardson }; 60a9de470cSBruce Richardson 61a9de470cSBruce Richardson struct link_bonding_rssconf_unittest_params { 62a9de470cSBruce Richardson uint8_t bond_port_id; 63a9de470cSBruce Richardson struct rte_eth_dev_info bond_dev_info; 64295968d1SFerruh Yigit struct rte_eth_rss_reta_entry64 bond_reta_conf[512 / RTE_ETH_RETA_GROUP_SIZE]; 6515e34522SLong Wu struct member_conf member_ports[MEMBER_COUNT]; 66a9de470cSBruce Richardson 67a9de470cSBruce Richardson struct rte_mempool *mbuf_pool; 68a9de470cSBruce Richardson }; 69a9de470cSBruce Richardson 70a9de470cSBruce Richardson static struct link_bonding_rssconf_unittest_params test_params = { 71a9de470cSBruce Richardson .bond_port_id = INVALID_PORT_ID, 7215e34522SLong Wu .member_ports = { 7315e34522SLong Wu [0 ... MEMBER_COUNT - 1] = { .port_id = INVALID_PORT_ID, .is_member = 0} 74a9de470cSBruce Richardson }, 75a9de470cSBruce Richardson .mbuf_pool = NULL, 76a9de470cSBruce Richardson }; 77a9de470cSBruce Richardson 78a9de470cSBruce Richardson /** 79a9de470cSBruce Richardson * Default port configuration with RSS turned off 80a9de470cSBruce Richardson */ 81a9de470cSBruce Richardson static struct rte_eth_conf default_pmd_conf = { 82a9de470cSBruce Richardson .rxmode = { 83295968d1SFerruh Yigit .mq_mode = RTE_ETH_MQ_RX_NONE, 84a9de470cSBruce Richardson }, 85a9de470cSBruce Richardson .txmode = { 86295968d1SFerruh Yigit .mq_mode = RTE_ETH_MQ_TX_NONE, 87a9de470cSBruce Richardson }, 88a9de470cSBruce Richardson .lpbk_mode = 0, 89a9de470cSBruce Richardson }; 90a9de470cSBruce Richardson 91a9de470cSBruce Richardson static struct rte_eth_conf rss_pmd_conf = { 92a9de470cSBruce Richardson .rxmode = { 93295968d1SFerruh Yigit .mq_mode = RTE_ETH_MQ_RX_RSS, 94a9de470cSBruce Richardson }, 95a9de470cSBruce Richardson .txmode = { 96295968d1SFerruh Yigit .mq_mode = RTE_ETH_MQ_TX_NONE, 97a9de470cSBruce Richardson }, 98a9de470cSBruce Richardson .rx_adv_conf = { 99a9de470cSBruce Richardson .rss_conf = { 100a9de470cSBruce Richardson .rss_key = NULL, 101295968d1SFerruh Yigit .rss_hf = RTE_ETH_RSS_IPV6, 102a9de470cSBruce Richardson }, 103a9de470cSBruce Richardson }, 104a9de470cSBruce Richardson .lpbk_mode = 0, 105a9de470cSBruce Richardson }; 106a9de470cSBruce Richardson 107a9de470cSBruce Richardson #define FOR_EACH(_i, _item, _array, _size) \ 108a9de470cSBruce Richardson for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++) 109a9de470cSBruce Richardson 11015e34522SLong Wu /* Macro for iterating over every port that can be used as a member 111a9de470cSBruce Richardson * in this test. 11215e34522SLong Wu * _i variable used as an index in test_params->member_ports 11315e34522SLong Wu * _member pointer to &test_params->member_ports[_idx] 114a9de470cSBruce Richardson */ 115a9de470cSBruce Richardson #define FOR_EACH_PORT(_i, _port) \ 11615e34522SLong Wu FOR_EACH(_i, _port, test_params.member_ports, \ 11715e34522SLong Wu RTE_DIM(test_params.member_ports)) 118a9de470cSBruce Richardson 119a9de470cSBruce Richardson static int 120a9de470cSBruce Richardson configure_ethdev(uint16_t port_id, struct rte_eth_conf *eth_conf, 121a9de470cSBruce Richardson uint8_t start) 122a9de470cSBruce Richardson { 123a9de470cSBruce Richardson int rxq, txq; 124a9de470cSBruce Richardson 125a9de470cSBruce Richardson TEST_ASSERT(rte_eth_dev_configure(port_id, RXTX_QUEUE_COUNT, 126a9de470cSBruce Richardson RXTX_QUEUE_COUNT, eth_conf) == 0, "Failed to configure device %u", 127a9de470cSBruce Richardson port_id); 128a9de470cSBruce Richardson 129b3eaaf1dSJunjie Wan int ret = rte_eth_dev_set_mtu(port_id, 1550); 130b3eaaf1dSJunjie Wan RTE_TEST_ASSERT(ret == 0 || ret == -ENOTSUP, 131b3eaaf1dSJunjie Wan "rte_eth_dev_set_mtu for port %d failed", port_id); 132b3eaaf1dSJunjie Wan 133a9de470cSBruce Richardson for (rxq = 0; rxq < RXTX_QUEUE_COUNT; rxq++) { 134a9de470cSBruce Richardson TEST_ASSERT(rte_eth_rx_queue_setup(port_id, rxq, RXTX_RING_SIZE, 135a9de470cSBruce Richardson rte_eth_dev_socket_id(port_id), NULL, 136a9de470cSBruce Richardson test_params.mbuf_pool) == 0, "Failed to setup rx queue."); 137a9de470cSBruce Richardson } 138a9de470cSBruce Richardson 139a9de470cSBruce Richardson for (txq = 0; txq < RXTX_QUEUE_COUNT; txq++) { 140a9de470cSBruce Richardson TEST_ASSERT(rte_eth_tx_queue_setup(port_id, txq, RXTX_RING_SIZE, 141a9de470cSBruce Richardson rte_eth_dev_socket_id(port_id), NULL) == 0, 142a9de470cSBruce Richardson "Failed to setup tx queue."); 143a9de470cSBruce Richardson } 144a9de470cSBruce Richardson 145a9de470cSBruce Richardson if (start) { 146a9de470cSBruce Richardson TEST_ASSERT(rte_eth_dev_start(port_id) == 0, 147a9de470cSBruce Richardson "Failed to start device (%d).", port_id); 148a9de470cSBruce Richardson } 149a9de470cSBruce Richardson 150a9de470cSBruce Richardson return 0; 151a9de470cSBruce Richardson } 152a9de470cSBruce Richardson 153a9de470cSBruce Richardson /** 15415e34522SLong Wu * Remove all members from bonding 155a9de470cSBruce Richardson */ 156a9de470cSBruce Richardson static int 15715e34522SLong Wu remove_members(void) 158a9de470cSBruce Richardson { 159a9de470cSBruce Richardson unsigned n; 16015e34522SLong Wu struct member_conf *port; 161a9de470cSBruce Richardson 162a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 16315e34522SLong Wu port = &test_params.member_ports[n]; 16415e34522SLong Wu if (port->is_member) { 16515e34522SLong Wu TEST_ASSERT_SUCCESS(rte_eth_bond_member_remove( 166a9de470cSBruce Richardson test_params.bond_port_id, port->port_id), 16715e34522SLong Wu "Cannot remove member %d from bonding", port->port_id); 16815e34522SLong Wu port->is_member = 0; 169a9de470cSBruce Richardson } 170a9de470cSBruce Richardson } 171a9de470cSBruce Richardson 172a9de470cSBruce Richardson return 0; 173a9de470cSBruce Richardson } 174a9de470cSBruce Richardson 175a9de470cSBruce Richardson static int 1764f840086SLong Wu remove_members_and_stop_bonding_device(void) 177a9de470cSBruce Richardson { 17815e34522SLong Wu TEST_ASSERT_SUCCESS(remove_members(), "Removing members"); 1790ead65afSIvan Ilchenko TEST_ASSERT_SUCCESS(rte_eth_dev_stop(test_params.bond_port_id), 1800ead65afSIvan Ilchenko "Failed to stop port %u", test_params.bond_port_id); 181a9de470cSBruce Richardson return TEST_SUCCESS; 182a9de470cSBruce Richardson } 183a9de470cSBruce Richardson 184a9de470cSBruce Richardson /** 18515e34522SLong Wu * Add all members to bonding 186a9de470cSBruce Richardson */ 187a9de470cSBruce Richardson static int 18815e34522SLong Wu bond_members(void) 189a9de470cSBruce Richardson { 190a9de470cSBruce Richardson unsigned n; 19115e34522SLong Wu struct member_conf *port; 192a9de470cSBruce Richardson 193a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 19415e34522SLong Wu port = &test_params.member_ports[n]; 19515e34522SLong Wu if (!port->is_member) { 19615e34522SLong Wu TEST_ASSERT_SUCCESS(rte_eth_bond_member_add(test_params.bond_port_id, 19715e34522SLong Wu port->port_id), "Cannot attach member %d to the bonding", 198a9de470cSBruce Richardson port->port_id); 19915e34522SLong Wu port->is_member = 1; 200a9de470cSBruce Richardson } 201a9de470cSBruce Richardson } 202a9de470cSBruce Richardson 203a9de470cSBruce Richardson return 0; 204a9de470cSBruce Richardson } 205a9de470cSBruce Richardson 206a9de470cSBruce Richardson /** 207a9de470cSBruce Richardson * Set all RETA values in port_id to value 208a9de470cSBruce Richardson */ 209a9de470cSBruce Richardson static int 210a9de470cSBruce Richardson reta_set(uint16_t port_id, uint8_t value, int reta_size) 211a9de470cSBruce Richardson { 212295968d1SFerruh Yigit struct rte_eth_rss_reta_entry64 reta_conf[512/RTE_ETH_RETA_GROUP_SIZE]; 213a9de470cSBruce Richardson int i, j; 214a9de470cSBruce Richardson 215295968d1SFerruh Yigit for (i = 0; i < reta_size / RTE_ETH_RETA_GROUP_SIZE; i++) { 216a9de470cSBruce Richardson /* select all fields to set */ 217a9de470cSBruce Richardson reta_conf[i].mask = ~0LL; 218295968d1SFerruh Yigit for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) 219a9de470cSBruce Richardson reta_conf[i].reta[j] = value; 220a9de470cSBruce Richardson } 221a9de470cSBruce Richardson 222a9de470cSBruce Richardson return rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size); 223a9de470cSBruce Richardson } 224a9de470cSBruce Richardson 225a9de470cSBruce Richardson /** 22615e34522SLong Wu * Check if members RETA is synchronized with bonding port. Returns 1 if member 227a9de470cSBruce Richardson * port is synced with bonding port. 228a9de470cSBruce Richardson */ 229a9de470cSBruce Richardson static int 23015e34522SLong Wu reta_check_synced(struct member_conf *port) 231a9de470cSBruce Richardson { 232a9de470cSBruce Richardson unsigned i; 233a9de470cSBruce Richardson 234a9de470cSBruce Richardson for (i = 0; i < test_params.bond_dev_info.reta_size; 235a9de470cSBruce Richardson i++) { 236a9de470cSBruce Richardson 237295968d1SFerruh Yigit int index = i / RTE_ETH_RETA_GROUP_SIZE; 238295968d1SFerruh Yigit int shift = i % RTE_ETH_RETA_GROUP_SIZE; 239a9de470cSBruce Richardson 240a9de470cSBruce Richardson if (port->reta_conf[index].reta[shift] != 241a9de470cSBruce Richardson test_params.bond_reta_conf[index].reta[shift]) 242a9de470cSBruce Richardson return 0; 243a9de470cSBruce Richardson 244a9de470cSBruce Richardson } 245a9de470cSBruce Richardson 246a9de470cSBruce Richardson return 1; 247a9de470cSBruce Richardson } 248a9de470cSBruce Richardson 249a9de470cSBruce Richardson /** 250a9de470cSBruce Richardson * Fetch bonding ports RETA 251a9de470cSBruce Richardson */ 252a9de470cSBruce Richardson static int 253a9de470cSBruce Richardson bond_reta_fetch(void) { 254a9de470cSBruce Richardson unsigned j; 255a9de470cSBruce Richardson 256295968d1SFerruh Yigit for (j = 0; j < test_params.bond_dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE; 257a9de470cSBruce Richardson j++) 258a9de470cSBruce Richardson test_params.bond_reta_conf[j].mask = ~0LL; 259a9de470cSBruce Richardson 260a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(test_params.bond_port_id, 261a9de470cSBruce Richardson test_params.bond_reta_conf, test_params.bond_dev_info.reta_size), 262a9de470cSBruce Richardson "Cannot take bonding ports RSS configuration"); 263a9de470cSBruce Richardson return 0; 264a9de470cSBruce Richardson } 265a9de470cSBruce Richardson 266a9de470cSBruce Richardson /** 26715e34522SLong Wu * Fetch members RETA 268a9de470cSBruce Richardson */ 269a9de470cSBruce Richardson static int 27015e34522SLong Wu member_reta_fetch(struct member_conf *port) { 271a9de470cSBruce Richardson unsigned j; 272a9de470cSBruce Richardson 273295968d1SFerruh Yigit for (j = 0; j < port->dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE; j++) 274a9de470cSBruce Richardson port->reta_conf[j].mask = ~0LL; 275a9de470cSBruce Richardson 276a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(port->port_id, 277a9de470cSBruce Richardson port->reta_conf, port->dev_info.reta_size), 278a9de470cSBruce Richardson "Cannot take bonding ports RSS configuration"); 279a9de470cSBruce Richardson return 0; 280a9de470cSBruce Richardson } 281a9de470cSBruce Richardson 282a9de470cSBruce Richardson /** 28315e34522SLong Wu * Remove and add member to check if members configuration is synced with 28415e34522SLong Wu * the bonding ports values after adding new member. 285a9de470cSBruce Richardson */ 286a9de470cSBruce Richardson static int 28715e34522SLong Wu member_remove_and_add(void) 288a9de470cSBruce Richardson { 28915e34522SLong Wu struct member_conf *port = &(test_params.member_ports[0]); 290a9de470cSBruce Richardson 29115e34522SLong Wu /* 1. Remove first member from bonding */ 29215e34522SLong Wu TEST_ASSERT_SUCCESS(rte_eth_bond_member_remove(test_params.bond_port_id, 29315e34522SLong Wu port->port_id), "Cannot remove member #d from bonding"); 294a9de470cSBruce Richardson 29515e34522SLong Wu /* 2. Change removed (ex-)member and bonding configuration to different 296a9de470cSBruce Richardson * values 297a9de470cSBruce Richardson */ 298a9de470cSBruce Richardson reta_set(test_params.bond_port_id, 1, test_params.bond_dev_info.reta_size); 299a9de470cSBruce Richardson bond_reta_fetch(); 300a9de470cSBruce Richardson 301a9de470cSBruce Richardson reta_set(port->port_id, 2, port->dev_info.reta_size); 30215e34522SLong Wu member_reta_fetch(port); 303a9de470cSBruce Richardson 304a9de470cSBruce Richardson TEST_ASSERT(reta_check_synced(port) == 0, 30515e34522SLong Wu "Removed member didn't should be synchronized with bonding port"); 306a9de470cSBruce Richardson 30715e34522SLong Wu /* 3. Add (ex-)member and check if configuration changed*/ 30815e34522SLong Wu TEST_ASSERT_SUCCESS(rte_eth_bond_member_add(test_params.bond_port_id, 30915e34522SLong Wu port->port_id), "Cannot add member"); 310a9de470cSBruce Richardson 311a9de470cSBruce Richardson bond_reta_fetch(); 31215e34522SLong Wu member_reta_fetch(port); 313a9de470cSBruce Richardson 314a9de470cSBruce Richardson return reta_check_synced(port); 315a9de470cSBruce Richardson } 316a9de470cSBruce Richardson 317a9de470cSBruce Richardson /** 31815e34522SLong Wu * Test configuration propagation over members. 319a9de470cSBruce Richardson */ 320a9de470cSBruce Richardson static int 321a9de470cSBruce Richardson test_propagate(void) 322a9de470cSBruce Richardson { 323a9de470cSBruce Richardson unsigned i; 324a9de470cSBruce Richardson uint8_t n; 32515e34522SLong Wu struct member_conf *port; 326a9de470cSBruce Richardson uint8_t bond_rss_key[40]; 327*fb662d63SJie Hai struct rte_eth_rss_conf bond_rss_conf = {0}; 328a9de470cSBruce Richardson 329a9de470cSBruce Richardson int retval = 0; 330a9de470cSBruce Richardson uint64_t rss_hf = 0; 331a9de470cSBruce Richardson uint64_t default_rss_hf = 0; 332a9de470cSBruce Richardson 33377339255SIvan Ilchenko retval = rte_eth_dev_info_get(test_params.bond_port_id, 33477339255SIvan Ilchenko &test_params.bond_dev_info); 33577339255SIvan Ilchenko TEST_ASSERT((retval == 0), 33677339255SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 33777339255SIvan Ilchenko test_params.bond_port_id, strerror(-retval)); 338a9de470cSBruce Richardson 339a9de470cSBruce Richardson /* 340a9de470cSBruce Richardson * Test hash function propagation 341a9de470cSBruce Richardson */ 342a9de470cSBruce Richardson for (i = 0; i < sizeof(test_params.bond_dev_info.flow_type_rss_offloads)*8; 343a9de470cSBruce Richardson i++) { 344a9de470cSBruce Richardson 345a9de470cSBruce Richardson rss_hf = test_params.bond_dev_info.flow_type_rss_offloads & (1<<i); 346a9de470cSBruce Richardson if (rss_hf) { 347a9de470cSBruce Richardson bond_rss_conf.rss_key = NULL; 348a9de470cSBruce Richardson bond_rss_conf.rss_hf = rss_hf; 349a9de470cSBruce Richardson 350a9de470cSBruce Richardson retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 351a9de470cSBruce Richardson &bond_rss_conf); 35215e34522SLong Wu TEST_ASSERT_SUCCESS(retval, "Cannot set members hash function"); 353a9de470cSBruce Richardson 354a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 35515e34522SLong Wu port = &test_params.member_ports[n]; 356a9de470cSBruce Richardson 357a9de470cSBruce Richardson retval = rte_eth_dev_rss_hash_conf_get(port->port_id, 358a9de470cSBruce Richardson &port->rss_conf); 359a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(retval, 36015e34522SLong Wu "Cannot take members RSS configuration"); 361a9de470cSBruce Richardson 362a9de470cSBruce Richardson TEST_ASSERT(port->rss_conf.rss_hf == rss_hf, 36315e34522SLong Wu "Hash function not propagated for member %d", 364a9de470cSBruce Richardson port->port_id); 365a9de470cSBruce Richardson } 366a9de470cSBruce Richardson 367a9de470cSBruce Richardson default_rss_hf = rss_hf; 368a9de470cSBruce Richardson } 369a9de470cSBruce Richardson 370a9de470cSBruce Richardson } 371a9de470cSBruce Richardson 372a9de470cSBruce Richardson /* 373a9de470cSBruce Richardson * Test key propagation 374a9de470cSBruce Richardson */ 375a9de470cSBruce Richardson for (i = 1; i < 10; i++) { 376a9de470cSBruce Richardson 377a9de470cSBruce Richardson /* Set all keys to zero */ 378a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 37915e34522SLong Wu port = &test_params.member_ports[n]; 380a9de470cSBruce Richardson memset(port->rss_conf.rss_key, 0, 40); 381a9de470cSBruce Richardson retval = rte_eth_dev_rss_hash_update(port->port_id, 382a9de470cSBruce Richardson &port->rss_conf); 38315e34522SLong Wu TEST_ASSERT_SUCCESS(retval, "Cannot set members RSS keys"); 384a9de470cSBruce Richardson } 385a9de470cSBruce Richardson 386a9de470cSBruce Richardson memset(bond_rss_key, i, sizeof(bond_rss_key)); 387a9de470cSBruce Richardson bond_rss_conf.rss_hf = default_rss_hf, 388a9de470cSBruce Richardson bond_rss_conf.rss_key = bond_rss_key; 389a9de470cSBruce Richardson bond_rss_conf.rss_key_len = 40; 390a9de470cSBruce Richardson 391a9de470cSBruce Richardson retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 392a9de470cSBruce Richardson &bond_rss_conf); 3934f840086SLong Wu TEST_ASSERT_SUCCESS(retval, "Cannot set bonding port RSS keys"); 394a9de470cSBruce Richardson 395a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 39615e34522SLong Wu port = &test_params.member_ports[n]; 397a9de470cSBruce Richardson 398a9de470cSBruce Richardson retval = rte_eth_dev_rss_hash_conf_get(port->port_id, 399a9de470cSBruce Richardson &(port->rss_conf)); 400a9de470cSBruce Richardson 401a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(retval, 40215e34522SLong Wu "Cannot take members RSS configuration"); 403a9de470cSBruce Richardson 404a9de470cSBruce Richardson /* compare keys */ 405a9de470cSBruce Richardson retval = memcmp(port->rss_conf.rss_key, bond_rss_key, 406a9de470cSBruce Richardson sizeof(bond_rss_key)); 40715e34522SLong Wu TEST_ASSERT(retval == 0, "Key value not propagated for member %d", 408a9de470cSBruce Richardson port->port_id); 409a9de470cSBruce Richardson } 410a9de470cSBruce Richardson } 411a9de470cSBruce Richardson 412a9de470cSBruce Richardson /* 413a9de470cSBruce Richardson * Test RETA propagation 414a9de470cSBruce Richardson */ 415a9de470cSBruce Richardson for (i = 0; i < RXTX_QUEUE_COUNT; i++) { 416a9de470cSBruce Richardson 417a9de470cSBruce Richardson /* Set all keys to zero */ 418a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 41915e34522SLong Wu port = &test_params.member_ports[n]; 420a9de470cSBruce Richardson retval = reta_set(port->port_id, (i + 1) % RXTX_QUEUE_COUNT, 421a9de470cSBruce Richardson port->dev_info.reta_size); 42215e34522SLong Wu TEST_ASSERT_SUCCESS(retval, "Cannot set members RETA"); 423a9de470cSBruce Richardson } 424a9de470cSBruce Richardson 425a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(reta_set(test_params.bond_port_id, 426a9de470cSBruce Richardson i % RXTX_QUEUE_COUNT, test_params.bond_dev_info.reta_size), 4274f840086SLong Wu "Cannot set bonding port RETA"); 428a9de470cSBruce Richardson 429a9de470cSBruce Richardson bond_reta_fetch(); 430a9de470cSBruce Richardson 431a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 43215e34522SLong Wu port = &test_params.member_ports[n]; 433a9de470cSBruce Richardson 43415e34522SLong Wu member_reta_fetch(port); 435a9de470cSBruce Richardson TEST_ASSERT(reta_check_synced(port) == 1, "RETAs inconsistent"); 436a9de470cSBruce Richardson } 437a9de470cSBruce Richardson } 438a9de470cSBruce Richardson 439a9de470cSBruce Richardson return TEST_SUCCESS; 440a9de470cSBruce Richardson } 441a9de470cSBruce Richardson 442a9de470cSBruce Richardson /** 443a9de470cSBruce Richardson * Test propagation logic, when RX_RSS mq_mode is turned on for bonding port 444a9de470cSBruce Richardson */ 445a9de470cSBruce Richardson static int 446a9de470cSBruce Richardson test_rss(void) 447a9de470cSBruce Richardson { 448a9de470cSBruce Richardson /** 449a9de470cSBruce Richardson * Configure bonding port in RSS mq mode 450a9de470cSBruce Richardson */ 45177339255SIvan Ilchenko int ret; 45277339255SIvan Ilchenko 453a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id, 454a9de470cSBruce Richardson &rss_pmd_conf, 0), "Failed to configure bonding device\n"); 455a9de470cSBruce Richardson 45677339255SIvan Ilchenko ret = rte_eth_dev_info_get(test_params.bond_port_id, 45777339255SIvan Ilchenko &test_params.bond_dev_info); 45877339255SIvan Ilchenko TEST_ASSERT((ret == 0), 45977339255SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 46077339255SIvan Ilchenko test_params.bond_port_id, strerror(-ret)); 461a9de470cSBruce Richardson 46215e34522SLong Wu TEST_ASSERT_SUCCESS(bond_members(), "Bonding members failed"); 463a9de470cSBruce Richardson 464a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id), 465a9de470cSBruce Richardson "Failed to start bonding port (%d).", test_params.bond_port_id); 466a9de470cSBruce Richardson 467a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(test_propagate(), "Propagation test failed"); 468a9de470cSBruce Richardson 46915e34522SLong Wu TEST_ASSERT(member_remove_and_add() == 1, "remove and add members success."); 470a9de470cSBruce Richardson 4714f840086SLong Wu remove_members_and_stop_bonding_device(); 472a9de470cSBruce Richardson 473a9de470cSBruce Richardson return TEST_SUCCESS; 474a9de470cSBruce Richardson } 475a9de470cSBruce Richardson 47664969223SHuisong Li 477a9de470cSBruce Richardson /** 4784f840086SLong Wu * Test RSS configuration over bonding and members. 47964969223SHuisong Li */ 48064969223SHuisong Li static int 48164969223SHuisong Li test_rss_config_lazy(void) 48264969223SHuisong Li { 48364969223SHuisong Li struct rte_eth_rss_conf bond_rss_conf = {0}; 48415e34522SLong Wu struct member_conf *port; 48564969223SHuisong Li uint8_t rss_key[40]; 48664969223SHuisong Li uint64_t rss_hf; 48764969223SHuisong Li int retval; 48864969223SHuisong Li uint16_t i; 48964969223SHuisong Li uint8_t n; 49064969223SHuisong Li 49164969223SHuisong Li retval = rte_eth_dev_info_get(test_params.bond_port_id, 49264969223SHuisong Li &test_params.bond_dev_info); 49364969223SHuisong Li TEST_ASSERT((retval == 0), "Error during getting device (port %u) info: %s\n", 49464969223SHuisong Li test_params.bond_port_id, strerror(-retval)); 49564969223SHuisong Li 49664969223SHuisong Li rss_hf = test_params.bond_dev_info.flow_type_rss_offloads; 49764969223SHuisong Li if (rss_hf != 0) { 49864969223SHuisong Li bond_rss_conf.rss_key = NULL; 49964969223SHuisong Li bond_rss_conf.rss_hf = rss_hf; 50064969223SHuisong Li retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 50164969223SHuisong Li &bond_rss_conf); 5024f840086SLong Wu TEST_ASSERT(retval != 0, "Succeeded in setting bonding port hash function"); 50364969223SHuisong Li } 50464969223SHuisong Li 50515e34522SLong Wu /* Set all keys to zero for all members */ 50664969223SHuisong Li FOR_EACH_PORT(n, port) { 50715e34522SLong Wu port = &test_params.member_ports[n]; 50864969223SHuisong Li retval = rte_eth_dev_rss_hash_conf_get(port->port_id, 50964969223SHuisong Li &port->rss_conf); 51015e34522SLong Wu TEST_ASSERT_SUCCESS(retval, "Cannot get members RSS configuration"); 51164969223SHuisong Li memset(port->rss_key, 0, sizeof(port->rss_key)); 51264969223SHuisong Li port->rss_conf.rss_key = port->rss_key; 51364969223SHuisong Li port->rss_conf.rss_key_len = sizeof(port->rss_key); 51464969223SHuisong Li retval = rte_eth_dev_rss_hash_update(port->port_id, 51564969223SHuisong Li &port->rss_conf); 51615e34522SLong Wu TEST_ASSERT(retval != 0, "Succeeded in setting members RSS keys"); 51764969223SHuisong Li } 51864969223SHuisong Li 5194f840086SLong Wu /* Set RSS keys for bonding port */ 52064969223SHuisong Li memset(rss_key, 1, sizeof(rss_key)); 52164969223SHuisong Li bond_rss_conf.rss_hf = rss_hf; 52264969223SHuisong Li bond_rss_conf.rss_key = rss_key; 52364969223SHuisong Li bond_rss_conf.rss_key_len = sizeof(rss_key); 52464969223SHuisong Li 52564969223SHuisong Li retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id, 52664969223SHuisong Li &bond_rss_conf); 5274f840086SLong Wu TEST_ASSERT(retval != 0, "Succeeded in setting bonding port RSS keys"); 52864969223SHuisong Li 52964969223SHuisong Li /* Test RETA propagation */ 53064969223SHuisong Li for (i = 0; i < RXTX_QUEUE_COUNT; i++) { 53164969223SHuisong Li FOR_EACH_PORT(n, port) { 53215e34522SLong Wu port = &test_params.member_ports[n]; 53364969223SHuisong Li retval = reta_set(port->port_id, (i + 1) % RXTX_QUEUE_COUNT, 53464969223SHuisong Li port->dev_info.reta_size); 53515e34522SLong Wu TEST_ASSERT(retval != 0, "Succeeded in setting members RETA"); 53664969223SHuisong Li } 53764969223SHuisong Li 53864969223SHuisong Li retval = reta_set(test_params.bond_port_id, i % RXTX_QUEUE_COUNT, 53964969223SHuisong Li test_params.bond_dev_info.reta_size); 5404f840086SLong Wu TEST_ASSERT(retval != 0, "Succeeded in setting bonding port RETA"); 54164969223SHuisong Li } 54264969223SHuisong Li 54364969223SHuisong Li return TEST_SUCCESS; 54464969223SHuisong Li } 54564969223SHuisong Li 54664969223SHuisong Li /** 54764969223SHuisong Li * Test RSS function logic, when RX_RSS mq_mode is turned off for bonding port 548a9de470cSBruce Richardson */ 549a9de470cSBruce Richardson static int 550a9de470cSBruce Richardson test_rss_lazy(void) 551a9de470cSBruce Richardson { 55277339255SIvan Ilchenko int ret; 55377339255SIvan Ilchenko 554a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id, 555a9de470cSBruce Richardson &default_pmd_conf, 0), "Failed to configure bonding device\n"); 556a9de470cSBruce Richardson 55777339255SIvan Ilchenko ret = rte_eth_dev_info_get(test_params.bond_port_id, 55877339255SIvan Ilchenko &test_params.bond_dev_info); 55977339255SIvan Ilchenko TEST_ASSERT((ret == 0), 56077339255SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 56177339255SIvan Ilchenko test_params.bond_port_id, strerror(-ret)); 562a9de470cSBruce Richardson 56315e34522SLong Wu TEST_ASSERT_SUCCESS(bond_members(), "Bonding members failed"); 564a9de470cSBruce Richardson 565a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id), 566a9de470cSBruce Richardson "Failed to start bonding port (%d).", test_params.bond_port_id); 567a9de470cSBruce Richardson 56864969223SHuisong Li TEST_ASSERT_SUCCESS(test_rss_config_lazy(), "Succeeded in setting RSS hash when RX_RSS mq_mode is turned off"); 569a9de470cSBruce Richardson 5704f840086SLong Wu remove_members_and_stop_bonding_device(); 571a9de470cSBruce Richardson 572a9de470cSBruce Richardson return TEST_SUCCESS; 573a9de470cSBruce Richardson } 574a9de470cSBruce Richardson 575a9de470cSBruce Richardson static int 576a9de470cSBruce Richardson test_setup(void) 577a9de470cSBruce Richardson { 578a9de470cSBruce Richardson unsigned n; 579a9de470cSBruce Richardson int retval; 580a9de470cSBruce Richardson int port_id; 581a9de470cSBruce Richardson char name[256]; 58215e34522SLong Wu struct member_conf *port; 5836d13ea8eSOlivier Matz struct rte_ether_addr mac_addr = { .addr_bytes = {0} }; 584a9de470cSBruce Richardson 585a9de470cSBruce Richardson if (test_params.mbuf_pool == NULL) { 586a9de470cSBruce Richardson 587a9de470cSBruce Richardson test_params.mbuf_pool = rte_pktmbuf_pool_create( 58815e34522SLong Wu "RSS_MBUF_POOL", NUM_MBUFS * MEMBER_COUNT, 589a9de470cSBruce Richardson MBUF_CACHE_SIZE, 0, MBUF_SIZE, rte_socket_id()); 590a9de470cSBruce Richardson 591a9de470cSBruce Richardson TEST_ASSERT(test_params.mbuf_pool != NULL, 592a9de470cSBruce Richardson "rte_pktmbuf_pool_create failed\n"); 593a9de470cSBruce Richardson } 594a9de470cSBruce Richardson 595a9de470cSBruce Richardson /* Create / initialize ring eth devs. */ 596a9de470cSBruce Richardson FOR_EACH_PORT(n, port) { 59715e34522SLong Wu port = &test_params.member_ports[n]; 598a9de470cSBruce Richardson 599a9de470cSBruce Richardson port_id = rte_eth_dev_count_avail(); 60015e34522SLong Wu snprintf(name, sizeof(name), MEMBER_DEV_NAME_FMT, port_id); 601a9de470cSBruce Richardson 602a9de470cSBruce Richardson retval = rte_vdev_init(name, "size=64,copy=0"); 603a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(retval, "Failed to create null device '%s'\n", 604a9de470cSBruce Richardson name); 605a9de470cSBruce Richardson 606a9de470cSBruce Richardson port->port_id = port_id; 607a9de470cSBruce Richardson 608a9de470cSBruce Richardson port->rss_conf.rss_key = port->rss_key; 609a9de470cSBruce Richardson port->rss_conf.rss_key_len = 40; 610a9de470cSBruce Richardson 611a9de470cSBruce Richardson retval = configure_ethdev(port->port_id, &default_pmd_conf, 0); 612a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n", 613a9de470cSBruce Richardson name); 614a9de470cSBruce Richardson 615a9de470cSBruce Richardson /* assign a non-zero MAC */ 616a9de470cSBruce Richardson mac_addr.addr_bytes[5] = 0x10 + port->port_id; 617a9de470cSBruce Richardson rte_eth_dev_default_mac_addr_set(port->port_id, &mac_addr); 618a9de470cSBruce Richardson 61977339255SIvan Ilchenko retval = rte_eth_dev_info_get(port->port_id, &port->dev_info); 62077339255SIvan Ilchenko TEST_ASSERT((retval == 0), 62177339255SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 62277339255SIvan Ilchenko test_params.bond_port_id, strerror(-retval)); 623a9de470cSBruce Richardson } 624a9de470cSBruce Richardson 625a9de470cSBruce Richardson if (test_params.bond_port_id == INVALID_PORT_ID) { 6264f840086SLong Wu retval = rte_eth_bond_create(BONDING_DEV_NAME, 0, rte_socket_id()); 627a9de470cSBruce Richardson 6284f840086SLong Wu TEST_ASSERT(retval >= 0, "Failed to create bonding ethdev %s", 6294f840086SLong Wu BONDING_DEV_NAME); 630a9de470cSBruce Richardson 631a9de470cSBruce Richardson test_params.bond_port_id = retval; 632a9de470cSBruce Richardson 633a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id, 634a9de470cSBruce Richardson &default_pmd_conf, 0), "Failed to configure bonding device\n"); 635a9de470cSBruce Richardson 63677339255SIvan Ilchenko retval = rte_eth_dev_info_get(test_params.bond_port_id, 637a9de470cSBruce Richardson &test_params.bond_dev_info); 63877339255SIvan Ilchenko TEST_ASSERT((retval == 0), 63977339255SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 64077339255SIvan Ilchenko test_params.bond_port_id, strerror(-retval)); 641a9de470cSBruce Richardson } 642a9de470cSBruce Richardson 643a9de470cSBruce Richardson return TEST_SUCCESS; 644a9de470cSBruce Richardson } 645a9de470cSBruce Richardson 646a9de470cSBruce Richardson static void 647a9de470cSBruce Richardson testsuite_teardown(void) 648a9de470cSBruce Richardson { 64915e34522SLong Wu struct member_conf *port; 650a9de470cSBruce Richardson uint8_t i; 651a9de470cSBruce Richardson 652a9de470cSBruce Richardson /* Only stop ports. 653a9de470cSBruce Richardson * Any cleanup/reset state is done when particular test is 654a9de470cSBruce Richardson * started. */ 655a9de470cSBruce Richardson 656a9de470cSBruce Richardson rte_eth_dev_stop(test_params.bond_port_id); 657a9de470cSBruce Richardson 658a9de470cSBruce Richardson FOR_EACH_PORT(i, port) 659a9de470cSBruce Richardson rte_eth_dev_stop(port->port_id); 660a9de470cSBruce Richardson } 661a9de470cSBruce Richardson 662a9de470cSBruce Richardson static int 663a9de470cSBruce Richardson check_environment(void) 664a9de470cSBruce Richardson { 665a9de470cSBruce Richardson return TEST_SUCCESS; 666a9de470cSBruce Richardson } 667a9de470cSBruce Richardson 668a9de470cSBruce Richardson static int 669a9de470cSBruce Richardson test_rssconf_executor(int (*test_func)(void)) 670a9de470cSBruce Richardson { 671a9de470cSBruce Richardson int test_result; 672a9de470cSBruce Richardson 673a9de470cSBruce Richardson /* Check if environment is clean. Fail to launch a test if there was 674a9de470cSBruce Richardson * a critical error before that prevented to reset environment. */ 675a9de470cSBruce Richardson TEST_ASSERT_SUCCESS(check_environment(), 676a9de470cSBruce Richardson "Refusing to launch test in dirty environment."); 677a9de470cSBruce Richardson 678a9de470cSBruce Richardson RTE_VERIFY(test_func != NULL); 679a9de470cSBruce Richardson test_result = (*test_func)(); 680a9de470cSBruce Richardson 681a9de470cSBruce Richardson /* If test succeed check if environment wast left in good condition. */ 682a9de470cSBruce Richardson if (test_result == TEST_SUCCESS) 683a9de470cSBruce Richardson test_result = check_environment(); 684a9de470cSBruce Richardson 685a9de470cSBruce Richardson /* Reset environment in case test failed to do that. */ 686a9de470cSBruce Richardson if (test_result != TEST_SUCCESS) { 6874f840086SLong Wu TEST_ASSERT_SUCCESS(remove_members_and_stop_bonding_device(), 6884f840086SLong Wu "Failed to stop bonding device"); 689a9de470cSBruce Richardson } 690a9de470cSBruce Richardson 691a9de470cSBruce Richardson return test_result; 692a9de470cSBruce Richardson } 693a9de470cSBruce Richardson 694a9de470cSBruce Richardson static int 695a9de470cSBruce Richardson test_setup_wrapper(void) 696a9de470cSBruce Richardson { 697a9de470cSBruce Richardson return test_rssconf_executor(&test_setup); 698a9de470cSBruce Richardson } 699a9de470cSBruce Richardson 700a9de470cSBruce Richardson static int 701a9de470cSBruce Richardson test_rss_wrapper(void) 702a9de470cSBruce Richardson { 703a9de470cSBruce Richardson return test_rssconf_executor(&test_rss); 704a9de470cSBruce Richardson } 705a9de470cSBruce Richardson 706a9de470cSBruce Richardson static int 707a9de470cSBruce Richardson test_rss_lazy_wrapper(void) 708a9de470cSBruce Richardson { 709a9de470cSBruce Richardson return test_rssconf_executor(&test_rss_lazy); 710a9de470cSBruce Richardson } 711a9de470cSBruce Richardson 712a9de470cSBruce Richardson static struct unit_test_suite link_bonding_rssconf_test_suite = { 713a9de470cSBruce Richardson .suite_name = "RSS Dynamic Configuration for Bonding Unit Test Suite", 714a9de470cSBruce Richardson .teardown = testsuite_teardown, 715a9de470cSBruce Richardson .unit_test_cases = { 716a9de470cSBruce Richardson TEST_CASE_NAMED("test_setup", test_setup_wrapper), 717a9de470cSBruce Richardson TEST_CASE_NAMED("test_rss", test_rss_wrapper), 718a9de470cSBruce Richardson TEST_CASE_NAMED("test_rss_lazy", test_rss_lazy_wrapper), 719a9de470cSBruce Richardson 720a9de470cSBruce Richardson TEST_CASES_END() 721a9de470cSBruce Richardson } 722a9de470cSBruce Richardson }; 723a9de470cSBruce Richardson 724a9de470cSBruce Richardson static int 725a9de470cSBruce Richardson test_link_bonding_rssconf(void) 726a9de470cSBruce Richardson { 727a9de470cSBruce Richardson return unit_test_suite_runner(&link_bonding_rssconf_test_suite); 728a9de470cSBruce Richardson } 729a9de470cSBruce Richardson 730d83fb967SDavid Marchand REGISTER_DRIVER_TEST(link_bonding_rssconf_autotest, test_link_bonding_rssconf); 731