test: move unit tests to separate directory
[dpdk.git] / test / test / test_link_bonding_rssconf.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdint.h>
39 #include <inttypes.h>
40 #include <errno.h>
41 #include <rte_cycles.h>
42 #include <sys/queue.h>
43
44 #include <rte_byteorder.h>
45 #include <rte_common.h>
46 #include <rte_debug.h>
47 #include <rte_ethdev.h>
48 #include <rte_log.h>
49 #include <rte_lcore.h>
50 #include <rte_memory.h>
51
52 #include <rte_string_fns.h>
53 #include <rte_errno.h>
54 #include <rte_eth_bond.h>
55 #include <rte_eth_null.h>
56
57 #include "test.h"
58
59 #define SLAVE_COUNT (4)
60
61 #define RXTX_RING_SIZE                  1024
62 #define RXTX_QUEUE_COUNT                4
63
64 #define BONDED_DEV_NAME         ("rssconf_bond_dev")
65
66 #define SLAVE_DEV_NAME_FMT      ("rssconf_slave%d")
67 #define SLAVE_RXTX_QUEUE_FMT      ("rssconf_slave%d_q%d")
68
69 #define NUM_MBUFS 8191
70 #define MBUF_SIZE (1600 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
71 #define MBUF_CACHE_SIZE 250
72 #define BURST_SIZE 32
73
74 #define INVALID_SOCKET_ID       (-1)
75 #define INVALID_PORT_ID         (0xFF)
76 #define INVALID_BONDING_MODE    (-1)
77
78 struct slave_conf {
79         uint8_t port_id;
80         struct rte_eth_dev_info dev_info;
81
82         struct rte_eth_rss_conf rss_conf;
83         uint8_t rss_key[40];
84         struct rte_eth_rss_reta_entry64 reta_conf[512 / RTE_RETA_GROUP_SIZE];
85
86         uint8_t is_slave;
87         struct rte_ring *rxtx_queue[RXTX_QUEUE_COUNT];
88 };
89
90 struct link_bonding_rssconf_unittest_params {
91         uint8_t bond_port_id;
92         struct rte_eth_dev_info bond_dev_info;
93         struct rte_eth_rss_reta_entry64 bond_reta_conf[512 / RTE_RETA_GROUP_SIZE];
94         struct slave_conf slave_ports[SLAVE_COUNT];
95
96         struct rte_mempool *mbuf_pool;
97 };
98
99 static struct link_bonding_rssconf_unittest_params test_params  = {
100         .bond_port_id = INVALID_PORT_ID,
101         .slave_ports = {
102                 [0 ... SLAVE_COUNT - 1] = { .port_id = INVALID_PORT_ID, .is_slave = 0}
103         },
104         .mbuf_pool = NULL,
105 };
106
107 /**
108  * Default port configuration with RSS turned off
109  */
110 static struct rte_eth_conf default_pmd_conf = {
111         .rxmode = {
112                 .mq_mode = ETH_MQ_RX_NONE,
113                 .max_rx_pkt_len = ETHER_MAX_LEN,
114                 .split_hdr_size = 0,
115                 .header_split   = 0, /**< Header Split disabled */
116                 .hw_ip_checksum = 0, /**< IP checksum offload enabled */
117                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
118                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
119                 .hw_strip_crc   = 0, /**< CRC stripped by hardware */
120         },
121         .txmode = {
122                 .mq_mode = ETH_MQ_TX_NONE,
123         },
124         .lpbk_mode = 0,
125 };
126
127 static struct rte_eth_conf rss_pmd_conf = {
128         .rxmode = {
129                 .mq_mode = ETH_MQ_RX_RSS,
130                 .max_rx_pkt_len = ETHER_MAX_LEN,
131                 .split_hdr_size = 0,
132                 .header_split   = 0, /**< Header Split disabled */
133                 .hw_ip_checksum = 0, /**< IP checksum offload enabled */
134                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
135                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
136                 .hw_strip_crc   = 0, /**< CRC stripped by hardware */
137         },
138         .txmode = {
139                 .mq_mode = ETH_MQ_TX_NONE,
140         },
141         .rx_adv_conf = {
142                 .rss_conf = {
143                         .rss_key = NULL,
144                         .rss_hf = ETH_RSS_IPV6,
145                 },
146         },
147         .lpbk_mode = 0,
148 };
149
150 #define FOR_EACH(_i, _item, _array, _size) \
151         for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
152
153 /* Macro for iterating over every port that can be used as a slave
154  * in this test.
155  * _i variable used as an index in test_params->slave_ports
156  * _slave pointer to &test_params->slave_ports[_idx]
157  */
158 #define FOR_EACH_PORT(_i, _port) \
159         FOR_EACH(_i, _port, test_params.slave_ports, \
160                 RTE_DIM(test_params.slave_ports))
161
162 static int
163 configure_ethdev(uint8_t port_id, struct rte_eth_conf *eth_conf, uint8_t start)
164 {
165         int rxq, txq;
166
167         TEST_ASSERT(rte_eth_dev_configure(port_id, RXTX_QUEUE_COUNT,
168                         RXTX_QUEUE_COUNT, eth_conf) == 0, "Failed to configure device %u",
169                         port_id);
170
171         for (rxq = 0; rxq < RXTX_QUEUE_COUNT; rxq++) {
172                 TEST_ASSERT(rte_eth_rx_queue_setup(port_id, rxq, RXTX_RING_SIZE,
173                                 rte_eth_dev_socket_id(port_id), NULL,
174                                 test_params.mbuf_pool) == 0, "Failed to setup rx queue.");
175         }
176
177         for (txq = 0; txq < RXTX_QUEUE_COUNT; txq++) {
178                 TEST_ASSERT(rte_eth_tx_queue_setup(port_id, txq, RXTX_RING_SIZE,
179                                 rte_eth_dev_socket_id(port_id), NULL) == 0,
180                                 "Failed to setup tx queue.");
181         }
182
183         if (start) {
184                 TEST_ASSERT(rte_eth_dev_start(port_id) == 0,
185                 "Failed to start device (%d).", port_id);
186         }
187
188         return 0;
189 }
190
191 /**
192  * Remove all slaves from bonding
193  */
194 static int
195 remove_slaves(void)
196 {
197         unsigned n;
198         struct slave_conf *port;
199
200         FOR_EACH_PORT(n, port) {
201                 port = &test_params.slave_ports[n];
202                 if (port->is_slave) {
203                         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(
204                                         test_params.bond_port_id, port->port_id),
205                                         "Cannot remove slave %d from bonding", port->port_id);
206                         port->is_slave = 0;
207                 }
208         }
209
210         return 0;
211 }
212
213 static int
214 remove_slaves_and_stop_bonded_device(void)
215 {
216         TEST_ASSERT_SUCCESS(remove_slaves(), "Removing slaves");
217         rte_eth_dev_stop(test_params.bond_port_id);
218         return TEST_SUCCESS;
219 }
220
221 /**
222  * Add all slaves to bonding
223  */
224 static int
225 bond_slaves(void)
226 {
227         unsigned n;
228         struct slave_conf *port;
229
230         FOR_EACH_PORT(n, port) {
231                 port = &test_params.slave_ports[n];
232                 if (!port->is_slave) {
233                         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bond_port_id,
234                                         port->port_id), "Cannot attach slave %d to the bonding",
235                                         port->port_id);
236                         port->is_slave = 1;
237                 }
238         }
239
240         return 0;
241 }
242
243 /**
244  * Set all RETA values in port_id to value
245  */
246 static int
247 reta_set(uint8_t port_id, uint8_t value, int reta_size)
248 {
249         struct rte_eth_rss_reta_entry64 reta_conf[512/RTE_RETA_GROUP_SIZE];
250         int i, j;
251
252         for (i = 0; i < reta_size / RTE_RETA_GROUP_SIZE; i++) {
253                 /* select all fields to set */
254                 reta_conf[i].mask = ~0LL;
255                 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
256                         reta_conf[i].reta[j] = value;
257         }
258
259         return rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size);
260 }
261
262 /**
263  * Check if slaves RETA is synchronized with bonding port. Returns 1 if slave
264  * port is synced with bonding port.
265  */
266 static int
267 reta_check_synced(struct slave_conf *port)
268 {
269         unsigned i;
270
271         for (i = 0; i < test_params.bond_dev_info.reta_size;
272                         i++) {
273
274                 int index = i / RTE_RETA_GROUP_SIZE;
275                 int shift = i % RTE_RETA_GROUP_SIZE;
276
277                 if (port->reta_conf[index].reta[shift] !=
278                                 test_params.bond_reta_conf[index].reta[shift])
279                         return 0;
280
281         }
282
283         return 1;
284 }
285
286 /**
287  * Fetch bonding ports RETA
288  */
289 static int
290 bond_reta_fetch(void) {
291         unsigned j;
292
293         for (j = 0; j < test_params.bond_dev_info.reta_size / RTE_RETA_GROUP_SIZE;
294                         j++)
295                 test_params.bond_reta_conf[j].mask = ~0LL;
296
297         TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(test_params.bond_port_id,
298                         test_params.bond_reta_conf, test_params.bond_dev_info.reta_size),
299                         "Cannot take bonding ports RSS configuration");
300         return 0;
301 }
302
303 /**
304  * Fetch slaves RETA
305  */
306 static int
307 slave_reta_fetch(struct slave_conf *port) {
308         unsigned j;
309
310         for (j = 0; j < port->dev_info.reta_size / RTE_RETA_GROUP_SIZE; j++)
311                 port->reta_conf[j].mask = ~0LL;
312
313         TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(port->port_id,
314                         port->reta_conf, port->dev_info.reta_size),
315                         "Cannot take bonding ports RSS configuration");
316         return 0;
317 }
318
319 /**
320  * Remove and add slave to check if slaves configuration is synced with
321  * the bonding ports values after adding new slave.
322  */
323 static int
324 slave_remove_and_add(void)
325 {
326         struct slave_conf *port = &(test_params.slave_ports[0]);
327
328         /* 1. Remove first slave from bonding */
329         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(test_params.bond_port_id,
330                         port->port_id), "Cannot remove slave #d from bonding");
331
332         /* 2. Change removed (ex-)slave and bonding configuration to different
333          *    values
334          */
335         reta_set(test_params.bond_port_id, 1, test_params.bond_dev_info.reta_size);
336         bond_reta_fetch();
337
338         reta_set(port->port_id, 2, port->dev_info.reta_size);
339         slave_reta_fetch(port);
340
341         TEST_ASSERT(reta_check_synced(port) == 0,
342                         "Removed slave didn't should be synchronized with bonding port");
343
344         /* 3. Add (ex-)slave and check if configuration changed*/
345         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bond_port_id,
346                         port->port_id), "Cannot add slave");
347
348         bond_reta_fetch();
349         slave_reta_fetch(port);
350
351         return reta_check_synced(port);
352 }
353
354 /**
355  * Test configuration propagation over slaves.
356  */
357 static int
358 test_propagate(void)
359 {
360         unsigned i;
361         uint8_t n;
362         struct slave_conf *port;
363         uint8_t bond_rss_key[40];
364         struct rte_eth_rss_conf bond_rss_conf;
365
366         int retval = 0;
367         uint64_t rss_hf = 0;
368         uint64_t default_rss_hf = 0;
369
370         rte_eth_dev_info_get(test_params.bond_port_id, &test_params.bond_dev_info);
371
372         /*
373          *  Test hash function propagation
374          */
375         for (i = 0; i < sizeof(test_params.bond_dev_info.flow_type_rss_offloads)*8;
376                         i++) {
377
378                 rss_hf = test_params.bond_dev_info.flow_type_rss_offloads & (1<<i);
379                 if (rss_hf) {
380                         bond_rss_conf.rss_key = NULL;
381                         bond_rss_conf.rss_hf = rss_hf;
382
383                         retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id,
384                                         &bond_rss_conf);
385                         TEST_ASSERT_SUCCESS(retval, "Cannot set slaves hash function");
386
387                         FOR_EACH_PORT(n, port) {
388                                 port = &test_params.slave_ports[n];
389
390                                 retval = rte_eth_dev_rss_hash_conf_get(port->port_id,
391                                                 &port->rss_conf);
392                                 TEST_ASSERT_SUCCESS(retval,
393                                                 "Cannot take slaves RSS configuration");
394
395                                 TEST_ASSERT(port->rss_conf.rss_hf == rss_hf,
396                                                 "Hash function not propagated for slave %d",
397                                                 port->port_id);
398                         }
399
400                         default_rss_hf = rss_hf;
401                 }
402
403         }
404
405         /*
406          *  Test key propagation
407          */
408         for (i = 1; i < 10; i++) {
409
410                 /* Set all keys to zero */
411                 FOR_EACH_PORT(n, port) {
412                         port = &test_params.slave_ports[n];
413                         memset(port->rss_conf.rss_key, 0, 40);
414                         retval = rte_eth_dev_rss_hash_update(port->port_id,
415                                         &port->rss_conf);
416                         TEST_ASSERT_SUCCESS(retval, "Cannot set slaves RSS keys");
417                 }
418
419                 memset(bond_rss_key, i, sizeof(bond_rss_key));
420                 bond_rss_conf.rss_hf = default_rss_hf,
421                 bond_rss_conf.rss_key = bond_rss_key;
422                 bond_rss_conf.rss_key_len = 40;
423
424                 retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id,
425                                 &bond_rss_conf);
426                 TEST_ASSERT_SUCCESS(retval, "Cannot set bonded port RSS keys");
427
428                 FOR_EACH_PORT(n, port) {
429                         port = &test_params.slave_ports[n];
430
431                         retval = rte_eth_dev_rss_hash_conf_get(port->port_id,
432                                         &(port->rss_conf));
433
434                         TEST_ASSERT_SUCCESS(retval,
435                                         "Cannot take slaves RSS configuration");
436
437                         /* compare keys */
438                         retval = memcmp(port->rss_conf.rss_key, bond_rss_key,
439                                         sizeof(bond_rss_key));
440                         TEST_ASSERT(retval == 0, "Key value not propagated for slave %d",
441                                         port->port_id);
442                 }
443         }
444
445         /*
446          *  Test RETA propagation
447          */
448         for (i = 0; i < RXTX_QUEUE_COUNT; i++) {
449
450                 /* Set all keys to zero */
451                 FOR_EACH_PORT(n, port) {
452                         port = &test_params.slave_ports[n];
453                         retval = reta_set(port->port_id, (i + 1) % RXTX_QUEUE_COUNT,
454                                         port->dev_info.reta_size);
455                         TEST_ASSERT_SUCCESS(retval, "Cannot set slaves RETA");
456                 }
457
458                 TEST_ASSERT_SUCCESS(reta_set(test_params.bond_port_id,
459                                 i % RXTX_QUEUE_COUNT, test_params.bond_dev_info.reta_size),
460                                 "Cannot set bonded port RETA");
461
462                 bond_reta_fetch();
463
464                 FOR_EACH_PORT(n, port) {
465                         port = &test_params.slave_ports[n];
466
467                         slave_reta_fetch(port);
468                         TEST_ASSERT(reta_check_synced(port) == 1, "RETAs inconsistent");
469                 }
470         }
471
472         return TEST_SUCCESS;
473 }
474
475 /**
476  * Test propagation logic, when RX_RSS mq_mode is turned on for bonding port
477  */
478 static int
479 test_rss(void)
480 {
481         /**
482          * Configure bonding port in RSS mq mode
483          */
484         TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id,
485                         &rss_pmd_conf, 0), "Failed to configure bonding device\n");
486
487         rte_eth_dev_info_get(test_params.bond_port_id, &test_params.bond_dev_info);
488
489         TEST_ASSERT_SUCCESS(bond_slaves(), "Bonding slaves failed");
490
491         TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id),
492                         "Failed to start bonding port (%d).", test_params.bond_port_id);
493
494         TEST_ASSERT_SUCCESS(test_propagate(), "Propagation test failed");
495
496         TEST_ASSERT(slave_remove_and_add() == 1, "New slave should be synced");
497
498         remove_slaves_and_stop_bonded_device();
499
500         return TEST_SUCCESS;
501 }
502
503 /**
504  * Test propagation logic, when RX_RSS mq_mode is turned off for bonding port
505  */
506 static int
507 test_rss_lazy(void)
508 {
509         TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id,
510                         &default_pmd_conf, 0), "Failed to configure bonding device\n");
511
512         rte_eth_dev_info_get(test_params.bond_port_id, &test_params.bond_dev_info);
513
514         TEST_ASSERT_SUCCESS(bond_slaves(), "Bonding slaves failed");
515
516         TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id),
517                         "Failed to start bonding port (%d).", test_params.bond_port_id);
518
519         TEST_ASSERT_SUCCESS(test_propagate(), "Propagation test failed");
520
521         TEST_ASSERT(slave_remove_and_add() == 0, "New slave shouldn't be synced");
522
523         remove_slaves_and_stop_bonded_device();
524
525         return TEST_SUCCESS;
526 }
527
528 static int
529 test_setup(void)
530 {
531         unsigned n;
532         int retval;
533         int port_id;
534         char name[256];
535         struct slave_conf *port;
536
537         if (test_params.mbuf_pool == NULL) {
538
539                 test_params.mbuf_pool = rte_mempool_create("RSS_MBUF_POOL", NUM_MBUFS *
540                                 SLAVE_COUNT, MBUF_SIZE, MBUF_CACHE_SIZE,
541                                 sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init,
542                                 NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0);
543
544                 TEST_ASSERT(test_params.mbuf_pool != NULL,
545                                 "rte_mempool_create failed\n");
546         }
547
548         /* Create / initialize ring eth devs. */
549         FOR_EACH_PORT(n, port) {
550                 port = &test_params.slave_ports[n];
551
552                 port_id = rte_eth_dev_count();
553                 snprintf(name, sizeof(name), SLAVE_DEV_NAME_FMT, port_id);
554
555                 retval = eth_dev_null_create(name, 0, 64, 0);
556                 TEST_ASSERT_SUCCESS(retval, "Failed to create null device '%s'\n",
557                                 name);
558
559                 port->port_id = port_id;
560
561                 port->rss_conf.rss_key = port->rss_key;
562                 port->rss_conf.rss_key_len = 40;
563
564                 retval = configure_ethdev(port->port_id, &default_pmd_conf, 0);
565                 TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n",
566                                 name);
567
568                 rte_eth_dev_info_get(port->port_id, &port->dev_info);
569         }
570
571         if (test_params.bond_port_id == INVALID_PORT_ID) {
572                 retval = rte_eth_bond_create(BONDED_DEV_NAME, 0, rte_socket_id());
573
574                 TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s",
575                                 BONDED_DEV_NAME);
576
577                 test_params.bond_port_id = retval;
578
579                 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id,
580                                 &default_pmd_conf, 0), "Failed to configure bonding device\n");
581
582                 rte_eth_dev_info_get(test_params.bond_port_id,
583                                 &test_params.bond_dev_info);
584         }
585
586         return TEST_SUCCESS;
587 }
588
589 static void
590 testsuite_teardown(void)
591 {
592         struct slave_conf *port;
593         uint8_t i;
594
595         /* Only stop ports.
596          * Any cleanup/reset state is done when particular test is
597          * started. */
598
599         rte_eth_dev_stop(test_params.bond_port_id);
600
601         FOR_EACH_PORT(i, port)
602                 rte_eth_dev_stop(port->port_id);
603 }
604
605 static int
606 check_environment(void)
607 {
608         return TEST_SUCCESS;
609 }
610
611 static int
612 test_rssconf_executor(int (*test_func)(void))
613 {
614         int test_result;
615
616         /* Check if environment is clean. Fail to launch a test if there was
617          * a critical error before that prevented to reset environment. */
618         TEST_ASSERT_SUCCESS(check_environment(),
619                 "Refusing to launch test in dirty environment.");
620
621         RTE_VERIFY(test_func != NULL);
622         test_result = (*test_func)();
623
624         /* If test succeed check if environment wast left in good condition. */
625         if (test_result == TEST_SUCCESS)
626                 test_result = check_environment();
627
628         /* Reset environment in case test failed to do that. */
629         if (test_result != TEST_SUCCESS) {
630                 TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
631                         "Failed to stop bonded device");
632         }
633
634         return test_result;
635 }
636
637 static int
638 test_setup_wrapper(void)
639 {
640         return test_rssconf_executor(&test_setup);
641 }
642
643 static int
644 test_rss_wrapper(void)
645 {
646         return test_rssconf_executor(&test_rss);
647 }
648
649 static int
650 test_rss_lazy_wrapper(void)
651 {
652         return test_rssconf_executor(&test_rss_lazy);
653 }
654
655 static struct unit_test_suite link_bonding_rssconf_test_suite  = {
656         .suite_name = "RSS Dynamic Configuration for Bonding Unit Test Suite",
657         .teardown = testsuite_teardown,
658         .unit_test_cases = {
659                 TEST_CASE_NAMED("test_setup", test_setup_wrapper),
660                 TEST_CASE_NAMED("test_rss", test_rss_wrapper),
661                 TEST_CASE_NAMED("test_rss_lazy", test_rss_lazy_wrapper),
662
663                 TEST_CASES_END()
664         }
665 };
666
667 static int
668 test_link_bonding_rssconf(void)
669 {
670         return unit_test_suite_runner(&link_bonding_rssconf_test_suite);
671 }
672
673 REGISTER_TEST_COMMAND(link_bonding_rssconf_autotest, test_link_bonding_rssconf);