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