bond: support link status polling
[dpdk.git] / app / test / test_link_bonding.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 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 <sys/queue.h>
42 #include <sys/time.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 #include <rte_string_fns.h>
52 #include <rte_eth_bond.h>
53
54 #include "virtual_pmd.h"
55 #include "packet_burst_generator.h"
56
57 #include "test.h"
58
59 #define TEST_MAX_NUMBER_OF_PORTS (16)
60
61 #define RX_RING_SIZE 128
62 #define RX_FREE_THRESH 32
63 #define RX_PTHRESH 8
64 #define RX_HTHRESH 8
65 #define RX_WTHRESH 0
66
67 #define TX_RING_SIZE 512
68 #define TX_FREE_THRESH 32
69 #define TX_PTHRESH 32
70 #define TX_HTHRESH 0
71 #define TX_WTHRESH 0
72 #define TX_RSBIT_THRESH 32
73 #define TX_Q_FLAGS (ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOVLANOFFL |\
74         ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \
75         ETH_TXQ_FLAGS_NOXSUMTCP)
76
77 #define MBUF_PAYLOAD_SIZE       (2048)
78 #define MBUF_SIZE (MBUF_PAYLOAD_SIZE + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
79 #define MBUF_CACHE_SIZE (250)
80 #define BURST_SIZE (32)
81
82 #define DEFAULT_MBUF_DATA_SIZE  (2048)
83 #define RTE_TEST_RX_DESC_MAX    (2048)
84 #define RTE_TEST_TX_DESC_MAX    (2048)
85 #define MAX_PKT_BURST                   (512)
86 #define DEF_PKT_BURST                   (16)
87
88 #define BONDED_DEV_NAME                 ("unit_test_bonded_device")
89
90 #define INVALID_SOCKET_ID               (-1)
91 #define INVALID_PORT_ID                 (-1)
92 #define INVALID_BONDING_MODE    (-1)
93
94
95 uint8_t slave_mac[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 };
96 uint8_t bonded_mac[] = {0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
97
98 struct link_bonding_unittest_params {
99         int8_t bonded_port_id;
100         int8_t slave_port_ids[TEST_MAX_NUMBER_OF_PORTS];
101         uint8_t bonded_slave_count;
102         uint8_t bonding_mode;
103
104         uint16_t nb_rx_q;
105         uint16_t nb_tx_q;
106
107         struct rte_mempool *mbuf_pool;
108
109         struct ether_addr *default_slave_mac;
110         struct ether_addr *default_bonded_mac;
111
112         /* Packet Headers */
113         struct ether_hdr *pkt_eth_hdr;
114         struct ipv4_hdr *pkt_ipv4_hdr;
115         struct ipv6_hdr *pkt_ipv6_hdr;
116         struct udp_hdr *pkt_udp_hdr;
117
118 };
119
120 static struct ipv4_hdr pkt_ipv4_hdr;
121 static struct ipv6_hdr pkt_ipv6_hdr;
122 static struct udp_hdr pkt_udp_hdr;
123
124 static struct link_bonding_unittest_params default_params  = {
125         .bonded_port_id = -1,
126         .slave_port_ids = { -1 },
127         .bonded_slave_count = 0,
128         .bonding_mode = BONDING_MODE_ROUND_ROBIN,
129
130         .nb_rx_q = 1,
131         .nb_tx_q = 1,
132
133         .mbuf_pool = NULL,
134
135         .default_slave_mac = (struct ether_addr *)slave_mac,
136         .default_bonded_mac = (struct ether_addr *)bonded_mac,
137
138         .pkt_eth_hdr = NULL,
139         .pkt_ipv4_hdr = &pkt_ipv4_hdr,
140         .pkt_ipv6_hdr = &pkt_ipv6_hdr,
141         .pkt_udp_hdr = &pkt_udp_hdr
142
143 };
144
145 static struct link_bonding_unittest_params *test_params = &default_params;
146
147 static uint8_t src_mac[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
148 static uint8_t dst_mac_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
149 static uint8_t dst_mac_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAB };
150
151 static uint32_t src_addr = IPV4_ADDR(192, 168, 1, 98);
152 static uint32_t dst_addr_0 = IPV4_ADDR(192, 168, 1, 98);
153 static uint32_t dst_addr_1 = IPV4_ADDR(193, 166, 10, 97);
154
155 static uint8_t src_ipv6_addr[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
156                 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA  };
157 static uint8_t dst_ipv6_addr_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
158                 0xAA, 0xFF, 0xAA,  0xFF, 0xAA , 0xFF, 0xAA, 0xFF, 0xAA  };
159 static uint8_t dst_ipv6_addr_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
160                 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA , 0xFF, 0xAB  };
161
162 static uint16_t src_port = 1024;
163 static uint16_t dst_port_0 = 1024;
164 static uint16_t dst_port_1 = 2024;
165
166 static uint16_t vlan_id = 0x100;
167
168 struct rte_eth_rxmode rx_mode = {
169         .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */
170         .split_hdr_size = 0,
171         .header_split   = 0, /**< Header Split disabled. */
172         .hw_ip_checksum = 0, /**< IP checksum offload disabled. */
173         .hw_vlan_filter = 1, /**< VLAN filtering enabled. */
174         .hw_vlan_strip  = 1, /**< VLAN strip enabled. */
175         .hw_vlan_extend = 0, /**< Extended VLAN disabled. */
176         .jumbo_frame    = 0, /**< Jumbo Frame Support disabled. */
177         .hw_strip_crc   = 0, /**< CRC stripping by hardware disabled. */
178 };
179
180 struct rte_fdir_conf fdir_conf = {
181         .mode = RTE_FDIR_MODE_NONE,
182         .pballoc = RTE_FDIR_PBALLOC_64K,
183         .status = RTE_FDIR_REPORT_STATUS,
184         .flexbytes_offset = 0x6,
185         .drop_queue = 127,
186 };
187
188 static struct rte_eth_conf default_pmd_conf = {
189         .rxmode = {
190                 .mq_mode = ETH_MQ_RX_NONE,
191                 .max_rx_pkt_len = ETHER_MAX_LEN,
192                 .split_hdr_size = 0,
193                 .header_split   = 0, /**< Header Split disabled */
194                 .hw_ip_checksum = 0, /**< IP checksum offload enabled */
195                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
196                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
197                 .hw_strip_crc   = 0, /**< CRC stripped by hardware */
198         },
199         .txmode = {
200                 .mq_mode = ETH_MQ_TX_NONE,
201         },
202         .lpbk_mode = 0,
203 };
204
205 static const struct rte_eth_rxconf rx_conf_default = {
206         .rx_thresh = {
207                 .pthresh = RX_PTHRESH,
208                 .hthresh = RX_HTHRESH,
209                 .wthresh = RX_WTHRESH,
210         },
211         .rx_free_thresh = RX_FREE_THRESH,
212         .rx_drop_en = 0,
213 };
214
215 static struct rte_eth_txconf tx_conf_default = {
216         .tx_thresh = {
217                 .pthresh = TX_PTHRESH,
218                 .hthresh = TX_HTHRESH,
219                 .wthresh = TX_WTHRESH,
220         },
221         .tx_free_thresh = TX_FREE_THRESH,
222         .tx_rs_thresh = TX_RSBIT_THRESH,
223         .txq_flags = TX_Q_FLAGS
224
225 };
226
227 static int
228 configure_ethdev(uint8_t port_id, uint8_t start, uint8_t en_isr)
229 {
230         int q_id;
231
232         if (en_isr)
233                 default_pmd_conf.intr_conf.lsc = 1;
234         else
235                 default_pmd_conf.intr_conf.lsc = 0;
236
237         TEST_ASSERT_SUCCESS(rte_eth_dev_configure(port_id, test_params->nb_rx_q,
238                         test_params->nb_tx_q, &default_pmd_conf),
239                         "rte_eth_dev_configure for port %d failed", port_id);
240
241         for (q_id = 0; q_id < test_params->nb_rx_q; q_id++)
242                 TEST_ASSERT_SUCCESS(rte_eth_rx_queue_setup(port_id, q_id, RX_RING_SIZE,
243                                 rte_eth_dev_socket_id(port_id), &rx_conf_default,
244                                 test_params->mbuf_pool) ,
245                                 "rte_eth_rx_queue_setup for port %d failed", port_id);
246
247         for (q_id = 0; q_id < test_params->nb_tx_q; q_id++)
248                 TEST_ASSERT_SUCCESS(rte_eth_tx_queue_setup(port_id, q_id, TX_RING_SIZE,
249                                 rte_eth_dev_socket_id(port_id), &tx_conf_default),
250                                 "rte_eth_tx_queue_setup for port %d failed", port_id);
251
252         if (start)
253                 TEST_ASSERT_SUCCESS(rte_eth_dev_start(port_id),
254                                 "rte_eth_dev_start for port %d failed", port_id);
255
256         return 0;
257 }
258
259 static int slaves_initialized;
260
261 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
262 static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
263
264
265 static int
266 test_setup(void)
267 {
268         int i, retval, nb_mbuf_per_pool;
269         struct ether_addr *mac_addr = (struct ether_addr *)slave_mac;
270
271         /* Allocate ethernet packet header with space for VLAN header */
272         if (test_params->pkt_eth_hdr == NULL) {
273                 test_params->pkt_eth_hdr = malloc(sizeof(struct ether_hdr) +
274                                 sizeof(struct vlan_hdr));
275
276                 if (test_params->pkt_eth_hdr == NULL) {
277                         printf("ethernet header struct allocation failed!\n");
278                         return -1;
279                 }
280         }
281
282         nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + DEF_PKT_BURST +
283                         RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
284         if (test_params->mbuf_pool == NULL) {
285                 test_params->mbuf_pool = rte_mempool_create("MBUF_POOL", nb_mbuf_per_pool,
286                                 MBUF_SIZE, MBUF_CACHE_SIZE, sizeof(struct rte_pktmbuf_pool_private),
287                                 rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL,
288                                 rte_socket_id(), 0);
289                 if (test_params->mbuf_pool == NULL) {
290                         printf("rte_mempool_create failed\n");
291                         return -1;
292                 }
293         }
294
295         /* Create / Initialize virtual eth devs */
296         if (!slaves_initialized) {
297                 for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) {
298                         char pmd_name[RTE_ETH_NAME_MAX_LEN];
299
300                         mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i;
301
302                         snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_%d", i);
303
304                         test_params->slave_port_ids[i] = virtual_ethdev_create(pmd_name,
305                                         mac_addr, rte_socket_id(), 1);
306                         if (test_params->slave_port_ids[i] < 0) {
307                                 printf("Failed to create virtual virtual ethdev %s\n", pmd_name);
308                                 return -1;
309                         }
310
311                         printf("Created virtual ethdev %s\n", pmd_name);
312
313                         retval = configure_ethdev(test_params->slave_port_ids[i], 1, 0);
314                         if (retval != 0) {
315                                 printf("Failed to configure virtual ethdev %s\n", pmd_name);
316                                 return -1;
317                         }
318
319                         printf("Configured virtual ethdev %s\n", pmd_name);
320                 }
321                 slaves_initialized = 1;
322         }
323
324         return 0;
325 }
326
327 static int
328 test_create_bonded_device(void)
329 {
330         int current_slave_count;
331
332         uint8_t slaves[RTE_MAX_ETHPORTS];
333
334         /* Don't try to recreate bonded device if re-running test suite*/
335         if (test_params->bonded_port_id == -1) {
336                 test_params->bonded_port_id = rte_eth_bond_create(BONDED_DEV_NAME,
337                                 test_params->bonding_mode, rte_socket_id());
338
339                 TEST_ASSERT(test_params->bonded_port_id >= 0,
340                                 "Failed to create bonded ethdev %s", BONDED_DEV_NAME);
341
342                 TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
343                                 "Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
344         }
345
346         TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
347                         test_params->bonding_mode), "Failed to set ethdev %d to mode %d",
348                         test_params->bonded_port_id, test_params->bonding_mode);
349
350         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
351                         slaves, RTE_MAX_ETHPORTS);
352
353         TEST_ASSERT(current_slave_count == 0,
354                         "Number of slaves %d is great than expected %d.",
355                         current_slave_count, 0);
356
357         current_slave_count = rte_eth_bond_active_slaves_get(
358                         test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
359
360         TEST_ASSERT(current_slave_count == 0,
361                         "Number of active slaves %d is great than expected %d.",
362                         current_slave_count, 0);
363
364         return 0;
365 }
366
367
368 static int
369 test_create_bonded_device_with_invalid_params(void)
370 {
371         int port_id;
372
373         test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN;
374
375         /* Invalid name */
376         port_id = rte_eth_bond_create(NULL, test_params->bonding_mode,
377                         rte_socket_id());
378         if (port_id >= 0) {
379                 printf("Created bonded device unexpectedly.\n");
380                 return -1;
381         }
382
383         test_params->bonding_mode = INVALID_BONDING_MODE;
384
385         /* Invalid bonding mode */
386         port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode,
387                         rte_socket_id());
388         if (port_id >= 0) {
389                 printf("Created bonded device unexpectedly.\n");
390                 return -1;
391         }
392
393         test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN;
394
395         /* Invalid socket id */
396         port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode,
397                         INVALID_SOCKET_ID);
398         if (port_id >= 0) {
399                 printf("Created bonded device unexpectedly.\n");
400                 return -1;
401         }
402
403         return 0;
404 }
405
406 static int
407 test_add_slave_to_bonded_device(void)
408 {
409         int current_slave_count;
410
411         uint8_t slaves[RTE_MAX_ETHPORTS];
412
413         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
414                         test_params->slave_port_ids[test_params->bonded_slave_count]),
415                         "Failed to add slave (%d) to bonded port (%d).",
416                         test_params->slave_port_ids[test_params->bonded_slave_count],
417                         test_params->bonded_port_id);
418
419         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
420                         slaves, RTE_MAX_ETHPORTS);
421         TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count + 1,
422                         "Number of slaves (%d) is greater than expected (%d).",
423                         current_slave_count, test_params->bonded_slave_count + 1);
424
425         current_slave_count = rte_eth_bond_active_slaves_get(
426                         test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
427         TEST_ASSERT_EQUAL(current_slave_count, 0,
428                                         "Number of active slaves (%d) is not as expected (%d).\n",
429                                         current_slave_count, 0);
430
431         test_params->bonded_slave_count++;
432
433         return 0;
434 }
435
436 static int
437 test_add_slave_to_invalid_bonded_device(void)
438 {
439         int retval;
440
441         /* Invalid port ID */
442         retval = rte_eth_bond_slave_add(test_params->bonded_port_id + 5,
443                         test_params->slave_port_ids[test_params->bonded_slave_count]);
444         if (retval == 0) {
445                 printf("Expected call to failed as invalid port specified.\n");
446                 return -1;
447         }
448
449         /* Non bonded device */
450         retval = rte_eth_bond_slave_add(test_params->slave_port_ids[0],
451                         test_params->slave_port_ids[test_params->bonded_slave_count]);
452         if (retval == 0) {
453                 printf("Expected call to failed as invalid port specified.\n");
454                 return -1;
455         }
456
457         return 0;
458 }
459
460
461 static int
462 test_remove_slave_from_bonded_device(void)
463 {
464         int current_slave_count;
465         struct ether_addr read_mac_addr, *mac_addr;
466         uint8_t slaves[RTE_MAX_ETHPORTS];
467
468         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(test_params->bonded_port_id,
469                         test_params->slave_port_ids[test_params->bonded_slave_count-1]),
470                         "Failed to remove slave %d from bonded port (%d).",
471                         test_params->slave_port_ids[test_params->bonded_slave_count-1],
472                         test_params->bonded_port_id);
473
474
475         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
476                         slaves, RTE_MAX_ETHPORTS);
477
478         TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count - 1,
479                         "Number of slaves (%d) is great than expected (%d).\n",
480                         current_slave_count, test_params->bonded_slave_count - 1);
481
482
483         mac_addr = (struct ether_addr *)slave_mac;
484         mac_addr->addr_bytes[ETHER_ADDR_LEN-1] =
485                         test_params->slave_port_ids[test_params->bonded_slave_count-1];
486
487         rte_eth_macaddr_get(
488                         test_params->slave_port_ids[test_params->bonded_slave_count-1],
489                         &read_mac_addr);
490         TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)),
491                         "bonded port mac address not set to that of primary port\n");
492
493         rte_eth_stats_reset(
494                         test_params->slave_port_ids[test_params->bonded_slave_count-1]);
495
496         virtual_ethdev_simulate_link_status_interrupt(test_params->bonded_port_id,
497                         0);
498
499         test_params->bonded_slave_count--;
500
501         return 0;
502 }
503
504 static int
505 test_remove_slave_from_invalid_bonded_device(void)
506 {
507         int retval;
508
509         /* Invalid port ID */
510         retval = rte_eth_bond_slave_remove(test_params->bonded_port_id + 5,
511                         test_params->slave_port_ids[test_params->bonded_slave_count - 1]);
512         if (retval == 0) {
513                 printf("Expected call to failed as invalid port specified.\n");
514                 return -1;
515         }
516
517         /* Non bonded device */
518         retval = rte_eth_bond_slave_remove(test_params->slave_port_ids[0],
519                         test_params->slave_port_ids[test_params->bonded_slave_count - 1]);
520         if (retval == 0) {
521                 printf("Expected call to failed as invalid port specified.\n");
522                 return -1;
523         }
524
525         return 0;
526 }
527
528 static int bonded_id = 2;
529
530 static int
531 test_add_already_bonded_slave_to_bonded_device(void)
532 {
533         int retval, port_id, current_slave_count;
534         uint8_t slaves[RTE_MAX_ETHPORTS];
535         char pmd_name[RTE_ETH_NAME_MAX_LEN];
536
537         test_add_slave_to_bonded_device();
538
539         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
540                         slaves, RTE_MAX_ETHPORTS);
541         if (current_slave_count != 1) {
542                 printf("Number of slaves (%d) is not that expected (%d).\n",
543                                 current_slave_count, 1);
544                 return -1;
545         }
546
547         snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "%s_%d", BONDED_DEV_NAME, ++bonded_id);
548
549         port_id = rte_eth_bond_create(pmd_name, test_params->bonding_mode,
550                         rte_socket_id());
551         if (port_id < 0) {
552                 printf("Failed to create bonded device.\n");
553                 return -1;
554         }
555
556         retval = rte_eth_bond_slave_add(port_id,
557                         test_params->slave_port_ids[test_params->bonded_slave_count - 1]);
558         if (retval == 0) {
559                 printf("Added slave (%d) to bonded port (%d) unexpectedly.\n",
560                                 test_params->slave_port_ids[test_params->bonded_slave_count-1],
561                                 port_id);
562                 return -1;
563         }
564
565         return test_remove_slave_from_bonded_device();
566 }
567
568
569 static int
570 test_get_slaves_from_bonded_device(void)
571 {
572         int retval, current_slave_count;
573
574         uint8_t slaves[RTE_MAX_ETHPORTS];
575
576         retval = test_add_slave_to_bonded_device();
577         if (retval != 0)
578                 return -1;
579
580         /* Invalid port id */
581         current_slave_count = rte_eth_bond_slaves_get(INVALID_PORT_ID, slaves,
582                         RTE_MAX_ETHPORTS);
583         if (current_slave_count >= 0)
584                 return -1;
585
586         current_slave_count = rte_eth_bond_active_slaves_get(INVALID_PORT_ID,
587                         slaves, RTE_MAX_ETHPORTS);
588         if (current_slave_count >= 0)
589                 return -1;
590
591         /* Invalid slaves pointer */
592         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
593                         NULL, RTE_MAX_ETHPORTS);
594         if (current_slave_count >= 0)
595                 return -1;
596
597         current_slave_count = rte_eth_bond_active_slaves_get(
598                         test_params->bonded_port_id, NULL, RTE_MAX_ETHPORTS);
599         if (current_slave_count >= 0)
600                 return -1;
601
602         /* non bonded device*/
603         current_slave_count = rte_eth_bond_slaves_get(
604                         test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS);
605         if (current_slave_count >= 0)
606                 return -1;
607
608         current_slave_count = rte_eth_bond_active_slaves_get(
609                         test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS);
610         if (current_slave_count >= 0)
611                 return -1;
612
613         retval = test_remove_slave_from_bonded_device();
614         if (retval != 0)
615                 return -1;
616
617         return 0;
618 }
619
620
621 static int
622 test_add_remove_multiple_slaves_to_from_bonded_device(void)
623 {
624         int i;
625
626         for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) {
627                 if (test_add_slave_to_bonded_device() != 0)
628                         return -1;
629         }
630
631         for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) {
632                 if (test_remove_slave_from_bonded_device() != 0)
633                         return -1;
634         }
635
636         return 0;
637 }
638
639 static void
640 enable_bonded_slaves(void)
641 {
642         int i;
643
644         for (i = 0; i < test_params->bonded_slave_count; i++) {
645                 virtual_ethdev_tx_burst_fn_set_success(test_params->slave_port_ids[i],
646                                 1);
647
648                 virtual_ethdev_simulate_link_status_interrupt(
649                                 test_params->slave_port_ids[i], 1);
650         }
651 }
652
653 static int
654 test_start_bonded_device(void)
655 {
656         struct rte_eth_link link_status;
657
658         int current_slave_count, current_bonding_mode, primary_port;
659         uint8_t slaves[RTE_MAX_ETHPORTS];
660
661         /* Add slave to bonded device*/
662         if (test_add_slave_to_bonded_device() != 0)
663                 return -1;
664
665         TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
666                 "Failed to start bonded pmd eth device %d.",
667                 test_params->bonded_port_id);
668
669         /* Change link status of virtual pmd so it will be added to the active
670          * slave list of the bonded device*/
671         virtual_ethdev_simulate_link_status_interrupt(
672                         test_params->slave_port_ids[test_params->bonded_slave_count-1], 1);
673
674         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
675                         slaves, RTE_MAX_ETHPORTS);
676         if (current_slave_count != test_params->bonded_slave_count) {
677                 printf("Number of slaves (%d) is not expected value (%d).\n",
678                                 current_slave_count, test_params->bonded_slave_count);
679                 return -1;
680         }
681
682         current_slave_count = rte_eth_bond_active_slaves_get(
683                         test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
684         if (current_slave_count != test_params->bonded_slave_count) {
685                 printf("Number of active slaves (%d) is not expected value (%d).\n",
686                                 current_slave_count, test_params->bonded_slave_count);
687                 return -1;
688         }
689
690         current_bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
691         if (current_bonding_mode != test_params->bonding_mode) {
692                 printf("Bonded device mode (%d) is not expected value (%d).\n",
693                                 current_bonding_mode, test_params->bonding_mode);
694                 return -1;
695
696         }
697
698         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
699         if (primary_port != test_params->slave_port_ids[0]) {
700                 printf("Primary port (%d) is not expected value (%d).\n",
701                                 primary_port, test_params->slave_port_ids[0]);
702                 return -1;
703
704         }
705
706         rte_eth_link_get(test_params->bonded_port_id, &link_status);
707         if (!link_status.link_status) {
708                 printf("Bonded port (%d) status (%d) is not expected value (%d).\n",
709                                 test_params->bonded_port_id, link_status.link_status, 1);
710                 return -1;
711
712         }
713
714         return 0;
715 }
716
717 static int
718 test_stop_bonded_device(void)
719 {
720         int current_slave_count;
721         uint8_t slaves[RTE_MAX_ETHPORTS];
722
723         struct rte_eth_link link_status;
724
725         rte_eth_dev_stop(test_params->bonded_port_id);
726
727         rte_eth_link_get(test_params->bonded_port_id, &link_status);
728         if (link_status.link_status) {
729                 printf("Bonded port (%d) status (%d) is not expected value (%d).\n",
730                                 test_params->bonded_port_id, link_status.link_status, 0);
731                 return -1;
732         }
733
734         current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
735                         slaves, RTE_MAX_ETHPORTS);
736         if (current_slave_count != test_params->bonded_slave_count) {
737                 printf("Number of slaves (%d) is not expected value (%d).\n",
738                                 current_slave_count, test_params->bonded_slave_count);
739                 return -1;
740         }
741
742         current_slave_count = rte_eth_bond_active_slaves_get(
743                         test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
744         if (current_slave_count != 0) {
745                 printf("Number of active slaves (%d) is not expected value (%d).\n",
746                                 current_slave_count, 0);
747                 return -1;
748         }
749
750         return 0;
751 }
752
753 static int remove_slaves_and_stop_bonded_device(void)
754 {
755         /* Clean up and remove slaves from bonded device */
756         while (test_params->bonded_slave_count > 0) {
757                 if (test_remove_slave_from_bonded_device() != 0) {
758                         printf("test_remove_slave_from_bonded_device failed\n");
759                         return -1;
760                 }
761         }
762
763         rte_eth_dev_stop(test_params->bonded_port_id);
764         rte_eth_stats_reset(test_params->bonded_port_id);
765         rte_eth_bond_mac_address_reset(test_params->bonded_port_id);
766
767         return 0;
768 }
769
770 static int
771 test_set_bonding_mode(void)
772 {
773         int i;
774         int retval, bonding_mode;
775
776         int bonding_modes[] = { BONDING_MODE_ROUND_ROBIN,
777                                                         BONDING_MODE_ACTIVE_BACKUP,
778                                                         BONDING_MODE_BALANCE,
779 #ifdef RTE_MBUF_REFCNT
780                                                         BONDING_MODE_BROADCAST
781 #endif
782                                                         };
783
784         /* Test supported link bonding modes */
785         for (i = 0; i < (int)RTE_DIM(bonding_modes);    i++) {
786                 /* Invalid port ID */
787                 retval = rte_eth_bond_mode_set(INVALID_PORT_ID, bonding_modes[i]);
788                 if (retval == 0) {
789                         printf("Expected call to failed as invalid port (%d) specified.\n",
790                                         INVALID_PORT_ID);
791                         return -1;
792                 }
793
794                 /* Non bonded device */
795                 retval = rte_eth_bond_mode_set(test_params->slave_port_ids[0],
796                                 bonding_modes[i]);
797                 if (retval == 0) {
798                         printf("Expected call to failed as invalid port (%d) specified.\n",
799                                         test_params->slave_port_ids[0]);
800                         return -1;
801                 }
802
803                 retval = rte_eth_bond_mode_set(test_params->bonded_port_id,
804                                 bonding_modes[i]);
805                 if (retval != 0) {
806                         printf("Failed to set link bonding mode on port (%d) to (%d).\n",
807                                         test_params->bonded_port_id, bonding_modes[i]);
808                         return -1;
809                 }
810
811                 bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
812                 if (bonding_mode != bonding_modes[i]) {
813                         printf("Link bonding mode (%d) of port (%d) is not expected value (%d).\n",
814                                         bonding_mode, test_params->bonded_port_id,
815                                         bonding_modes[i]);
816                         return -1;
817                 }
818
819
820                 /* Invalid port ID */
821                 bonding_mode = rte_eth_bond_mode_get(INVALID_PORT_ID);
822                 if (bonding_mode >= 0) {
823                         printf("Expected call to failed as invalid port (%d) specified.\n",
824                                         INVALID_PORT_ID);
825                         return -1;
826                 }
827
828
829                 /* Non bonded device */
830                 bonding_mode = rte_eth_bond_mode_get(test_params->slave_port_ids[0]);
831                 if (bonding_mode >= 0) {
832                         printf("Expected call to failed as invalid port (%d) specified.\n",
833                                         test_params->slave_port_ids[0]);
834                         return -1;
835                 }
836
837         }
838
839         return remove_slaves_and_stop_bonded_device();
840 }
841
842 static int
843 test_set_primary_slave(void)
844 {
845         int i, j, retval;
846         struct ether_addr read_mac_addr;
847         struct ether_addr *expected_mac_addr;
848
849         /* Add 4 slaves to bonded device */
850         for (i = test_params->bonded_slave_count; i < 4; i++) {
851                 retval = test_add_slave_to_bonded_device();
852                 if (retval != 0) {
853                         printf("Failed to add slave to bonded device.\n");
854                         return -1;
855                 }
856         }
857         retval = rte_eth_bond_mode_set(test_params->bonded_port_id,
858                         BONDING_MODE_ROUND_ROBIN);
859         if (retval != 0) {
860                 printf("Failed to set link bonding mode on port (%d) to (%d).\n",
861                                 test_params->bonded_port_id, BONDING_MODE_ROUND_ROBIN);
862                 return -1;
863         }
864
865         /* Invalid port ID */
866         retval = rte_eth_bond_primary_set(INVALID_PORT_ID,
867                         test_params->slave_port_ids[i]);
868         if (retval == 0) {
869                 printf("Expected call to failed as invalid port specified.\n");
870                 return -1;
871         }
872
873         /* Non bonded device */
874         retval = rte_eth_bond_primary_set(test_params->slave_port_ids[i],
875                         test_params->slave_port_ids[i]);
876         if (retval == 0) {
877                 printf("Expected call to failed as invalid port specified.\n");
878                 return -1;
879         }
880
881         /* Set slave as primary
882          * Verify slave it is now primary slave
883          * Verify that MAC address of bonded device is that of primary slave
884          * Verify that MAC address of all bonded slaves are that of primary slave
885          */
886         for (i = 0; i < 4; i++) {
887                 retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
888                                 test_params->slave_port_ids[i]);
889                 if (retval != 0) {
890                         printf("Failed to set bonded port (%d) primary port to (%d)\n",
891                                         test_params->bonded_port_id,
892                                         test_params->slave_port_ids[i]);
893                         return -1;
894                 }
895
896                 retval = rte_eth_bond_primary_get(test_params->bonded_port_id);
897                 if (retval < 0) {
898                         printf("Failed to read primary port from bonded port (%d)\n",
899                                         test_params->bonded_port_id);
900                         return -1;
901                 } else if (retval != test_params->slave_port_ids[i]) {
902                         printf("Bonded port (%d) primary port (%d) not expected value (%d)\n",
903                                         test_params->bonded_port_id, retval,
904                                         test_params->slave_port_ids[i]);
905                         return -1;
906                 }
907
908                 /* stop/start bonded eth dev to apply new MAC */
909                 rte_eth_dev_stop(test_params->bonded_port_id);
910
911                 if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
912                         return -1;
913
914                 expected_mac_addr = (struct ether_addr *)&slave_mac;
915                 expected_mac_addr->addr_bytes[ETHER_ADDR_LEN-1] =
916                                 test_params->slave_port_ids[i];
917
918                 /* Check primary slave MAC */
919                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
920                 if (memcmp(expected_mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
921                         printf("bonded port mac address not set to that of primary port\n");
922                         return -1;
923                 }
924
925                 /* Check bonded MAC */
926                 rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
927                 if (memcmp(&read_mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
928                         printf("bonded port mac address not set to that of primary port\n");
929                         return -1;
930                 }
931
932                 /* Check other slaves MACs */
933                 for (j = 0; j < 4; j++) {
934                         if (j != i) {
935                                 rte_eth_macaddr_get(test_params->slave_port_ids[j],
936                                                 &read_mac_addr);
937                                 if (memcmp(expected_mac_addr, &read_mac_addr,
938                                                 sizeof(read_mac_addr))) {
939                                         printf("slave port mac address not set to that of primary port\n");
940                                         return -1;
941                                 }
942                         }
943                 }
944         }
945
946
947         /* Test with none existent port */
948         retval = rte_eth_bond_primary_get(test_params->bonded_port_id + 10);
949         if (retval >= 0) {
950                 printf("read primary port from expectedly\n");
951                 return -1;
952         }
953
954         /* Test with slave port */
955         retval = rte_eth_bond_primary_get(test_params->slave_port_ids[0]);
956         if (retval >= 0) {
957                 printf("read primary port from expectedly\n");
958                 return -1;
959         }
960
961         if (remove_slaves_and_stop_bonded_device() != 0)
962                 return -1;
963
964         /* No slaves  */
965         retval = rte_eth_bond_primary_get(test_params->bonded_port_id);
966         if (retval >= 0) {
967                 printf("read primary port from expectedly\n");
968                 return -1;
969         }
970
971         return 0;
972 }
973
974 static int
975 test_set_explicit_bonded_mac(void)
976 {
977         int i, retval;
978         struct ether_addr read_mac_addr;
979         struct ether_addr *mac_addr;
980
981         uint8_t explicit_bonded_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01 };
982
983         mac_addr = (struct ether_addr *)explicit_bonded_mac;
984
985         /* Invalid port ID */
986         retval = rte_eth_bond_mac_address_set(INVALID_PORT_ID, mac_addr);
987         if (retval == 0) {
988                 printf("Expected call to failed as invalid port specified.\n");
989                 return -1;
990         }
991
992         /* Non bonded device */
993         retval = rte_eth_bond_mac_address_set(test_params->slave_port_ids[0],
994                         mac_addr);
995         if (retval == 0) {
996                 printf("Expected call to failed as invalid port specified.\n");
997                 return -1;
998         }
999
1000         /* NULL MAC address */
1001         retval = rte_eth_bond_mac_address_set(test_params->bonded_port_id, NULL);
1002         if (retval == 0) {
1003                 printf("Expected call to failed as NULL MAC specified\n");
1004                 return -1;
1005         }
1006
1007         retval = rte_eth_bond_mac_address_set(test_params->bonded_port_id,
1008                         mac_addr);
1009         if (retval != 0) {
1010                 printf("Failed to set MAC address on bonded port (%d)\n",
1011                                 test_params->bonded_port_id);
1012                 return -1;
1013         }
1014
1015         /* Add 4 slaves to bonded device */
1016         for (i = test_params->bonded_slave_count; i < 4; i++) {
1017                 retval = test_add_slave_to_bonded_device();
1018                 if (retval != 0) {
1019                         printf("Failed to add slave to bonded device.\n");
1020                         return -1;
1021                 }
1022         }
1023
1024         /* Check bonded MAC */
1025         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
1026         if (memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
1027                 printf("bonded port mac address not set to that of primary port\n");
1028                 return -1;
1029         }
1030
1031         /* Check other slaves MACs */
1032         for (i = 0; i < 4; i++) {
1033                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1034                 if (memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
1035                         printf("slave port mac address not set to that of primary port\n");
1036                         return -1;
1037                 }
1038         }
1039
1040         /* test resetting mac address on bonded device */
1041         if (rte_eth_bond_mac_address_reset(test_params->bonded_port_id) != 0) {
1042                 printf("Failed to reset MAC address on bonded port (%d)\n",
1043                                 test_params->bonded_port_id);
1044
1045                 return -1;
1046         }
1047
1048         if (rte_eth_bond_mac_address_reset(test_params->slave_port_ids[0]) == 0) {
1049                 printf("Reset MAC address on bonded port (%d) unexpectedly\n",
1050                                 test_params->slave_port_ids[1]);
1051
1052                 return -1;
1053         }
1054
1055         /* test resetting mac address on bonded device with no slaves */
1056
1057         if (remove_slaves_and_stop_bonded_device() != 0)
1058                 return -1;
1059
1060         if (rte_eth_bond_mac_address_reset(test_params->bonded_port_id) != 0) {
1061                 printf("Failed to reset MAC address on bonded port (%d)\n",
1062                                 test_params->bonded_port_id);
1063
1064                 return -1;
1065         }
1066
1067         return 0;
1068 }
1069
1070
1071 static int
1072 initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t bond_en_isr,
1073                 uint8_t number_of_slaves, uint8_t enable_slave)
1074 {
1075         /* Configure bonded device */
1076         TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0,
1077                         bond_en_isr), "Failed to configure bonding port (%d) in mode %d "
1078                         "with (%d) slaves.", test_params->bonded_port_id, bonding_mode,
1079                         number_of_slaves);
1080
1081         /* Add slaves to bonded device */
1082         while (number_of_slaves > test_params->bonded_slave_count)
1083                 TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
1084                                 "Failed to add slave (%d to  bonding port (%d).",
1085                                 test_params->bonded_slave_count - 1,
1086                                 test_params->bonded_port_id);
1087
1088         /* Set link bonding mode  */
1089         TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
1090                         bonding_mode),
1091                         "Failed to set link bonding mode on port (%d) to (%d).",
1092                         test_params->bonded_port_id, bonding_mode);
1093
1094         TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
1095                 "Failed to start bonded pmd eth device %d.",
1096                 test_params->bonded_port_id);
1097
1098         if (enable_slave)
1099                 enable_bonded_slaves();
1100
1101         return 0;
1102 }
1103
1104 static int
1105 test_adding_slave_after_bonded_device_started(void)
1106 {
1107         int i;
1108
1109         TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
1110                         BONDING_MODE_ROUND_ROBIN, 0, 4, 0),
1111                         "Failed to add slaves to bonded device");
1112
1113         /* Enabled slave devices */
1114         for (i = 0; i < test_params->bonded_slave_count + 1; i++) {
1115                 virtual_ethdev_simulate_link_status_interrupt(
1116                                 test_params->slave_port_ids[i], 1);
1117         }
1118
1119         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
1120                         test_params->slave_port_ids[test_params->bonded_slave_count]),
1121                         "Failed to add slave to bonded port.\n");
1122
1123         rte_eth_stats_reset(
1124                         test_params->slave_port_ids[test_params->bonded_slave_count]);
1125
1126         test_params->bonded_slave_count++;
1127
1128         return remove_slaves_and_stop_bonded_device();
1129 }
1130
1131 #define TEST_STATUS_INTERRUPT_SLAVE_COUNT       4
1132 #define TEST_LSC_WAIT_TIMEOUT_MS        500
1133
1134 int test_lsc_interrupt_count;
1135
1136
1137 static void
1138 test_bonding_lsc_event_callback(uint8_t port_id __rte_unused,
1139                 enum rte_eth_event_type type  __rte_unused, void *param __rte_unused)
1140 {
1141         pthread_mutex_lock(&mutex);
1142         test_lsc_interrupt_count++;
1143
1144         pthread_cond_signal(&cvar);
1145         pthread_mutex_unlock(&mutex);
1146 }
1147
1148 static inline int
1149 lsc_timeout(int wait_us)
1150 {
1151         int retval = 0;
1152
1153         struct timespec ts;
1154         struct timeval tp;
1155
1156         gettimeofday(&tp, NULL);
1157
1158         /* Convert from timeval to timespec */
1159         ts.tv_sec = tp.tv_sec;
1160         ts.tv_nsec = tp.tv_usec * 1000;
1161         ts.tv_nsec += wait_us * 1000;
1162
1163         pthread_mutex_lock(&mutex);
1164         if (test_lsc_interrupt_count < 1)
1165                 retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
1166
1167         pthread_mutex_unlock(&mutex);
1168
1169         if (retval == 0 && test_lsc_interrupt_count < 1)
1170                 return -1;
1171
1172         return retval;
1173 }
1174
1175 static int
1176 test_status_interrupt(void)
1177 {
1178         int slave_count;
1179         uint8_t slaves[RTE_MAX_ETHPORTS];
1180
1181         /* initialized bonding device with T slaves */
1182         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 1,
1183                         TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1) != 0)
1184                 return -1;
1185
1186         test_lsc_interrupt_count = 0;
1187
1188         /* register link status change interrupt callback */
1189         rte_eth_dev_callback_register(test_params->bonded_port_id,
1190                         RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
1191                         &test_params->bonded_port_id);
1192
1193         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
1194                         slaves, RTE_MAX_ETHPORTS);
1195
1196         TEST_ASSERT_EQUAL(slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT,
1197                         "Number of active slaves (%d) is not as expected (%d)",
1198                         slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT);
1199
1200         /* Bring all 4 slaves link status to down and test that we have received a
1201          * lsc interrupts */
1202         virtual_ethdev_simulate_link_status_interrupt(
1203                         test_params->slave_port_ids[0], 0);
1204         virtual_ethdev_simulate_link_status_interrupt(
1205                         test_params->slave_port_ids[1], 0);
1206         virtual_ethdev_simulate_link_status_interrupt(
1207                         test_params->slave_port_ids[2], 0);
1208
1209         TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0,
1210                         "Received a link status change interrupt unexpectedly");
1211
1212         virtual_ethdev_simulate_link_status_interrupt(
1213                         test_params->slave_port_ids[3], 0);
1214
1215         TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
1216                         "timed out waiting for interrupt");
1217
1218         TEST_ASSERT(test_lsc_interrupt_count > 0,
1219                         "Did not receive link status change interrupt");
1220
1221         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
1222                         slaves, RTE_MAX_ETHPORTS);
1223
1224         TEST_ASSERT_EQUAL(slave_count, 0,
1225                         "Number of active slaves (%d) is not as expected (%d)",
1226                         slave_count, 0);
1227
1228         /* bring one slave port up so link status will change */
1229         test_lsc_interrupt_count = 0;
1230
1231         virtual_ethdev_simulate_link_status_interrupt(
1232                         test_params->slave_port_ids[0], 1);
1233
1234         TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
1235                         "timed out waiting for interrupt");
1236
1237         /* test that we have received another lsc interrupt */
1238         TEST_ASSERT(test_lsc_interrupt_count > 0,
1239                         "Did not receive link status change interrupt");
1240
1241         /* Verify that calling the same slave lsc interrupt doesn't cause another
1242          * lsc interrupt from bonded device */
1243         test_lsc_interrupt_count = 0;
1244
1245         virtual_ethdev_simulate_link_status_interrupt(
1246                         test_params->slave_port_ids[0], 1);
1247
1248         TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) != 0,
1249                         "received unexpected interrupt");
1250
1251         TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0,
1252                         "Did not receive link status change interrupt");
1253
1254
1255         /* unregister lsc callback before exiting */
1256         rte_eth_dev_callback_unregister(test_params->bonded_port_id,
1257                                 RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
1258                                 &test_params->bonded_port_id);
1259
1260         /* Clean up and remove slaves from bonded device */
1261         return remove_slaves_and_stop_bonded_device();
1262 }
1263
1264 static int
1265 generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size,
1266                 uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac,
1267                 uint8_t toggle_ip_addr, uint8_t toggle_udp_port)
1268 {
1269         uint16_t pktlen, generated_burst_size;
1270         void *ip_hdr;
1271
1272         if (toggle_dst_mac)
1273                 initialize_eth_header(test_params->pkt_eth_hdr,
1274                                 (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1,
1275                                 vlan, vlan_id);
1276         else
1277                 initialize_eth_header(test_params->pkt_eth_hdr,
1278                                 (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0,
1279                                 vlan, vlan_id);
1280
1281
1282         if (toggle_udp_port)
1283                 pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
1284                                 dst_port_1, 64);
1285         else
1286                 pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
1287                                 dst_port_0, 64);
1288
1289         if (ipv4) {
1290                 if (toggle_ip_addr)
1291                         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
1292                                         dst_addr_1, pktlen);
1293                 else
1294                         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
1295                                         dst_addr_0, pktlen);
1296
1297                 ip_hdr = test_params->pkt_ipv4_hdr;
1298         } else {
1299                 if (toggle_ip_addr)
1300                         pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
1301                                         (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_1,
1302                                         pktlen);
1303                 else
1304                         pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
1305                                         (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_0,
1306                                         pktlen);
1307
1308                 ip_hdr = test_params->pkt_ipv6_hdr;
1309         }
1310
1311         /* Generate burst of packets to transmit */
1312         generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
1313                         pkts_burst,     test_params->pkt_eth_hdr, vlan, ip_hdr, ipv4,
1314                         test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN_128,
1315                         1);
1316         if (generated_burst_size != burst_size) {
1317                 printf("Failed to generate packet burst");
1318                 return -1;
1319         }
1320
1321         return generated_burst_size;
1322 }
1323
1324 /** Round Robin Mode Tests */
1325
1326 static int
1327 test_roundrobin_tx_burst(void)
1328 {
1329         int i, burst_size, nb_tx;
1330         struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
1331         struct rte_eth_stats port_stats;
1332
1333         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 2, 1)
1334                         != 0)
1335                 return -1;
1336
1337         burst_size = 20 * test_params->bonded_slave_count;
1338
1339         if (burst_size > MAX_PKT_BURST) {
1340                 printf("Burst size specified is greater than supported.\n");
1341                 return -1;
1342         }
1343
1344         /* Generate test bursts of packets to transmit */
1345         if (generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0) != burst_size)
1346                 return -1;
1347
1348         /* Send burst on bonded port */
1349         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
1350                         burst_size);
1351         if (nb_tx != burst_size)
1352                 return -1;
1353
1354         /* Verify bonded port tx stats */
1355         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1356         if (port_stats.opackets != (uint64_t)burst_size) {
1357                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
1358                                 test_params->bonded_port_id, (unsigned int)port_stats.opackets,
1359                                 burst_size);
1360                 return -1;
1361         }
1362
1363         /* Verify slave ports tx stats */
1364         for (i = 0; i < test_params->bonded_slave_count; i++) {
1365                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
1366                 if (port_stats.opackets !=
1367                                 (uint64_t)burst_size / test_params->bonded_slave_count) {
1368                         printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
1369                                         test_params->bonded_port_id,
1370                                         (unsigned int)port_stats.opackets,
1371                                         burst_size / test_params->bonded_slave_count);
1372                         return -1;
1373                 }
1374         }
1375
1376         /* Put all slaves down and try and transmit */
1377         for (i = 0; i < test_params->bonded_slave_count; i++) {
1378                 virtual_ethdev_simulate_link_status_interrupt(
1379                                 test_params->slave_port_ids[i], 0);
1380         }
1381
1382         /* Send burst on bonded port */
1383         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
1384                         burst_size);
1385         if (nb_tx != 0)
1386                 return -1;
1387
1388         /* Clean up and remove slaves from bonded device */
1389         return remove_slaves_and_stop_bonded_device();
1390 }
1391
1392 #ifdef RTE_MBUF_REFCNT
1393 static int
1394 verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
1395 {
1396         int i, refcnt;
1397
1398         for (i = 0; i < nb_mbufs; i++) {
1399                 refcnt = rte_mbuf_refcnt_read(mbufs[i]);
1400                 TEST_ASSERT_EQUAL(refcnt, val,
1401                         "mbuf ref count (%d)is not the expected value (%d)",
1402                         refcnt, val);
1403         }
1404         return 0;
1405 }
1406 #endif
1407
1408
1409 static void
1410 free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs)
1411 {
1412         int i;
1413
1414         for (i = 0; i < nb_mbufs; i++)
1415                 rte_pktmbuf_free(mbufs[i]);
1416 }
1417
1418 #define TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT               (2)
1419 #define TEST_RR_SLAVE_TX_FAIL_BURST_SIZE                (64)
1420 #define TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT             (22)
1421 #define TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (1)
1422
1423 static int
1424 test_roundrobin_tx_burst_slave_tx_fail(void)
1425 {
1426         struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
1427         struct rte_mbuf *expected_tx_fail_pkts[MAX_PKT_BURST];
1428
1429         struct rte_eth_stats port_stats;
1430
1431         int i, first_fail_idx, tx_count;
1432
1433         TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
1434                         BONDING_MODE_ROUND_ROBIN, 0,
1435                         TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
1436                         "Failed to intialise bonded device");
1437
1438         /* Generate test bursts of packets to transmit */
1439         TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst,
1440                         TEST_RR_SLAVE_TX_FAIL_BURST_SIZE, 0, 1, 0, 0, 0),
1441                         TEST_RR_SLAVE_TX_FAIL_BURST_SIZE,
1442                         "Failed to generate test packet burst");
1443
1444         /* Copy references to packets which we expect not to be transmitted */
1445         first_fail_idx = (TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
1446                         (TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT *
1447                         TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)) +
1448                         TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX;
1449
1450         for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
1451                 expected_tx_fail_pkts[i] = pkt_burst[first_fail_idx +
1452                                 (i * TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)];
1453         }
1454
1455         /* Set virtual slave to only fail transmission of
1456          * TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT packets in burst */
1457         virtual_ethdev_tx_burst_fn_set_success(
1458                         test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
1459                         0);
1460
1461         virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
1462                         test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
1463                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
1464
1465         tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
1466                         TEST_RR_SLAVE_TX_FAIL_BURST_SIZE);
1467
1468         TEST_ASSERT_EQUAL(tx_count, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
1469                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,
1470                         "Transmitted (%d) an unexpected (%d) number of packets", tx_count,
1471                         TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
1472                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
1473
1474         /* Verify that failed packet are expected failed packets */
1475         for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
1476                 TEST_ASSERT_EQUAL(expected_tx_fail_pkts[i], pkt_burst[i + tx_count],
1477                                 "expected mbuf (%d) pointer %p not expected pointer %p",
1478                                 i, expected_tx_fail_pkts[i], pkt_burst[i + tx_count]);
1479         }
1480
1481         /* Verify bonded port tx stats */
1482         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1483
1484         TEST_ASSERT_EQUAL(port_stats.opackets,
1485                         (uint64_t)TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
1486                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,
1487                         "Bonded Port (%d) opackets value (%u) not as expected (%d)",
1488                         test_params->bonded_port_id, (unsigned int)port_stats.opackets,
1489                         TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
1490                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
1491
1492         /* Verify slave ports tx stats */
1493         for (i = 0; i < test_params->bonded_slave_count; i++) {
1494                 int slave_expected_tx_count;
1495
1496                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
1497
1498                 slave_expected_tx_count = TEST_RR_SLAVE_TX_FAIL_BURST_SIZE /
1499                                 test_params->bonded_slave_count;
1500
1501                 if (i == TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX)
1502                         slave_expected_tx_count = slave_expected_tx_count -
1503                                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT;
1504
1505                 TEST_ASSERT_EQUAL(port_stats.opackets,
1506                                 (uint64_t)slave_expected_tx_count,
1507                                 "Slave Port (%d) opackets value (%u) not as expected (%d)",
1508                                 test_params->slave_port_ids[i],
1509                                 (unsigned int)port_stats.opackets, slave_expected_tx_count);
1510         }
1511
1512 #ifdef RTE_MBUF_REFCNT
1513         /* Verify that all mbufs have a ref value of zero */
1514         TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkt_burst[tx_count],
1515                         TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, 1),
1516                         "mbufs refcnts not as expected");
1517 #endif
1518         free_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
1519
1520         /* Clean up and remove slaves from bonded device */
1521         return remove_slaves_and_stop_bonded_device();
1522 }
1523
1524 static int
1525 test_roundrobin_rx_burst_on_single_slave(void)
1526 {
1527         struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
1528         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1529
1530         struct rte_eth_stats port_stats;
1531
1532         int i, j, nb_rx, burst_size = 25;
1533
1534         /* Initialize bonded device with 4 slaves in round robin mode */
1535         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1) !=
1536                         0)
1537                 return -1;
1538
1539         /* Generate test bursts of packets to transmit */
1540         if (generate_test_burst(gen_pkt_burst, burst_size, 0, 1, 0, 0, 0) !=
1541                         burst_size)
1542                 return -1;
1543
1544         for (i = 0; i < test_params->bonded_slave_count; i++) {
1545                 /* Add rx data to slave */
1546                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1547                                 &gen_pkt_burst[0], burst_size);
1548
1549                 /* Call rx burst on bonded device */
1550                 /* Send burst on bonded port */
1551                 nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
1552                                 MAX_PKT_BURST);
1553                 if (nb_rx != burst_size) {
1554                         printf("round-robin rx burst failed");
1555                         return -1;
1556                 }
1557
1558                 /* Verify bonded device rx count */
1559                 rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1560                 if (port_stats.ipackets != (uint64_t)burst_size) {
1561                         printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
1562                                         test_params->bonded_port_id,
1563                                         (unsigned int)port_stats.ipackets, burst_size);
1564                         return -1;
1565                 }
1566
1567
1568                 /* Verify bonded slave devices rx count */
1569                 /* Verify slave ports tx stats */
1570                 for (j = 0; j < test_params->bonded_slave_count; j++) {
1571                         rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
1572
1573                         if (i == j) {
1574                                 if (port_stats.ipackets != (uint64_t)burst_size) {
1575                                         printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1576                                                         test_params->slave_port_ids[i],
1577                                                         (unsigned int)port_stats.ipackets, burst_size);
1578                                         return -1;
1579                                 }
1580                         } else {
1581                                 if (port_stats.ipackets != 0) {
1582                                         printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1583                                                         test_params->slave_port_ids[i],
1584                                                         (unsigned int)port_stats.ipackets, 0);
1585                                         return -1;
1586                                 }
1587                         }
1588
1589                         /* Reset bonded slaves stats */
1590                         rte_eth_stats_reset(test_params->slave_port_ids[j]);
1591                 }
1592                 /* reset bonded device stats */
1593                 rte_eth_stats_reset(test_params->bonded_port_id);
1594         }
1595
1596         /* free mbufs */
1597         for (i = 0; i < MAX_PKT_BURST; i++) {
1598                 if (gen_pkt_burst[i] != NULL)
1599                         rte_pktmbuf_free(gen_pkt_burst[i]);
1600
1601                 if (rx_pkt_burst[i] != NULL)
1602                         rte_pktmbuf_free(rx_pkt_burst[i]);
1603         }
1604
1605
1606         /* Clean up and remove slaves from bonded device */
1607         return remove_slaves_and_stop_bonded_device();
1608 }
1609
1610 #define TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT (3)
1611
1612 static int
1613 test_roundrobin_rx_burst_on_multiple_slaves(void)
1614 {
1615         struct rte_mbuf *gen_pkt_burst[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
1616
1617         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1618         struct rte_eth_stats port_stats;
1619
1620         int burst_size[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT] = { 15, 13, 36 };
1621         int i, nb_rx;
1622
1623
1624         /* Initialize bonded device with 4 slaves in round robin mode */
1625         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1) !=
1626                         0)
1627                 return -1;
1628
1629         /* Generate test bursts of packets to transmit */
1630         for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
1631                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size[i], 0, 1, 0, 0,
1632                                 0) != burst_size[i])
1633                         return -1;
1634         }
1635
1636         /* Add rx data to slaves */
1637         for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
1638                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1639                                 &gen_pkt_burst[i][0], burst_size[i]);
1640         }
1641
1642         /* Call rx burst on bonded device */
1643         /* Send burst on bonded port */
1644         nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
1645                         MAX_PKT_BURST);
1646         if (nb_rx != burst_size[0] + burst_size[1] + burst_size[2]) {
1647                 printf("round-robin rx burst failed (%d != %d)\n", nb_rx,
1648                                 burst_size[0] + burst_size[1] + burst_size[2]);
1649                 return -1;
1650         }
1651
1652         /* Verify bonded device rx count */
1653         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1654         if (port_stats.ipackets != (uint64_t)(burst_size[0] + burst_size[1] +
1655                         burst_size[2])) {
1656                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
1657                                 test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
1658                                 burst_size[0] + burst_size[1] + burst_size[2]);
1659                 return -1;
1660         }
1661
1662
1663         /* Verify bonded slave devices rx counts */
1664         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
1665         if (port_stats.ipackets != (uint64_t)burst_size[0]) {
1666                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1667                                 test_params->slave_port_ids[0],
1668                                 (unsigned int)port_stats.ipackets, burst_size[0]);
1669                 return -1;
1670         }
1671
1672         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
1673         if (port_stats.ipackets != (uint64_t)burst_size[1]) {
1674                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1675                                 test_params->slave_port_ids[1],
1676                                 (unsigned int)port_stats.ipackets, burst_size[1]);
1677                 return -1;
1678         }
1679
1680         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
1681         if (port_stats.ipackets != (uint64_t)burst_size[2]) {
1682                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1683                                 test_params->slave_port_ids[2],
1684                                 (unsigned int)port_stats.ipackets, burst_size[2]);
1685                 return -1;
1686         }
1687
1688         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
1689         if (port_stats.ipackets != 0) {
1690                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1691                                 test_params->slave_port_ids[3],
1692                                 (unsigned int)port_stats.ipackets, 0);
1693                 return -1;
1694         }
1695
1696         /* free mbufs */
1697         for (i = 0; i < MAX_PKT_BURST; i++) {
1698                 if (rx_pkt_burst[i] != NULL)
1699                         rte_pktmbuf_free(rx_pkt_burst[i]);
1700         }
1701
1702         /* Clean up and remove slaves from bonded device */
1703         return remove_slaves_and_stop_bonded_device();
1704 }
1705
1706 static int
1707 test_roundrobin_verify_mac_assignment(void)
1708 {
1709         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_2;
1710
1711         int i, retval;
1712
1713         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
1714         rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_2);
1715
1716         /* Initialize bonded device with 4 slaves in round robin mode */
1717         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1)
1718                         != 0)
1719                 return -1;
1720
1721         /* Verify that all MACs are the same as first slave added to bonded dev */
1722         for (i = 0; i < test_params->bonded_slave_count; i++) {
1723                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1724                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
1725                                 sizeof(read_mac_addr))) {
1726                         printf("slave port (%d) mac address not set to that of primary port\n",
1727                                         test_params->slave_port_ids[i]);
1728                         return -1;
1729                 }
1730         }
1731
1732         /* change primary and verify that MAC addresses haven't changed */
1733         retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
1734                         test_params->slave_port_ids[2]);
1735         if (retval != 0) {
1736                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
1737                                 test_params->bonded_port_id, test_params->slave_port_ids[i]);
1738                 return -1;
1739         }
1740
1741         for (i = 0; i < test_params->bonded_slave_count; i++) {
1742                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1743                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
1744                                 sizeof(read_mac_addr))) {
1745                         printf("slave port (%d) mac address has changed to that of primary port without stop/start toggle of bonded device\n",
1746                                         test_params->slave_port_ids[i]);
1747                         return -1;
1748                 }
1749         }
1750
1751         /* stop / start bonded device and verify that primary MAC address is
1752          * propagate to bonded device and slaves */
1753
1754         rte_eth_dev_stop(test_params->bonded_port_id);
1755
1756         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
1757                 return -1;
1758
1759         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
1760         if (memcmp(&expected_mac_addr_2, &read_mac_addr, sizeof(read_mac_addr))) {
1761                 printf("bonded port (%d) mac address not set to that of new primary port\n",
1762                                 test_params->slave_port_ids[i]);
1763                 return -1;
1764         }
1765
1766         for (i = 0; i < test_params->bonded_slave_count; i++) {
1767                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1768                 if (memcmp(&expected_mac_addr_2, &read_mac_addr,
1769                                 sizeof(read_mac_addr))) {
1770                         printf("slave port (%d) mac address not set to that of new primary port\n",
1771                                         test_params->slave_port_ids[i]);
1772                         return -1;
1773                 }
1774         }
1775
1776         /* Set explicit MAC address */
1777         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
1778                         (struct ether_addr *)bonded_mac) != 0) {
1779                 return -1;
1780         }
1781
1782         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
1783         if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
1784                 printf("bonded port (%d) mac address not set to that of new primary port\n",
1785                                 test_params->slave_port_ids[i]);
1786                 return -1;
1787         }
1788
1789         for (i = 0; i < test_params->bonded_slave_count; i++) {
1790                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1791                 if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
1792                         printf("slave port (%d) mac address not set to that of new primary port\n",
1793                                         test_params->slave_port_ids[i]);
1794                         return -1;
1795                 }
1796         }
1797
1798         /* Clean up and remove slaves from bonded device */
1799         return remove_slaves_and_stop_bonded_device();
1800 }
1801
1802 static int
1803 test_roundrobin_verify_promiscuous_enable_disable(void)
1804 {
1805         int i, promiscuous_en;
1806
1807         /* Initialize bonded device with 4 slaves in round robin mode */
1808         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1) !=
1809                         0)
1810                 return -1;
1811
1812         rte_eth_promiscuous_enable(test_params->bonded_port_id);
1813
1814         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
1815         if (promiscuous_en != 1) {
1816                 printf("Port (%d) promiscuous mode not enabled\n",
1817                                 test_params->bonded_port_id);
1818                 return -1;
1819         }
1820
1821         for (i = 0; i < test_params->bonded_slave_count; i++) {
1822                 promiscuous_en = rte_eth_promiscuous_get(test_params->slave_port_ids[i]);
1823                 if (promiscuous_en != 1) {
1824                         printf("slave port (%d) promiscuous mode not enabled\n",
1825                                         test_params->slave_port_ids[i]);
1826                         return -1;
1827                 }
1828         }
1829
1830         rte_eth_promiscuous_disable(test_params->bonded_port_id);
1831
1832         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
1833         if (promiscuous_en != 0) {
1834                 printf("Port (%d) promiscuous mode not disabled\n",
1835                                 test_params->bonded_port_id);
1836                 return -1;
1837         }
1838
1839         for (i = 0; i < test_params->bonded_slave_count; i++) {
1840                 promiscuous_en = rte_eth_promiscuous_get(test_params->slave_port_ids[i]);
1841                 if (promiscuous_en != 0) {
1842                         printf("slave port (%d) promiscuous mode not disabled\n",
1843                                         test_params->slave_port_ids[i]);
1844                         return -1;
1845                 }
1846         }
1847
1848         /* Clean up and remove slaves from bonded device */
1849         return remove_slaves_and_stop_bonded_device();
1850 }
1851
1852 #define TEST_RR_LINK_STATUS_SLAVE_COUNT (4)
1853 #define TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT (2)
1854
1855 static int
1856 test_roundrobin_verify_slave_link_status_change_behaviour(void)
1857 {
1858         struct rte_mbuf *tx_pkt_burst[MAX_PKT_BURST] = { NULL };
1859         struct rte_mbuf *gen_pkt_burst[TEST_RR_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST];
1860         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1861
1862         struct rte_eth_stats port_stats;
1863         uint8_t slaves[RTE_MAX_ETHPORTS];
1864
1865         int i, burst_size, slave_count;
1866
1867         /* NULL all pointers in array to simplify cleanup */
1868         memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
1869
1870         /* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves
1871          * in round robin mode */
1872         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
1873                         TEST_RR_LINK_STATUS_SLAVE_COUNT, 1) != 0)
1874                 return -1;
1875
1876         /* Verify Current Slaves Count /Active Slave Count is */
1877         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
1878                         RTE_MAX_ETHPORTS);
1879         if (slave_count != TEST_RR_LINK_STATUS_SLAVE_COUNT) {
1880                 printf("Number of slaves (%d) is not as expected (%d).\n", slave_count,
1881                                 TEST_RR_LINK_STATUS_SLAVE_COUNT);
1882                 return -1;
1883         }
1884
1885         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
1886                         slaves, RTE_MAX_ETHPORTS);
1887         if (slave_count != TEST_RR_LINK_STATUS_SLAVE_COUNT) {
1888                 printf("Number of active slaves (%d) is not as expected (%d).\n",
1889                                 slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT);
1890                 return -1;
1891         }
1892
1893         /* Set 2 slaves eth_devs link status to down */
1894         virtual_ethdev_simulate_link_status_interrupt(
1895                         test_params->slave_port_ids[1], 0);
1896         virtual_ethdev_simulate_link_status_interrupt(
1897                         test_params->slave_port_ids[3], 0);
1898
1899         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
1900                         slaves, RTE_MAX_ETHPORTS) !=
1901                                         TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) {
1902                 printf("Number of active slaves (%d) is not as expected (%d).\n",
1903                                 slave_count, TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT);
1904                 return -1;
1905         }
1906
1907         burst_size = 20;
1908
1909         /* Verify that pkts are not sent on slaves with link status down:
1910          *
1911          * 1. Generate test burst of traffic
1912          * 2. Transmit burst on bonded eth_dev
1913          * 3. Verify stats for bonded eth_dev (opackets = burst_size)
1914          * 4. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
1915          */
1916         if (generate_test_burst(tx_pkt_burst, burst_size, 0, 1, 0, 0, 0) !=
1917                         burst_size) {
1918                 printf("generate_test_burst failed\n");
1919                 return -1;
1920         }
1921
1922         rte_eth_stats_reset(test_params->bonded_port_id);
1923
1924         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, tx_pkt_burst,
1925                         burst_size) != burst_size) {
1926                 printf("rte_eth_tx_burst failed\n");
1927                 return -1;
1928         }
1929
1930         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1931         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
1932                         "Port (%d) opackets stats (%d) not expected (%d) value",
1933                         test_params->bonded_port_id, (int)port_stats.opackets,
1934                         burst_size);
1935
1936         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
1937         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
1938                         "Port (%d) opackets stats (%d) not expected (%d) value",
1939                         test_params->slave_port_ids[0], (int)port_stats.opackets, 10);
1940
1941         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
1942         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
1943                         "Port (%d) opackets stats (%d) not expected (%d) value",
1944                         test_params->slave_port_ids[1], (int)port_stats.opackets, 0);
1945
1946         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
1947         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
1948                         "Port (%d) opackets stats (%d) not expected (%d) value",
1949                         test_params->slave_port_ids[2], (int)port_stats.opackets, 10);
1950
1951         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
1952         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
1953                         "Port (%d) opackets stats (%d) not expected (%d) value",
1954                         test_params->slave_port_ids[3], (int)port_stats.opackets, 0);
1955
1956         /* Verify that pkts are not sent on slaves with link status down:
1957          *
1958          * 1. Generate test bursts of traffic
1959          * 2. Add bursts on to virtual eth_devs
1960          * 3. Rx burst on bonded eth_dev, expected (burst_ size *
1961          *    TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) received
1962          * 4. Verify stats for bonded eth_dev
1963          * 6. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
1964          */
1965         for (i = 0; i < TEST_RR_LINK_STATUS_SLAVE_COUNT; i++) {
1966                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0)
1967                                 != burst_size) {
1968                         return -1;
1969                 }
1970                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1971                                 &gen_pkt_burst[i][0], burst_size);
1972         }
1973
1974         if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
1975                         MAX_PKT_BURST) != burst_size + burst_size) {
1976                 printf("rte_eth_rx_burst\n");
1977                 return -1;
1978         }
1979
1980         /* Verify bonded device rx count */
1981         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1982         if (port_stats.ipackets != (uint64_t)(burst_size + burst_size)) {
1983                 printf("(%d) port_stats.ipackets not as expected\n",
1984                                 test_params->bonded_port_id);
1985                 return -1;
1986         }
1987
1988         /* free mbufs */
1989         for (i = 0; i < MAX_PKT_BURST; i++) {
1990                 if (rx_pkt_burst[i] != NULL)
1991                         rte_pktmbuf_free(rx_pkt_burst[i]);
1992
1993                 if (gen_pkt_burst[1][i] != NULL)
1994                         rte_pktmbuf_free(gen_pkt_burst[1][i]);
1995
1996                 if (gen_pkt_burst[3][i] != NULL)
1997                         rte_pktmbuf_free(gen_pkt_burst[1][i]);
1998         }
1999
2000         /* Clean up and remove slaves from bonded device */
2001         return remove_slaves_and_stop_bonded_device();
2002 }
2003
2004 #define TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT (2)
2005
2006 uint8_t polling_slave_mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00 };
2007
2008 #include "unistd.h"
2009
2010 int polling_test_slaves[TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT] = { -1, -1 };
2011
2012 static int
2013 test_roundrobin_verfiy_polling_slave_link_status_change(void)
2014 {
2015         struct ether_addr *mac_addr = (struct ether_addr *)polling_slave_mac;
2016         char slave_name[RTE_ETH_NAME_MAX_LEN];
2017
2018         int i;
2019
2020         for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) {
2021                 /* Generate slave name / MAC address */
2022                 snprintf(slave_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_poll_%d", i);
2023                 mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i;
2024
2025                 /* Create slave devices with no ISR Support */
2026                 if (polling_test_slaves[i] == -1) {
2027                         polling_test_slaves[i] = virtual_ethdev_create(slave_name, mac_addr,
2028                                         rte_socket_id(), 0);
2029                         TEST_ASSERT(polling_test_slaves[i] >= 0,
2030                                         "Failed to create virtual virtual ethdev %s\n", slave_name);
2031
2032                         /* Configure slave */
2033                         TEST_ASSERT_SUCCESS(configure_ethdev(polling_test_slaves[i], 0, 0),
2034                                         "Failed to configure virtual ethdev %s(%d)", slave_name,
2035                                         polling_test_slaves[i]);
2036                 }
2037
2038                 /* Add slave to bonded device */
2039                 TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
2040                                 polling_test_slaves[i]),
2041                                 "Failed to add slave %s(%d) to bonded device %d",
2042                                 slave_name, polling_test_slaves[i], test_params->bonded_port_id);
2043         }
2044
2045         /* Initialize bonded device */
2046         TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 1, 1),
2047                         "Failed to configure bonded device %d",
2048                         test_params->bonded_port_id);
2049
2050
2051         /* Register link status change interrupt callback */
2052         rte_eth_dev_callback_register(test_params->bonded_port_id,
2053                         RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
2054                         &test_params->bonded_port_id);
2055
2056         /* link status change callback for first slave link up */
2057         test_lsc_interrupt_count = 0;
2058
2059         virtual_ethdev_set_link_status(polling_test_slaves[0], 1);
2060
2061         TEST_ASSERT_SUCCESS(lsc_timeout(15000), "timed out waiting for interrupt");
2062
2063
2064         /* no link status change callback for second slave link up */
2065         test_lsc_interrupt_count = 0;
2066
2067         virtual_ethdev_set_link_status(polling_test_slaves[1], 1);
2068
2069         TEST_ASSERT_FAIL(lsc_timeout(15000), "unexpectedly succeeded");
2070
2071         /* link status change callback for both slave links down */
2072         test_lsc_interrupt_count = 0;
2073
2074         virtual_ethdev_set_link_status(polling_test_slaves[0], 0);
2075         virtual_ethdev_set_link_status(polling_test_slaves[1], 0);
2076
2077         TEST_ASSERT_SUCCESS(lsc_timeout(20000), "timed out waiting for interrupt");
2078
2079         /* Un-Register link status change interrupt callback */
2080         rte_eth_dev_callback_unregister(test_params->bonded_port_id,
2081                         RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
2082                         &test_params->bonded_port_id);
2083
2084
2085         /* Clean up and remove slaves from bonded device */
2086         for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) {
2087
2088                 TEST_ASSERT_SUCCESS(
2089                                 rte_eth_bond_slave_remove(test_params->bonded_port_id,
2090                                                 polling_test_slaves[i]),
2091                                 "Failed to remove slave %d from bonded port (%d)",
2092                                 polling_test_slaves[i], test_params->bonded_port_id);
2093         }
2094
2095         return remove_slaves_and_stop_bonded_device();
2096 }
2097
2098
2099 /** Active Backup Mode Tests */
2100
2101 static int
2102 test_activebackup_tx_burst(void)
2103 {
2104         int i, retval, pktlen, primary_port, burst_size, generated_burst_size, nb_tx;
2105         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
2106         struct rte_eth_stats port_stats;
2107
2108         retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1);
2109         if (retval != 0) {
2110                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2111                 return -1;
2112         }
2113
2114         initialize_eth_header(test_params->pkt_eth_hdr,
2115                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0);
2116         pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
2117                         dst_port_0, 16);
2118         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
2119                         dst_addr_0, pktlen);
2120
2121         burst_size = 20 * test_params->bonded_slave_count;
2122
2123         if (burst_size > MAX_PKT_BURST) {
2124                 printf("Burst size specified is greater than supported.\n");
2125                 return -1;
2126         }
2127
2128         /* Generate a burst of packets to transmit */
2129         generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
2130                         pkts_burst,     test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
2131                         1, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN, 1);
2132         if (generated_burst_size != burst_size)
2133                 return -1;
2134
2135         /* Send burst on bonded port */
2136         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
2137                         burst_size);
2138         if (nb_tx != burst_size)
2139                 return -1;
2140
2141         /* Verify bonded port tx stats */
2142         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2143         if (port_stats.opackets != (uint64_t)burst_size) {
2144                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
2145                                 test_params->bonded_port_id, (unsigned int)port_stats.opackets,
2146                                 burst_size);
2147                 return -1;
2148         }
2149
2150         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2151
2152         /* Verify slave ports tx stats */
2153         for (i = 0; i < test_params->bonded_slave_count; i++) {
2154                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
2155                 if (test_params->slave_port_ids[i] == primary_port) {
2156                         if (port_stats.opackets != (uint64_t)burst_size) {
2157                                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2158                                                 test_params->bonded_port_id,
2159                                                 (unsigned int)port_stats.opackets,
2160                                                 burst_size / test_params->bonded_slave_count);
2161                                 return -1;
2162                         }
2163                 } else {
2164                         if (port_stats.opackets != 0) {
2165                                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2166                                                 test_params->bonded_port_id,
2167                                                 (unsigned int)port_stats.opackets, 0);
2168                                 return -1;
2169                         }
2170                 }
2171         }
2172
2173         /* Put all slaves down and try and transmit */
2174         for (i = 0; i < test_params->bonded_slave_count; i++) {
2175
2176                 virtual_ethdev_simulate_link_status_interrupt(
2177                                 test_params->slave_port_ids[i], 0);
2178         }
2179
2180         /* Send burst on bonded port */
2181         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
2182                         burst_size);
2183         if (nb_tx != 0)
2184                 return -1;
2185
2186         /* Clean up and remove slaves from bonded device */
2187         return remove_slaves_and_stop_bonded_device();
2188 }
2189
2190 #define TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT (4)
2191
2192 static int
2193 test_activebackup_rx_burst(void)
2194 {
2195         struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
2196         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
2197
2198         struct rte_eth_stats port_stats;
2199
2200         int primary_port;
2201
2202         int i, j, nb_rx, burst_size = 17;
2203
2204         /* Initialize bonded device with 4 slaves in round robin mode */
2205         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
2206                         TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
2207                         != 0)
2208                 return -1;
2209
2210
2211         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2212         if (primary_port < 0) {
2213                 printf("failed to get primary slave for bonded port (%d)",
2214                                 test_params->bonded_port_id);
2215         }
2216
2217         for (i = 0; i < test_params->bonded_slave_count; i++) {
2218                 /* Generate test bursts of packets to transmit */
2219                 if (generate_test_burst(&gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0)
2220                                 != burst_size) {
2221                         return -1;
2222                 }
2223
2224                 /* Add rx data to slave */
2225                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
2226                                 &gen_pkt_burst[0], burst_size);
2227
2228                 /* Call rx burst on bonded device */
2229                 nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0,
2230                                 &rx_pkt_burst[0], MAX_PKT_BURST);
2231                 if (nb_rx < 0) {
2232                         printf("rte_eth_rx_burst failed\n");
2233                         return -1;
2234                 }
2235
2236                 if (test_params->slave_port_ids[i] == primary_port) {
2237                         /* Verify bonded device rx count */
2238                         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2239                         if (port_stats.ipackets != (uint64_t)burst_size) {
2240                                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
2241                                                 test_params->bonded_port_id,
2242                                                 (unsigned int)port_stats.ipackets, burst_size);
2243                                 return -1;
2244                         }
2245
2246                         /* Verify bonded slave devices rx count */
2247                         for (j = 0; j < test_params->bonded_slave_count; j++) {
2248                                 rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
2249                                 if (i == j) {
2250                                         if (port_stats.ipackets != (uint64_t)burst_size) {
2251                                                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2252                                                                 test_params->slave_port_ids[i],
2253                                                                 (unsigned int)port_stats.ipackets, burst_size);
2254                                                 return -1;
2255                                         }
2256                                 } else {
2257                                         if (port_stats.ipackets != 0) {
2258                                                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2259                                                                 test_params->slave_port_ids[i],
2260                                                                 (unsigned int)port_stats.ipackets, 0);
2261                                                 return -1;
2262                                         }
2263                                 }
2264                         }
2265                 } else {
2266                         for (j = 0; j < test_params->bonded_slave_count; j++) {
2267                                 rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
2268                                 if (port_stats.ipackets != 0) {
2269                                         printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2270                                                         test_params->slave_port_ids[i],
2271                                                         (unsigned int)port_stats.ipackets, 0);
2272                                         return -1;
2273                                 }
2274                         }
2275                 }
2276
2277                 /* free mbufs */
2278                 for (i = 0; i < MAX_PKT_BURST; i++) {
2279                         if (rx_pkt_burst[i] != NULL) {
2280                                 rte_pktmbuf_free(rx_pkt_burst[i]);
2281                                 rx_pkt_burst[i] = NULL;
2282                         }
2283                 }
2284
2285                 /* reset bonded device stats */
2286                 rte_eth_stats_reset(test_params->bonded_port_id);
2287         }
2288
2289         /* Clean up and remove slaves from bonded device */
2290         return remove_slaves_and_stop_bonded_device();
2291 }
2292
2293 static int
2294 test_activebackup_verify_promiscuous_enable_disable(void)
2295 {
2296         int i, primary_port, promiscuous_en;
2297
2298         /* Initialize bonded device with 4 slaves in round robin mode */
2299         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 4, 1)
2300                         != 0)
2301                 return -1;
2302
2303         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2304         if (primary_port < 0) {
2305                 printf("failed to get primary slave for bonded port (%d)",
2306                                 test_params->bonded_port_id);
2307         }
2308
2309         rte_eth_promiscuous_enable(test_params->bonded_port_id);
2310
2311         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
2312         if (promiscuous_en != 1) {
2313                 printf("Port (%d) promiscuous mode not enabled\n",
2314                                 test_params->bonded_port_id);
2315                 return -1;
2316         }
2317
2318         for (i = 0; i < test_params->bonded_slave_count; i++) {
2319                 promiscuous_en = rte_eth_promiscuous_get(
2320                                 test_params->slave_port_ids[i]);
2321                 if (primary_port == test_params->slave_port_ids[i]) {
2322                         if (promiscuous_en != 1) {
2323                                 printf("slave port (%d) promiscuous mode not enabled\n",
2324                                                 test_params->slave_port_ids[i]);
2325                                 return -1;
2326                         }
2327                 } else {
2328                         if (promiscuous_en != 0) {
2329                                 printf("slave port (%d) promiscuous mode enabled\n",
2330                                                 test_params->slave_port_ids[i]);
2331                                 return -1;
2332                         }
2333                 }
2334
2335         }
2336
2337         rte_eth_promiscuous_disable(test_params->bonded_port_id);
2338
2339         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
2340         if (promiscuous_en != 0) {
2341                 printf("Port (%d) promiscuous mode not disabled\n",
2342                                 test_params->bonded_port_id);
2343                 return -1;
2344         }
2345
2346         for (i = 0; i < test_params->bonded_slave_count; i++) {
2347                 promiscuous_en = rte_eth_promiscuous_get(
2348                                 test_params->slave_port_ids[i]);
2349                 if (promiscuous_en != 0) {
2350                         printf("slave port (%d) promiscuous mode not disabled\n",
2351                                         test_params->slave_port_ids[i]);
2352                         return -1;
2353                 }
2354         }
2355
2356         /* Clean up and remove slaves from bonded device */
2357         return remove_slaves_and_stop_bonded_device();
2358 }
2359
2360 static int
2361 test_activebackup_verify_mac_assignment(void)
2362 {
2363         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1;
2364
2365         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
2366         rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1);
2367
2368         /* Initialize bonded device with 2 slaves in active backup mode */
2369         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1)
2370                         != 0)
2371                 return -1;
2372
2373         /* Verify that bonded MACs is that of first slave and that the other slave
2374          * MAC hasn't been changed */
2375         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2376         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2377                 printf("bonded port (%d) mac address not set to that of primary port\n",
2378                                 test_params->bonded_port_id);
2379                 return -1;
2380         }
2381
2382         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2383         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2384                 printf("slave port (%d) mac address not set to that of primary port\n",
2385                                 test_params->slave_port_ids[0]);
2386                 return -1;
2387         }
2388
2389         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2390         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2391                 printf("slave port (%d) mac address not as expected\n",
2392                                 test_params->slave_port_ids[1]);
2393                 return -1;
2394         }
2395
2396         /* change primary and verify that MAC addresses haven't changed */
2397         if (rte_eth_bond_primary_set(test_params->bonded_port_id,
2398                         test_params->slave_port_ids[1]) != 0) {
2399                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
2400                                 test_params->bonded_port_id, test_params->slave_port_ids[1]);
2401                 return -1;
2402         }
2403
2404         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2405         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2406                 printf("bonded port (%d) mac address not set to that of primary port\n",
2407                                 test_params->bonded_port_id);
2408                 return -1;
2409         }
2410
2411         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2412         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2413                 printf("slave port (%d) mac address not set to that of primary port\n",
2414                                 test_params->slave_port_ids[0]);
2415                 return -1;
2416         }
2417
2418         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2419         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2420                 printf("slave port (%d) mac address not as expected\n",
2421                                 test_params->slave_port_ids[1]);
2422                 return -1;
2423         }
2424
2425         /* stop / start bonded device and verify that primary MAC address is
2426          * propagated to bonded device and slaves */
2427
2428         rte_eth_dev_stop(test_params->bonded_port_id);
2429
2430         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
2431                 return -1;
2432
2433         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2434         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2435                 printf("bonded port (%d) mac address not set to that of primary port\n",
2436                                 test_params->bonded_port_id);
2437                 return -1;
2438         }
2439
2440         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2441         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2442                 printf("slave port (%d) mac address not as expected\n",
2443                                 test_params->slave_port_ids[0]);
2444                 return -1;
2445         }
2446
2447         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2448         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2449                 printf("slave port (%d) mac address not set to that of primary port\n",
2450                                 test_params->slave_port_ids[1]);
2451                 return -1;
2452         }
2453
2454         /* Set explicit MAC address */
2455         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
2456                         (struct ether_addr *)bonded_mac) != 0) {
2457                 return -1;
2458         }
2459
2460         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2461         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
2462                 printf("bonded port (%d) mac address not set to that of bonded port\n",
2463                                 test_params->bonded_port_id);
2464                 return -1;
2465         }
2466
2467         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2468         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2469                 printf("slave port (%d) mac address not as expected\n",
2470                                 test_params->slave_port_ids[0]);
2471                 return -1;
2472         }
2473
2474         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2475         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
2476                 printf("slave port (%d) mac address not set to that of bonded port\n",
2477                                 test_params->slave_port_ids[1]);
2478                 return -1;
2479         }
2480
2481         /* Clean up and remove slaves from bonded device */
2482         return remove_slaves_and_stop_bonded_device();
2483 }
2484
2485 static int
2486 test_activebackup_verify_slave_link_status_change_failover(void)
2487 {
2488         struct rte_mbuf *pkt_burst[TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
2489         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
2490         struct rte_eth_stats port_stats;
2491
2492         uint8_t slaves[RTE_MAX_ETHPORTS];
2493
2494         int i, j, burst_size, slave_count, primary_port;
2495
2496         burst_size = 21;
2497
2498         memset(pkt_burst, 0, sizeof(pkt_burst));
2499
2500         /* Generate packet burst for testing */
2501         if (generate_test_burst(&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0) !=
2502                         burst_size) {
2503                 printf("generate_test_burst failed\n");
2504                 return -1;
2505         }
2506
2507         /* Initialize bonded device with 4 slaves in round robin mode */
2508         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
2509                         TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
2510                         != 0)
2511                 return -1;
2512
2513         /* Verify Current Slaves Count /Active Slave Count is */
2514         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
2515                         RTE_MAX_ETHPORTS);
2516         if (slave_count != 4) {
2517                 printf("Number of slaves (%d) is not as expected (%d).\n",
2518                                 slave_count, 4);
2519                 return -1;
2520         }
2521
2522         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
2523                         slaves, RTE_MAX_ETHPORTS);
2524         if (slave_count != 4) {
2525                 printf("Number of active slaves (%d) is not as expected (%d).\n",
2526                                 slave_count, 4);
2527                 return -1;
2528         }
2529
2530         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2531         if (primary_port != test_params->slave_port_ids[0])
2532                 printf("Primary port not as expected");
2533
2534         /* Bring 2 slaves down and verify active slave count */
2535         virtual_ethdev_simulate_link_status_interrupt(
2536                         test_params->slave_port_ids[1], 0);
2537         virtual_ethdev_simulate_link_status_interrupt(
2538                         test_params->slave_port_ids[3], 0);
2539
2540         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves,
2541                         RTE_MAX_ETHPORTS) != 2) {
2542                 printf("Number of active slaves (%d) is not as expected (%d).\n",
2543                                 slave_count, 2);
2544                 return -1;
2545         }
2546
2547         virtual_ethdev_simulate_link_status_interrupt(
2548                         test_params->slave_port_ids[1], 1);
2549         virtual_ethdev_simulate_link_status_interrupt(
2550                         test_params->slave_port_ids[3], 1);
2551
2552
2553         /* Bring primary port down, verify that active slave count is 3 and primary
2554          *  has changed */
2555         virtual_ethdev_simulate_link_status_interrupt(
2556                         test_params->slave_port_ids[0], 0);
2557
2558         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves,
2559                         RTE_MAX_ETHPORTS) != 3) {
2560                 printf("Number of active slaves (%d) is not as expected (%d).\n",
2561                                 slave_count, 3);
2562                 return -1;
2563         }
2564
2565         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2566         if (primary_port != test_params->slave_port_ids[2])
2567                 printf("Primary port not as expected");
2568
2569         /* Verify that pkts are sent on new primary slave */
2570
2571         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size)
2572                         != burst_size) {
2573                 printf("rte_eth_tx_burst failed\n");
2574                 return -1;
2575         }
2576
2577         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
2578         if (port_stats.opackets != (uint64_t)burst_size) {
2579                 printf("(%d) port_stats.opackets not as expected\n",
2580                                 test_params->slave_port_ids[2]);
2581                 return -1;
2582         }
2583
2584         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2585         if (port_stats.opackets != 0) {
2586                 printf("(%d) port_stats.opackets not as expected\n",
2587                                 test_params->slave_port_ids[0]);
2588                 return -1;
2589         }
2590         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2591         if (port_stats.opackets != 0) {
2592                 printf("(%d) port_stats.opackets not as expected\n",
2593                                 test_params->slave_port_ids[1]);
2594                 return -1;
2595         }
2596         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
2597         if (port_stats.opackets != 0) {
2598                 printf("(%d) port_stats.opackets not as expected\n",
2599                                 test_params->slave_port_ids[3]);
2600                 return -1;
2601         }
2602
2603         /* Generate packet burst for testing */
2604
2605         for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) {
2606                 if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0) !=
2607                                 burst_size)
2608                         return -1;
2609
2610                 virtual_ethdev_add_mbufs_to_rx_queue(
2611                         test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size);
2612         }
2613
2614         if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
2615                         MAX_PKT_BURST) != burst_size) {
2616                 printf("rte_eth_rx_burst\n");
2617                 return -1;
2618         }
2619
2620         /* Verify bonded device rx count */
2621         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2622         if (port_stats.ipackets != (uint64_t)burst_size) {
2623                 printf("(%d) port_stats.ipackets not as expected\n",
2624                                 test_params->bonded_port_id);
2625                 return -1;
2626         }
2627
2628         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
2629         if (port_stats.opackets != (uint64_t)burst_size) {
2630                 printf("(%d) port_stats.opackets not as expected\n",
2631                                 test_params->slave_port_ids[2]);
2632                 return -1;
2633         }
2634
2635         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2636         if (port_stats.opackets != 0) {
2637                 printf("(%d) port_stats.opackets not as expected\n",
2638                                 test_params->slave_port_ids[0]);
2639                 return -1;
2640         }
2641
2642         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2643         if (port_stats.opackets != 0) {
2644                 printf("(%d) port_stats.opackets not as expected\n",
2645                                 test_params->slave_port_ids[1]);
2646                 return -1;
2647         }
2648
2649         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
2650         if (port_stats.opackets != 0) {
2651                 printf("(%d) port_stats.opackets not as expected\n",
2652                                 test_params->slave_port_ids[3]);
2653                 return -1;
2654         }
2655
2656         /* free mbufs */
2657
2658         for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) {
2659                 for (j = 0; j < MAX_PKT_BURST; j++) {
2660                         if (pkt_burst[i][j] != NULL) {
2661                                 rte_pktmbuf_free(pkt_burst[i][j]);
2662                                 pkt_burst[i][j] = NULL;
2663                         }
2664                 }
2665         }
2666
2667
2668         /* Clean up and remove slaves from bonded device */
2669         return remove_slaves_and_stop_bonded_device();
2670 }
2671
2672 /** Balance Mode Tests */
2673
2674 static int
2675 test_balance_xmit_policy_configuration(void)
2676 {
2677         int retval;
2678
2679         retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
2680                         2, 1);
2681         if (retval != 0) {
2682                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2683                 return -1;
2684         }
2685
2686         /* Invalid port id */
2687         retval = rte_eth_bond_xmit_policy_set(INVALID_PORT_ID,
2688                         BALANCE_XMIT_POLICY_LAYER2);
2689         if (retval == 0) {
2690                 printf("Expected call to failed as invalid port specified.\n");
2691                 return -1;
2692         }
2693
2694         /* Set xmit policy on non bonded device */
2695         retval = rte_eth_bond_xmit_policy_set(test_params->slave_port_ids[0],
2696                         BALANCE_XMIT_POLICY_LAYER2);
2697         if (retval == 0) {
2698                 printf("Expected call to failed as invalid port specified.\n");
2699                 return -1;
2700         }
2701
2702         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2703                         BALANCE_XMIT_POLICY_LAYER2);
2704         if (retval != 0) {
2705                 printf("Failed to set balance xmit policy.\n");
2706                 return -1;
2707         }
2708         if (rte_eth_bond_xmit_policy_get(test_params->bonded_port_id) !=
2709                         BALANCE_XMIT_POLICY_LAYER2) {
2710                 printf("balance xmit policy not as expected.\n");
2711                 return -1;
2712         }
2713
2714         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2715                         BALANCE_XMIT_POLICY_LAYER23);
2716         if (retval != 0) {
2717                 printf("Failed to set balance xmit policy.\n");
2718                 return -1;
2719         }
2720         if (rte_eth_bond_xmit_policy_get(test_params->bonded_port_id) !=
2721                         BALANCE_XMIT_POLICY_LAYER23) {
2722                 printf("balance xmit policy not as expected.\n");
2723                 return -1;
2724         }
2725
2726         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2727                         BALANCE_XMIT_POLICY_LAYER34);
2728         if (retval != 0) {
2729                 printf("Failed to set balance xmit policy.\n");
2730                 return -1;
2731         }
2732         if (rte_eth_bond_xmit_policy_get(test_params->bonded_port_id) !=
2733                         BALANCE_XMIT_POLICY_LAYER34) {
2734                 printf("balance xmit policy not as expected.\n");
2735                 return -1;
2736         }
2737
2738         /* Invalid port id */
2739         if (rte_eth_bond_xmit_policy_get(INVALID_PORT_ID) >= 0)
2740                 return -1;
2741
2742         /* Clean up and remove slaves from bonded device */
2743         return remove_slaves_and_stop_bonded_device();
2744 }
2745
2746 #define TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT (2)
2747
2748 static int
2749 test_balance_l2_tx_burst(void)
2750 {
2751         struct rte_mbuf *pkts_burst[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
2752         int burst_size[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT] = { 10, 15 };
2753
2754         uint16_t pktlen;
2755
2756         int retval, i;
2757         struct rte_eth_stats port_stats;
2758
2759         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
2760                         TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1);
2761         if (retval != 0) {
2762                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2763                 return -1;
2764         }
2765
2766         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2767                         BALANCE_XMIT_POLICY_LAYER2);
2768         if (retval != 0) {
2769                 printf("Failed to set balance xmit policy.\n");
2770                 return -1;
2771         }
2772
2773
2774         initialize_eth_header(test_params->pkt_eth_hdr,
2775                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0);
2776         pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
2777                         dst_port_0, 16);
2778         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
2779                         dst_addr_0, pktlen);
2780
2781         /* Generate a burst 1 of packets to transmit */
2782         if (generate_packet_burst(test_params->mbuf_pool, &pkts_burst[0][0],
2783                         test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
2784                         test_params->pkt_udp_hdr, burst_size[0],
2785                         PACKET_BURST_GEN_PKT_LEN, 1) != burst_size[0])
2786                 return -1;
2787
2788         initialize_eth_header(test_params->pkt_eth_hdr,
2789                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, 0, 0);
2790
2791         /* Generate a burst 2 of packets to transmit */
2792         if (generate_packet_burst(test_params->mbuf_pool, &pkts_burst[1][0],
2793                         test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
2794                         test_params->pkt_udp_hdr, burst_size[1],
2795                         PACKET_BURST_GEN_PKT_LEN, 1) != burst_size[1])
2796                 return -1;
2797
2798         /* Send burst 1 on bonded port */
2799         for (i = 0; i < TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT; i++) {
2800                 if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkts_burst[i][0],
2801                         burst_size[i]) != burst_size[i])
2802                         return -1;
2803         }
2804         /* Verify bonded port tx stats */
2805         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2806         if (port_stats.opackets != (uint64_t)(burst_size[0] + burst_size[1])) {
2807                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
2808                                 test_params->bonded_port_id,
2809                                 (unsigned int)port_stats.opackets, burst_size[0] + burst_size[1]);
2810                 return -1;
2811         }
2812
2813
2814         /* Verify slave ports tx stats */
2815         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2816         if (port_stats.opackets != (uint64_t)burst_size[0]) {
2817                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2818                                 test_params->slave_port_ids[0],
2819                                 (unsigned int)port_stats.opackets, burst_size[0]);
2820                 return -1;
2821         }
2822
2823         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2824         if (port_stats.opackets != (uint64_t)burst_size[1]) {
2825                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2826                                 test_params->slave_port_ids[1], (
2827                                                 unsigned int)port_stats.opackets, burst_size[1]);
2828                 return -1;
2829         }
2830
2831         /* Put all slaves down and try and transmit */
2832         for (i = 0; i < test_params->bonded_slave_count; i++) {
2833
2834                 virtual_ethdev_simulate_link_status_interrupt(
2835                                 test_params->slave_port_ids[i], 0);
2836         }
2837
2838         /* Send burst on bonded port */
2839         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkts_burst[0][0],
2840                         burst_size[0]) != 0)
2841                 return -1;
2842
2843         /* Clean up and remove slaves from bonded device */
2844         return remove_slaves_and_stop_bonded_device();
2845 }
2846
2847 static int
2848 balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
2849                 uint8_t toggle_mac_addr, uint8_t toggle_ip_addr)
2850 {
2851         int retval, i;
2852         int burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
2853
2854         struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
2855         struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
2856
2857         struct rte_eth_stats port_stats;
2858
2859         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1);
2860         if (retval != 0) {
2861                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2862                 return -1;
2863         }
2864
2865         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2866                         BALANCE_XMIT_POLICY_LAYER23);
2867         if (retval != 0) {
2868                 printf("Failed to set balance xmit policy.\n");
2869                 return -1;
2870         }
2871
2872         burst_size_1 = 20;
2873         burst_size_2 = 10;
2874
2875         if (burst_size_1 > MAX_PKT_BURST || burst_size_2 > MAX_PKT_BURST) {
2876                 printf("Burst size specified is greater than supported.\n");
2877                 return -1;
2878         }
2879
2880         /* Generate test bursts of packets to transmit */
2881         if (generate_test_burst(pkts_burst_1, burst_size_1, vlan_enabled, ipv4,
2882                         0, 0, 0) != burst_size_1)
2883                 return -1;
2884
2885         if (generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4,
2886                         toggle_mac_addr, toggle_ip_addr, 0) != burst_size_2)
2887                 return -1;
2888
2889         /* Send burst 1 on bonded port */
2890         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
2891                         burst_size_1);
2892         if (nb_tx_1 != burst_size_1)
2893                 return -1;
2894
2895         /* Send burst 2 on bonded port */
2896         nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
2897                         burst_size_2);
2898         if (nb_tx_2 != burst_size_2)
2899                 return -1;
2900
2901         /* Verify bonded port tx stats */
2902         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2903         if (port_stats.opackets != (uint64_t)(nb_tx_1 + nb_tx_2)) {
2904                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
2905                                 test_params->bonded_port_id,
2906                                 (unsigned int)port_stats.opackets, nb_tx_1 + nb_tx_2);
2907                 return -1;
2908         }
2909
2910         /* Verify slave ports tx stats */
2911         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2912         if (port_stats.opackets != (uint64_t)nb_tx_1) {
2913                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2914                                 test_params->slave_port_ids[0],
2915                                 (unsigned int)port_stats.opackets, nb_tx_1);
2916                 return -1;
2917         }
2918
2919         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2920         if (port_stats.opackets != (uint64_t)nb_tx_2) {
2921                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2922                                 test_params->slave_port_ids[1],
2923                                 (unsigned int)port_stats.opackets, nb_tx_2);
2924                 return -1;
2925         }
2926
2927         /* Put all slaves down and try and transmit */
2928         for (i = 0; i < test_params->bonded_slave_count; i++) {
2929
2930                 virtual_ethdev_simulate_link_status_interrupt(
2931                                 test_params->slave_port_ids[i], 0);
2932         }
2933
2934         /* Send burst on bonded port */
2935         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
2936                         burst_size_1);
2937         if (nb_tx_1 != 0)
2938                 return -1;
2939
2940         /* Clean up and remove slaves from bonded device */
2941         return remove_slaves_and_stop_bonded_device();
2942 }
2943
2944 static int
2945 test_balance_l23_tx_burst_ipv4_toggle_ip_addr(void)
2946 {
2947         return balance_l23_tx_burst(0, 1, 1, 0);
2948 }
2949
2950 static int
2951 test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr(void)
2952 {
2953         return balance_l23_tx_burst(1, 1, 0, 1);
2954 }
2955
2956 static int
2957 test_balance_l23_tx_burst_ipv6_toggle_ip_addr(void)
2958 {
2959         return balance_l23_tx_burst(0, 0, 0, 1);
2960 }
2961
2962 static int
2963 test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr(void)
2964 {
2965         return balance_l23_tx_burst(1, 0, 0, 1);
2966 }
2967
2968 static int
2969 test_balance_l23_tx_burst_toggle_mac_addr(void)
2970 {
2971         return balance_l23_tx_burst(0, 0, 1, 0);
2972 }
2973
2974 static int
2975 balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
2976                 uint8_t toggle_mac_addr, uint8_t toggle_ip_addr,
2977                 uint8_t toggle_udp_port)
2978 {
2979         int retval, i;
2980         int burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
2981
2982         struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
2983         struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
2984
2985         struct rte_eth_stats port_stats;
2986
2987         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1);
2988         if (retval != 0) {
2989                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2990                 return -1;
2991         }
2992
2993         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2994                         BALANCE_XMIT_POLICY_LAYER34);
2995         if (retval != 0) {
2996                 printf("Failed to set balance xmit policy.\n");
2997                 return -1;
2998         }
2999
3000         burst_size_1 = 20;
3001         burst_size_2 = 10;
3002
3003         if (burst_size_1 > MAX_PKT_BURST || burst_size_2 > MAX_PKT_BURST) {
3004                 printf("Burst size specified is greater than supported.\n");
3005                 return -1;
3006         }
3007
3008         /* Generate test bursts of packets to transmit */
3009         if (generate_test_burst(pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0,
3010                         0, 0) != burst_size_1)
3011                 return -1;
3012
3013         if (generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4,
3014                         toggle_mac_addr, toggle_ip_addr, toggle_udp_port) != burst_size_2)
3015                 return -1;
3016
3017         /* Send burst 1 on bonded port */
3018         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
3019                         burst_size_1);
3020         if (nb_tx_1 != burst_size_1)
3021                 return -1;
3022
3023         /* Send burst 2 on bonded port */
3024         nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
3025                         burst_size_2);
3026         if (nb_tx_2 != burst_size_2)
3027                 return -1;
3028
3029
3030         /* Verify bonded port tx stats */
3031         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3032         if (port_stats.opackets != (uint64_t)(nb_tx_1 + nb_tx_2)) {
3033                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
3034                                 test_params->bonded_port_id,
3035                                 (unsigned int)port_stats.opackets, nb_tx_1 + nb_tx_2);
3036                 return -1;
3037         }
3038
3039         /* Verify slave ports tx stats */
3040         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3041         if (port_stats.opackets != (uint64_t)nb_tx_1) {
3042                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
3043                                 test_params->slave_port_ids[0],
3044                                 (unsigned int)port_stats.opackets, nb_tx_1);
3045                 return -1;
3046         }
3047
3048         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3049         if (port_stats.opackets != (uint64_t)nb_tx_2) {
3050                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
3051                                 test_params->slave_port_ids[1],
3052                                 (unsigned int)port_stats.opackets, nb_tx_2);
3053                 return -1;
3054         }
3055
3056         /* Put all slaves down and try and transmit */
3057         for (i = 0; i < test_params->bonded_slave_count; i++) {
3058
3059                 virtual_ethdev_simulate_link_status_interrupt(
3060                                 test_params->slave_port_ids[i], 0);
3061         }
3062
3063         /* Send burst on bonded port */
3064         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
3065                         burst_size_1);
3066         if (nb_tx_1 != 0)
3067                 return -1;
3068
3069         /* Clean up and remove slaves from bonded device */
3070         return remove_slaves_and_stop_bonded_device();
3071 }
3072
3073 static int
3074 test_balance_l34_tx_burst_ipv4_toggle_ip_addr(void)
3075 {
3076         return balance_l34_tx_burst(0, 1, 0, 1, 0);
3077 }
3078
3079 static int
3080 test_balance_l34_tx_burst_ipv4_toggle_udp_port(void)
3081 {
3082         return balance_l34_tx_burst(0, 1, 0, 0, 1);
3083 }
3084
3085 static int
3086 test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr(void)
3087 {
3088         return balance_l34_tx_burst(1, 1, 0, 1, 0);
3089 }
3090
3091 static int
3092 test_balance_l34_tx_burst_ipv6_toggle_ip_addr(void)
3093 {
3094         return balance_l34_tx_burst(0, 0, 0, 1, 0);
3095 }
3096
3097 static int
3098 test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr(void)
3099 {
3100         return balance_l34_tx_burst(1, 0, 0, 1, 0);
3101 }
3102
3103 static int
3104 test_balance_l34_tx_burst_ipv6_toggle_udp_port(void)
3105 {
3106         return balance_l34_tx_burst(0, 0, 0, 0, 1);
3107 }
3108
3109 #define TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT                      (2)
3110 #define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1                     (40)
3111 #define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2                     (20)
3112 #define TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT            (25)
3113 #define TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX        (0)
3114
3115 static int
3116 test_balance_tx_burst_slave_tx_fail(void)
3117 {
3118         struct rte_mbuf *pkts_burst_1[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1];
3119         struct rte_mbuf *pkts_burst_2[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2];
3120
3121         struct rte_mbuf *expected_fail_pkts[TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT];
3122
3123         struct rte_eth_stats port_stats;
3124
3125         int i, first_tx_fail_idx, tx_count_1, tx_count_2;
3126
3127         TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
3128                         BONDING_MODE_BALANCE, 0,
3129                         TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
3130                         "Failed to intialise bonded device");
3131
3132         TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
3133                         test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
3134                         "Failed to set balance xmit policy.");
3135
3136
3137         /* Generate test bursts for transmission */
3138         TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_1,
3139                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1, 0, 0, 0, 0, 0),
3140                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1,
3141                         "Failed to generate test packet burst 1");
3142
3143         first_tx_fail_idx = TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3144                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT;
3145
3146         /* copy mbuf referneces for expected transmission failures */
3147         for (i = 0; i < TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT; i++)
3148                 expected_fail_pkts[i] = pkts_burst_1[i + first_tx_fail_idx];
3149
3150         TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2,
3151                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, 0, 0, 1, 0, 0),
3152                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
3153                         "Failed to generate test packet burst 2");
3154
3155
3156         /* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail
3157          * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */
3158         virtual_ethdev_tx_burst_fn_set_success(
3159                         test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
3160                         0);
3161
3162         virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
3163                         test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
3164                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
3165
3166
3167         /* Transmit burst 1 */
3168         tx_count_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
3169                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1);
3170
3171         TEST_ASSERT_EQUAL(tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3172                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,
3173                         "Transmitted (%d) packets, expected to transmit (%d) packets",
3174                         tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3175                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
3176
3177         /* Verify that failed packet are expected failed packets */
3178         for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
3179                 TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst_1[i + tx_count_1],
3180                                 "expected mbuf (%d) pointer %p not expected pointer %p",
3181                                 i, expected_fail_pkts[i], pkts_burst_1[i + tx_count_1]);
3182         }
3183
3184         /* Transmit burst 2 */
3185         tx_count_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
3186                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
3187
3188         TEST_ASSERT_EQUAL(tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
3189                         "Transmitted (%d) packets, expected to transmit (%d) packets",
3190                         tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
3191
3192
3193         /* Verify bonded port tx stats */
3194         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3195
3196         TEST_ASSERT_EQUAL(port_stats.opackets,
3197                         (uint64_t)((TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3198                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +
3199                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2),
3200                         "Bonded Port (%d) opackets value (%u) not as expected (%d)",
3201                         test_params->bonded_port_id, (unsigned int)port_stats.opackets,
3202                         (TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3203                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +
3204                         TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
3205
3206         /* Verify slave ports tx stats */
3207
3208         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3209
3210         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)
3211                                 TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3212                                 TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,
3213                                 "Slave Port (%d) opackets value (%u) not as expected (%d)",
3214                                 test_params->slave_port_ids[0],
3215                                 (unsigned int)port_stats.opackets,
3216                                 TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
3217                                 TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
3218
3219
3220
3221
3222         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3223
3224         TEST_ASSERT_EQUAL(port_stats.opackets,
3225                                 (uint64_t)TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
3226                                 "Slave Port (%d) opackets value (%u) not as expected (%d)",
3227                                 test_params->slave_port_ids[1],
3228                                 (unsigned int)port_stats.opackets,
3229                                 TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
3230
3231 #ifdef RTE_MBUF_REFCNT
3232         /* Verify that all mbufs have a ref value of zero */
3233         TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst_1[tx_count_1],
3234                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, 1),
3235                         "mbufs refcnts not as expected");
3236 #endif
3237
3238         free_mbufs(&pkts_burst_1[tx_count_1],
3239                         TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
3240
3241         /* Clean up and remove slaves from bonded device */
3242         return remove_slaves_and_stop_bonded_device();
3243 }
3244
3245 #define TEST_BALANCE_RX_BURST_SLAVE_COUNT (3)
3246
3247 static int
3248 test_balance_rx_burst(void)
3249 {
3250         struct rte_mbuf *gen_pkt_burst[TEST_BALANCE_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
3251
3252         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
3253         struct rte_eth_stats port_stats;
3254
3255         int burst_size[TEST_BALANCE_RX_BURST_SLAVE_COUNT] = { 10, 5, 30 };
3256         int i, j, nb_rx;
3257
3258         memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
3259
3260         /* Initialize bonded device with 4 slaves in round robin mode */
3261         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 3, 1)
3262                         != 0)
3263                 return -1;
3264
3265         /* Generate test bursts of packets to transmit */
3266         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
3267                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size[i], 0, 0, 1,
3268                                 0, 0) != burst_size[i])
3269                         return -1;
3270         }
3271         /* Add rx data to slaves */
3272         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
3273                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
3274                                 &gen_pkt_burst[i][0], burst_size[i]);
3275         }
3276
3277         /* Call rx burst on bonded device */
3278         /* Send burst on bonded port */
3279         nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
3280                         MAX_PKT_BURST);
3281         if (nb_rx != burst_size[0] + burst_size[1] + burst_size[2]) {
3282                 printf("balance rx burst failed\n");
3283                 return -1;
3284         }
3285
3286         /* Verify bonded device rx count */
3287         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3288         if (port_stats.ipackets != (uint64_t)(burst_size[0] + burst_size[1] +
3289                         burst_size[2])) {
3290                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
3291                                 test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
3292                                 burst_size[0] + burst_size[1] + burst_size[2]);
3293                 return -1;
3294         }
3295
3296
3297         /* Verify bonded slave devices rx counts */
3298         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3299         if (port_stats.ipackets != (uint64_t)burst_size[0]) {
3300                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3301                                 test_params->slave_port_ids[0],
3302                                 (unsigned int)port_stats.ipackets, burst_size[0]);
3303                 return -1;
3304         }
3305
3306         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3307         if (port_stats.ipackets != (uint64_t)burst_size[1]) {
3308                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3309                                 test_params->slave_port_ids[1],
3310                                 (unsigned int)port_stats.ipackets, burst_size[1]);
3311                 return -1;
3312         }
3313
3314         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3315         if (port_stats.ipackets != (uint64_t)burst_size[2]) {
3316                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3317                                 test_params->slave_port_ids[2],
3318                                 (unsigned int)port_stats.ipackets, burst_size[2]);
3319                 return -1;
3320         }
3321
3322         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
3323         if (port_stats.ipackets != 0) {
3324                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3325                                 test_params->slave_port_ids[3],
3326                                 (unsigned int)port_stats.ipackets, 0);
3327                 return -1;
3328         }
3329
3330         /* free mbufs */
3331         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
3332                 for (j = 0; j < MAX_PKT_BURST; j++) {
3333                         if (gen_pkt_burst[i][j] != NULL) {
3334                                 rte_pktmbuf_free(gen_pkt_burst[i][j]);
3335                                 gen_pkt_burst[i][j] = NULL;
3336                         }
3337                 }
3338         }
3339
3340         /* Clean up and remove slaves from bonded device */
3341         return remove_slaves_and_stop_bonded_device();
3342 }
3343
3344 static int
3345 test_balance_verify_promiscuous_enable_disable(void)
3346 {
3347         int i, promiscuous_en;
3348
3349         /* Initialize bonded device with 4 slaves in round robin mode */
3350         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 4, 1) != 0)
3351                 return -1;
3352
3353         rte_eth_promiscuous_enable(test_params->bonded_port_id);
3354
3355         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
3356         if (promiscuous_en != 1) {
3357                 printf("Port (%d) promiscuous mode not enabled\n",
3358                                 test_params->bonded_port_id);
3359                 return -1;
3360         }
3361
3362         for (i = 0; i < test_params->bonded_slave_count; i++) {
3363                 promiscuous_en = rte_eth_promiscuous_get(
3364                                 test_params->slave_port_ids[i]);
3365                 if (promiscuous_en != 1) {
3366                         printf("slave port (%d) promiscuous mode not enabled\n",
3367                                         test_params->slave_port_ids[i]);
3368                         return -1;
3369                 }
3370         }
3371
3372         rte_eth_promiscuous_disable(test_params->bonded_port_id);
3373
3374         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
3375         if (promiscuous_en != 0) {
3376                 printf("Port (%d) promiscuous mode not disabled\n",
3377                                 test_params->bonded_port_id);
3378                 return -1;
3379         }
3380
3381         for (i = 0; i < test_params->bonded_slave_count; i++) {
3382                 promiscuous_en = rte_eth_promiscuous_get(
3383                                 test_params->slave_port_ids[i]);
3384                 if (promiscuous_en != 0) {
3385                         printf("slave port (%d) promiscuous mode not disabled\n",
3386                                         test_params->slave_port_ids[i]);
3387                         return -1;
3388                 }
3389         }
3390
3391         /* Clean up and remove slaves from bonded device */
3392         return remove_slaves_and_stop_bonded_device();
3393 }
3394
3395 static int
3396 test_balance_verify_mac_assignment(void)
3397 {
3398         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1;
3399
3400         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
3401         rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1);
3402
3403         /* Initialize bonded device with 2 slaves in active backup mode */
3404         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1) != 0)
3405                 return -1;
3406
3407         /* Verify that bonded MACs is that of first slave and that the other slave
3408          * MAC hasn't been changed */
3409         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3410         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
3411                 printf("bonded port (%d) mac address not set to that of primary port\n",
3412                                 test_params->bonded_port_id);
3413                 return -1;
3414         }
3415
3416         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
3417         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
3418                 printf("slave port (%d) mac address not set to that of primary port\n",
3419                                 test_params->slave_port_ids[0]);
3420                 return -1;
3421         }
3422
3423         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
3424         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
3425                 printf("slave port (%d) mac address not set to that of primary port\n",
3426                                 test_params->slave_port_ids[1]);
3427                 return -1;
3428         }
3429
3430         /* change primary and verify that MAC addresses haven't changed */
3431         if (rte_eth_bond_primary_set(test_params->bonded_port_id,
3432                         test_params->slave_port_ids[1]) != 0) {
3433                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
3434                                 test_params->bonded_port_id, test_params->slave_port_ids[1]);
3435                 return -1;
3436         }
3437
3438         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3439         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
3440                 printf("bonded port (%d) mac address not set to that of primary port\n",
3441                                 test_params->bonded_port_id);
3442                 return -1;
3443         }
3444
3445         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
3446         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
3447                 printf("slave port (%d) mac address not set to that of primary port\n",
3448                                 test_params->slave_port_ids[0]);
3449                 return -1;
3450         }
3451
3452         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
3453         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
3454                 printf("slave port (%d) mac address not set to that of primary port\n",
3455                                 test_params->slave_port_ids[1]);
3456                 return -1;
3457         }
3458
3459         /* stop / start bonded device and verify that primary MAC address is
3460          * propagated to bonded device and slaves */
3461
3462         rte_eth_dev_stop(test_params->bonded_port_id);
3463
3464         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
3465                 return -1;
3466
3467         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3468         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
3469                 printf("bonded port (%d) mac address not set to that of primary port\n",
3470                                 test_params->bonded_port_id);
3471                 return -1;
3472         }
3473
3474         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
3475         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
3476                 printf("slave port (%d) mac address not set to that of primary port\n",
3477                                 test_params->slave_port_ids[0]);
3478                 return -1;
3479         }
3480
3481         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
3482         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
3483                 printf("slave port (%d) mac address not set to that of primary port\n",
3484                                 test_params->slave_port_ids[1]);
3485                 return -1;
3486         }
3487
3488         /* Set explicit MAC address */
3489         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
3490                         (struct ether_addr *)bonded_mac) != 0)
3491                 return -1;
3492
3493         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3494         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3495                 printf("bonded port (%d) mac address not set to that of bonded port\n",
3496                                 test_params->bonded_port_id);
3497                 return -1;
3498         }
3499
3500         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
3501         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3502                 printf("slave port (%d) mac address not as expected\n",
3503                                 test_params->slave_port_ids[0]);
3504                 return -1;
3505         }
3506
3507         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
3508         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3509                 printf("slave port (%d) mac address not set to that of bonded port\n",
3510                                 test_params->slave_port_ids[1]);
3511                 return -1;
3512         }
3513
3514         /* Clean up and remove slaves from bonded device */
3515         return remove_slaves_and_stop_bonded_device();
3516 }
3517
3518 #define TEST_BALANCE_LINK_STATUS_SLAVE_COUNT (4)
3519
3520 static int
3521 test_balance_verify_slave_link_status_change_behaviour(void)
3522 {
3523         struct rte_mbuf *pkt_burst[TEST_BALANCE_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST];
3524         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
3525         struct rte_eth_stats port_stats;
3526
3527         uint8_t slaves[RTE_MAX_ETHPORTS];
3528
3529         int i, j, burst_size, slave_count;
3530
3531         memset(pkt_burst, 0, sizeof(pkt_burst));
3532
3533         /* Initialize bonded device with 4 slaves in round robin mode */
3534         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
3535                         TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1) != 0)
3536                 return -1;
3537
3538         if (rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
3539                         BALANCE_XMIT_POLICY_LAYER2)) {
3540                 printf("Failed to set balance xmit policy.\n");
3541                 return -1;
3542         }
3543
3544         /* Verify Current Slaves Count /Active Slave Count is */
3545         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
3546                         RTE_MAX_ETHPORTS);
3547         if (slave_count != TEST_BALANCE_LINK_STATUS_SLAVE_COUNT) {
3548                 printf("Number of slaves (%d) is not as expected (%d).\n", slave_count,
3549                                 TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
3550                 return -1;
3551         }
3552
3553         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
3554                         slaves, RTE_MAX_ETHPORTS);
3555         if (slave_count != TEST_BALANCE_LINK_STATUS_SLAVE_COUNT) {
3556                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3557                                 slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
3558                 return -1;
3559         }
3560
3561         /* Set 2 slaves link status to down */
3562         virtual_ethdev_simulate_link_status_interrupt(
3563                         test_params->slave_port_ids[1], 0);
3564         virtual_ethdev_simulate_link_status_interrupt(
3565                         test_params->slave_port_ids[3], 0);
3566
3567         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
3568                         slaves, RTE_MAX_ETHPORTS) != 2) {
3569                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3570                                 slave_count, 2);
3571                 return -1;
3572         }
3573
3574         /* Send to sets of packet burst and verify that they are balanced across
3575          *  slaves */
3576         burst_size = 21;
3577
3578         if (generate_test_burst(&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0) !=
3579                         burst_size) {
3580                 printf("generate_test_burst failed\n");
3581                 return -1;
3582         }
3583
3584         if (generate_test_burst(&pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0) !=
3585                         burst_size) {
3586                 printf("generate_test_burst failed\n");
3587                 return -1;
3588         }
3589
3590         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0],
3591                         burst_size) != burst_size) {
3592                 printf("rte_eth_tx_burst failed\n");
3593                 return -1;
3594         }
3595
3596         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[1][0],
3597                         burst_size) != burst_size) {
3598                 printf("rte_eth_tx_burst failed\n");
3599                 return -1;
3600         }
3601
3602         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3603         if (port_stats.opackets != (uint64_t)(burst_size + burst_size)) {
3604                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3605                                 test_params->bonded_port_id, (int)port_stats.opackets,
3606                                 burst_size + burst_size);
3607                 return -1;
3608         }
3609
3610         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3611         if (port_stats.opackets != (uint64_t)burst_size) {
3612                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3613                                 test_params->slave_port_ids[0], (int)port_stats.opackets,
3614                                 burst_size);
3615                 return -1;
3616         }
3617
3618         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3619         if (port_stats.opackets != (uint64_t)burst_size) {
3620                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3621                                 test_params->slave_port_ids[2], (int)port_stats.opackets,
3622                                 burst_size);
3623                 return -1;
3624         }
3625
3626         /* verify that all packets get send on primary slave when no other slaves
3627          * are available */
3628         virtual_ethdev_simulate_link_status_interrupt(
3629                         test_params->slave_port_ids[2], 0);
3630
3631         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves,
3632                         RTE_MAX_ETHPORTS) != 1) {
3633                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3634                                 slave_count, 1);
3635                 return -1;
3636         }
3637
3638         if (generate_test_burst(&pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0) !=
3639                         burst_size) {
3640                 printf("generate_test_burst failed\n");
3641                 return -1;
3642         }
3643
3644         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[1][0],
3645                         burst_size) != burst_size) {
3646                 printf("rte_eth_tx_burst failed\n");
3647                 return -1;
3648         }
3649
3650         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3651         if (port_stats.opackets != (uint64_t)(burst_size + burst_size +
3652                         burst_size)) {
3653                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3654                                 test_params->bonded_port_id, (int)port_stats.opackets,
3655                                 burst_size + burst_size + burst_size);
3656                 return -1;
3657         }
3658
3659         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3660         if (port_stats.opackets != (uint64_t)(burst_size + burst_size)) {
3661                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3662                                 test_params->slave_port_ids[0], (int)port_stats.opackets,
3663                                 burst_size + burst_size);
3664                 return -1;
3665         }
3666
3667
3668         virtual_ethdev_simulate_link_status_interrupt(
3669                         test_params->slave_port_ids[0], 0);
3670         virtual_ethdev_simulate_link_status_interrupt(
3671                         test_params->slave_port_ids[1], 1);
3672         virtual_ethdev_simulate_link_status_interrupt(
3673                         test_params->slave_port_ids[2], 1);
3674         virtual_ethdev_simulate_link_status_interrupt(
3675                         test_params->slave_port_ids[3], 1);
3676
3677         for (i = 0; i < TEST_BALANCE_LINK_STATUS_SLAVE_COUNT; i++) {
3678                 if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0) !=
3679                                 burst_size)
3680                         return -1;
3681
3682                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
3683                                 &pkt_burst[i][0], burst_size);
3684         }
3685
3686
3687
3688         /* Verify that pkts are not received on slaves with link status down */
3689
3690         rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
3691                         MAX_PKT_BURST);
3692
3693         /* Verify bonded device rx count */
3694         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3695         if (port_stats.ipackets != (uint64_t)(burst_size * 3)) {
3696                 printf("(%d) port_stats.ipackets (%d) not as expected (%d)\n",
3697                                 test_params->bonded_port_id, (int)port_stats.ipackets,
3698                                 burst_size * 3);
3699                 return -1;
3700         }
3701
3702         /* free mbufs allocate for rx testing */
3703         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
3704                 for (j = 0; j < MAX_PKT_BURST; j++) {
3705                         if (pkt_burst[i][j] != NULL) {
3706                                 rte_pktmbuf_free(pkt_burst[i][j]);
3707                                 pkt_burst[i][j] = NULL;
3708                         }
3709                 }
3710         }
3711
3712         /* Clean up and remove slaves from bonded device */
3713         return remove_slaves_and_stop_bonded_device();
3714 }
3715
3716 #ifdef RTE_MBUF_REFCNT
3717 /** Broadcast Mode Tests */
3718
3719 static int
3720 test_broadcast_tx_burst(void)
3721 {
3722         int i, pktlen, retval, burst_size, generated_burst_size, nb_tx;
3723         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
3724
3725         struct rte_eth_stats port_stats;
3726
3727         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 2, 1);
3728         if (retval != 0) {
3729                 printf("Failed to initialize_bonded_device_with_slaves.\n");
3730                 return -1;
3731         }
3732
3733         initialize_eth_header(test_params->pkt_eth_hdr,
3734                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0);
3735
3736         pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
3737                         dst_port_0, 16);
3738         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
3739                         dst_addr_0, pktlen);
3740
3741         burst_size = 20 * test_params->bonded_slave_count;
3742
3743         if (burst_size > MAX_PKT_BURST) {
3744                 printf("Burst size specified is greater than supported.\n");
3745                 return -1;
3746         }
3747
3748         /* Generate a burst of packets to transmit */
3749         generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
3750                         pkts_burst,     test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
3751                         1, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN,
3752                         1);
3753         if (generated_burst_size != burst_size)
3754                 return -1;
3755
3756         /* Send burst on bonded port */
3757         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
3758                         burst_size);
3759         if (nb_tx != burst_size) {
3760                 printf("Bonded Port (%d) rx burst failed, packets transmitted value (%u) not as expected (%d)\n",
3761                                 test_params->bonded_port_id,
3762                                 nb_tx, burst_size);
3763                 return -1;
3764         }
3765
3766         /* Verify bonded port tx stats */
3767         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3768         if (port_stats.opackets != (uint64_t)burst_size *
3769                         test_params->bonded_slave_count) {
3770                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
3771                                 test_params->bonded_port_id, (unsigned int)port_stats.opackets,
3772                                 burst_size);
3773         }
3774
3775         /* Verify slave ports tx stats */
3776         for (i = 0; i < test_params->bonded_slave_count; i++) {
3777                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
3778                 if (port_stats.opackets != (uint64_t)burst_size) {
3779                         printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
3780                                         test_params->bonded_port_id,
3781                                         (unsigned int)port_stats.opackets, burst_size);
3782                 }
3783         }
3784
3785         /* Put all slaves down and try and transmit */
3786         for (i = 0; i < test_params->bonded_slave_count; i++) {
3787
3788                 virtual_ethdev_simulate_link_status_interrupt(
3789                                 test_params->slave_port_ids[i], 0);
3790         }
3791
3792         /* Send burst on bonded port */
3793         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
3794                         burst_size);
3795         if (nb_tx != 0)
3796                 return -1;
3797
3798         /* Clean up and remove slaves from bonded device */
3799         return remove_slaves_and_stop_bonded_device();
3800 }
3801
3802
3803 #define TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT            (3)
3804 #define TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE                     (40)
3805 #define TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT      (15)
3806 #define TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT      (10)
3807
3808 static int
3809 test_broadcast_tx_burst_slave_tx_fail(void)
3810 {
3811         struct rte_mbuf *pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE];
3812         struct rte_mbuf *expected_fail_pkts[TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT];
3813
3814         struct rte_eth_stats port_stats;
3815
3816         int i, tx_count;
3817
3818         TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
3819                         BONDING_MODE_BROADCAST, 0,
3820                         TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
3821                         "Failed to intialise bonded device");
3822
3823         /* Generate test bursts for transmission */
3824         TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst,
3825                         TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE, 0, 0, 0, 0, 0),
3826                         TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE,
3827                         "Failed to generate test packet burst");
3828
3829         for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {
3830                 expected_fail_pkts[i] = pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3831                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT + i];
3832         }
3833
3834         /* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail
3835          * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */
3836         virtual_ethdev_tx_burst_fn_set_success(
3837                         test_params->slave_port_ids[0],
3838                         0);
3839         virtual_ethdev_tx_burst_fn_set_success(
3840                         test_params->slave_port_ids[1],
3841                         0);
3842         virtual_ethdev_tx_burst_fn_set_success(
3843                         test_params->slave_port_ids[2],
3844                         0);
3845
3846         virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
3847                         test_params->slave_port_ids[0],
3848                         TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
3849
3850         virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
3851                         test_params->slave_port_ids[1],
3852                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
3853
3854         virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
3855                         test_params->slave_port_ids[2],
3856                         TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
3857
3858         /* Transmit burst */
3859         tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
3860                         TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE);
3861
3862         TEST_ASSERT_EQUAL(tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3863                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,
3864                         "Transmitted (%d) packets, expected to transmit (%d) packets",
3865                         tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3866                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
3867
3868         /* Verify that failed packet are expected failed packets */
3869         for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {
3870                 TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst[i + tx_count],
3871                                 "expected mbuf (%d) pointer %p not expected pointer %p",
3872                                 i, expected_fail_pkts[i], pkts_burst[i + tx_count]);
3873         }
3874
3875         /* Verify slave ports tx stats */
3876
3877         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3878
3879         TEST_ASSERT_EQUAL(port_stats.opackets,
3880                         (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3881                         TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,
3882                         "Port (%d) opackets value (%u) not as expected (%d)",
3883                         test_params->bonded_port_id, (unsigned int)port_stats.opackets,
3884                         TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3885                         TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
3886
3887
3888         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3889
3890         TEST_ASSERT_EQUAL(port_stats.opackets,
3891                         (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3892                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,
3893                         "Port (%d) opackets value (%u) not as expected (%d)",
3894                         test_params->bonded_port_id, (unsigned int)port_stats.opackets,
3895                         TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3896                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
3897
3898         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3899
3900         TEST_ASSERT_EQUAL(port_stats.opackets,
3901                         (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3902                         TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,
3903                         "Port (%d) opackets value (%u) not as expected (%d)",
3904                         test_params->bonded_port_id, (unsigned int)port_stats.opackets,
3905                         TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
3906                         TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
3907
3908
3909         /* Verify that all mbufs who transmission failed have a ref value of one */
3910         TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst[tx_count],
3911                         TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, 1),
3912                         "mbufs refcnts not as expected");
3913
3914         free_mbufs(&pkts_burst[tx_count],
3915                 TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
3916
3917         /* Clean up and remove slaves from bonded device */
3918         return remove_slaves_and_stop_bonded_device();
3919 }
3920
3921 #define BROADCAST_RX_BURST_NUM_OF_SLAVES (3)
3922
3923 static int
3924 test_broadcast_rx_burst(void)
3925 {
3926         struct rte_mbuf *gen_pkt_burst[BROADCAST_RX_BURST_NUM_OF_SLAVES][MAX_PKT_BURST];
3927
3928         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
3929         struct rte_eth_stats port_stats;
3930
3931         int burst_size[BROADCAST_RX_BURST_NUM_OF_SLAVES] = { 10, 5, 30 };
3932         int i, j, nb_rx;
3933
3934         memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
3935
3936         /* Initialize bonded device with 4 slaves in round robin mode */
3937         if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 3, 1) != 0)
3938                 return -1;
3939
3940
3941         /* Generate test bursts of packets to transmit */
3942         for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
3943                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size[i], 0, 0, 1, 0,
3944                                 0) != burst_size[i])
3945                         return -1;
3946         }
3947
3948         /* Add rx data to slave 0 */
3949         for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
3950                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
3951                                 &gen_pkt_burst[i][0], burst_size[i]);
3952         }
3953
3954
3955         /* Call rx burst on bonded device */
3956         /* Send burst on bonded port */
3957         nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
3958                         MAX_PKT_BURST);
3959         if (nb_rx != burst_size[0] + burst_size[1] + burst_size[2]) {
3960                 printf("round-robin rx burst failed");
3961                 return -1;
3962         }
3963
3964         /* Verify bonded device rx count */
3965         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3966         if (port_stats.ipackets != (uint64_t)(burst_size[0] + burst_size[1] +
3967                         burst_size[2])) {
3968                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
3969                                 test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
3970                                 burst_size[0] + burst_size[1] + burst_size[2]);
3971                 return -1;
3972         }
3973
3974
3975         /* Verify bonded slave devices rx counts */
3976         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3977         if (port_stats.ipackets != (uint64_t)burst_size[0]) {
3978                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3979                                 test_params->slave_port_ids[0],
3980                                 (unsigned int)port_stats.ipackets, burst_size[0]);
3981                 return -1;
3982         }
3983
3984         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3985         if (port_stats.ipackets != (uint64_t)burst_size[1]) {
3986                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3987                                 test_params->slave_port_ids[1],
3988                                 (unsigned int)port_stats.ipackets, burst_size[1]);
3989                 return -1;
3990         }
3991
3992         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3993         if (port_stats.ipackets != (uint64_t)burst_size[2]) {
3994                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3995                                 test_params->slave_port_ids[2],
3996                                 (unsigned int)port_stats.ipackets,
3997                                 burst_size[2]);
3998                 return -1;
3999         }
4000
4001         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
4002         if (port_stats.ipackets != 0) {
4003                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
4004                                 test_params->slave_port_ids[3],
4005                                 (unsigned int)port_stats.ipackets, 0);
4006                 return -1;
4007         }
4008
4009         /* free mbufs allocate for rx testing */
4010         for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
4011                 for (j = 0; j < MAX_PKT_BURST; j++) {
4012                         if (gen_pkt_burst[i][j] != NULL) {
4013                                 rte_pktmbuf_free(gen_pkt_burst[i][j]);
4014                                 gen_pkt_burst[i][j] = NULL;
4015                         }
4016                 }
4017         }
4018
4019         /* Clean up and remove slaves from bonded device */
4020         return remove_slaves_and_stop_bonded_device();
4021 }
4022
4023 static int
4024 test_broadcast_verify_promiscuous_enable_disable(void)
4025 {
4026         int i, promiscuous_en;
4027
4028         /* Initialize bonded device with 4 slaves in round robin mode */
4029         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 4, 1) != 0)
4030                 return -1;
4031
4032         rte_eth_promiscuous_enable(test_params->bonded_port_id);
4033
4034         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
4035         if (promiscuous_en != 1) {
4036                 printf("Port (%d) promiscuous mode not enabled\n",
4037                                 test_params->bonded_port_id);
4038                 return -1;
4039         }
4040
4041         for (i = 0; i < test_params->bonded_slave_count; i++) {
4042                 promiscuous_en = rte_eth_promiscuous_get(
4043                                 test_params->slave_port_ids[i]);
4044                 if (promiscuous_en != 1) {
4045                         printf("slave port (%d) promiscuous mode not enabled\n",
4046                                         test_params->slave_port_ids[i]);
4047                         return -1;
4048                 }
4049         }
4050
4051         rte_eth_promiscuous_disable(test_params->bonded_port_id);
4052
4053         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
4054         if (promiscuous_en != 0) {
4055                 printf("Port (%d) promiscuous mode not disabled\n",
4056                                 test_params->bonded_port_id);
4057                 return -1;
4058         }
4059
4060         for (i = 0; i < test_params->bonded_slave_count; i++) {
4061                 promiscuous_en = rte_eth_promiscuous_get(
4062                                 test_params->slave_port_ids[i]);
4063                 if (promiscuous_en != 0) {
4064                         printf("slave port (%d) promiscuous mode not disabled\n",
4065                                         test_params->slave_port_ids[i]);
4066                         return -1;
4067                 }
4068         }
4069
4070         /* Clean up and remove slaves from bonded device */
4071         return remove_slaves_and_stop_bonded_device();
4072 }
4073
4074 static int
4075 test_broadcast_verify_mac_assignment(void)
4076 {
4077         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1;
4078
4079         int i, retval;
4080
4081         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
4082         rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_1);
4083
4084         /* Initialize bonded device with 4 slaves in round robin mode */
4085         if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 4, 1) != 0)
4086                 return -1;
4087
4088         /* Verify that all MACs are the same as first slave added to bonded
4089          * device */
4090         for (i = 0; i < test_params->bonded_slave_count; i++) {
4091                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
4092                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
4093                                 sizeof(read_mac_addr))) {
4094                         printf("slave port (%d) mac address not set to that of primary port\n",
4095                                         test_params->slave_port_ids[i]);
4096                         return -1;
4097                 }
4098         }
4099
4100         /* change primary and verify that MAC addresses haven't changed */
4101         retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
4102                         test_params->slave_port_ids[2]);
4103         if (retval != 0) {
4104                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
4105                                 test_params->bonded_port_id, test_params->slave_port_ids[i]);
4106                 return -1;
4107         }
4108
4109         for (i = 0; i < test_params->bonded_slave_count; i++) {
4110                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
4111                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
4112                                 sizeof(read_mac_addr))) {
4113                         printf("slave port (%d) mac address has changed to that of primary"
4114                                         "port without stop/start toggle of bonded device\n",
4115                                         test_params->slave_port_ids[i]);
4116                         return -1;
4117                 }
4118         }
4119
4120         /* stop / start bonded device and verify that primary MAC address is
4121          * propagated to bonded device and slaves */
4122
4123         rte_eth_dev_stop(test_params->bonded_port_id);
4124
4125         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
4126                 return -1;
4127
4128         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
4129         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
4130                 printf("bonded port (%d) mac address not set to that of new primary"
4131                                 " port\n", test_params->slave_port_ids[i]);
4132                 return -1;
4133         }
4134
4135         for (i = 0; i < test_params->bonded_slave_count; i++) {
4136                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
4137                 if (memcmp(&expected_mac_addr_1, &read_mac_addr,
4138                                 sizeof(read_mac_addr))) {
4139                         printf("slave port (%d) mac address not set to that of new primary"
4140                                         "port\n", test_params->slave_port_ids[i]);
4141                         return -1;
4142                 }
4143         }
4144
4145         /* Set explicit MAC address */
4146         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
4147                         (struct ether_addr *)bonded_mac) != 0)
4148                 return -1;
4149
4150         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
4151         if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
4152                 printf("bonded port (%d) mac address not set to that of new primary port\n",
4153                                 test_params->slave_port_ids[i]);
4154                 return -1;
4155         }
4156
4157         for (i = 0; i < test_params->bonded_slave_count; i++) {
4158                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
4159                 if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
4160                         printf("slave port (%d) mac address not set to that of new primary port\n",
4161                                         test_params->slave_port_ids[i]);
4162                         return -1;
4163                 }
4164         }
4165
4166         /* Clean up and remove slaves from bonded device */
4167         return remove_slaves_and_stop_bonded_device();
4168 }
4169
4170 #define BROADCAST_LINK_STATUS_NUM_OF_SLAVES (4)
4171 static int
4172 test_broadcast_verify_slave_link_status_change_behaviour(void)
4173 {
4174         struct rte_mbuf *pkt_burst[BROADCAST_LINK_STATUS_NUM_OF_SLAVES][MAX_PKT_BURST];
4175         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
4176         struct rte_eth_stats port_stats;
4177
4178         uint8_t slaves[RTE_MAX_ETHPORTS];
4179
4180         int i, j, burst_size, slave_count;
4181
4182         memset(pkt_burst, 0, sizeof(pkt_burst));
4183
4184         /* Initialize bonded device with 4 slaves in round robin mode */
4185         if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0,
4186                         BROADCAST_LINK_STATUS_NUM_OF_SLAVES, 1) != 0)
4187                 return -1;
4188
4189         /* Verify Current Slaves Count /Active Slave Count is */
4190         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
4191                         RTE_MAX_ETHPORTS);
4192         if (slave_count != 4) {
4193                 printf("Number of slaves (%d) is not as expected (%d).\n",
4194                                 slave_count, 4);
4195                 return -1;
4196         }
4197
4198         slave_count = rte_eth_bond_active_slaves_get(
4199                         test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
4200         if (slave_count != 4) {
4201                 printf("Number of active slaves (%d) is not as expected (%d).\n",
4202                                 slave_count, 4);
4203                 return -1;
4204         }
4205
4206         /* Set 2 slaves link status to down */
4207         virtual_ethdev_simulate_link_status_interrupt(
4208                         test_params->slave_port_ids[1], 0);
4209         virtual_ethdev_simulate_link_status_interrupt(
4210                         test_params->slave_port_ids[3], 0);
4211
4212         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
4213                         slaves, RTE_MAX_ETHPORTS);
4214         if (slave_count != 2) {
4215                 printf("Number of active slaves (%d) is not as expected (%d).\n",
4216                                 slave_count, 2);
4217                 return -1;
4218         }
4219
4220         for (i = 0; i < test_params->bonded_slave_count; i++)
4221                 rte_eth_stats_reset(test_params->slave_port_ids[i]);
4222
4223         /* Verify that pkts are not sent on slaves with link status down */
4224         burst_size = 21;
4225
4226         if (generate_test_burst(&pkt_burst[0][0], burst_size, 0, 0, 1, 0, 0) !=
4227                         burst_size) {
4228                 printf("generate_test_burst failed\n");
4229                 return -1;
4230         }
4231
4232         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0],
4233                         burst_size) != burst_size) {
4234                 printf("rte_eth_tx_burst failed\n");
4235                 return -1;
4236         }
4237
4238         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
4239         if (port_stats.opackets != (uint64_t)(burst_size * slave_count)) {
4240                 printf("(%d) port_stats.opackets (%d) not as expected (%d)\n",
4241                                 test_params->bonded_port_id, (int)port_stats.opackets,
4242                                 burst_size * slave_count);
4243                 return -1;
4244         }
4245
4246         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
4247         if (port_stats.opackets != (uint64_t)burst_size) {
4248                 printf("(%d) port_stats.opackets not as expected\n",
4249                                 test_params->slave_port_ids[0]);
4250                 return -1;
4251         }
4252
4253         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
4254         if (port_stats.opackets != 0) {
4255                 printf("(%d) port_stats.opackets not as expected\n",
4256                                 test_params->slave_port_ids[1]);
4257                 return -1;
4258         }
4259
4260         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
4261         if (port_stats.opackets != (uint64_t)burst_size) {
4262                 printf("(%d) port_stats.opackets not as expected\n",
4263                                 test_params->slave_port_ids[2]);
4264                 return -1;
4265         }
4266
4267         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
4268         if (port_stats.opackets != 0) {
4269                 printf("(%d) port_stats.opackets not as expected\n",
4270                                 test_params->slave_port_ids[3]);
4271                 return -1;
4272         }
4273
4274         for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) {
4275                 if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 0, 1, 0, 0) !=
4276                                 burst_size) {
4277                         return -1;
4278                 }
4279
4280                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
4281                                 &pkt_burst[i][0], burst_size);
4282         }
4283
4284         /* Verify that pkts are not received on slaves with link status down */
4285
4286         if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
4287                         MAX_PKT_BURST) !=
4288                         burst_size + burst_size) {
4289                 printf("rte_eth_rx_burst\n");
4290                 return -1;
4291         }
4292
4293         /* Verify bonded device rx count */
4294         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
4295         if (port_stats.ipackets != (uint64_t)(burst_size + burst_size)) {
4296                 printf("(%d) port_stats.ipackets not as expected\n",
4297                                 test_params->bonded_port_id);
4298                 return -1;
4299         }
4300
4301         /* free mbufs allocate for rx testing */
4302         for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) {
4303                 for (j = 0; j < MAX_PKT_BURST; j++) {
4304                         if (pkt_burst[i][j] != NULL) {
4305                                 rte_pktmbuf_free(pkt_burst[i][j]);
4306                                 pkt_burst[i][j] = NULL;
4307                         }
4308                 }
4309         }
4310
4311         /* Clean up and remove slaves from bonded device */
4312         return remove_slaves_and_stop_bonded_device();
4313 }
4314 #endif
4315
4316 static int
4317 test_reconfigure_bonded_device(void)
4318 {
4319         test_params->nb_rx_q = 4;
4320         test_params->nb_tx_q = 4;
4321
4322         if (configure_ethdev(test_params->bonded_port_id, 0, 0)  != 0) {
4323                 printf("failed to reconfigure bonded device");
4324                 return -1;
4325         }
4326
4327
4328         test_params->nb_rx_q = 2;
4329         test_params->nb_tx_q = 2;
4330
4331         if (configure_ethdev(test_params->bonded_port_id, 0, 0)  != 0) {
4332                 printf("failed to reconfigure bonded device with less rx/tx queues");
4333                 return -1;
4334         }
4335
4336         return 0;
4337 }
4338
4339
4340 static int
4341 test_close_bonded_device(void)
4342 {
4343         rte_eth_dev_close(test_params->bonded_port_id);
4344         return 0;
4345 }
4346
4347 static int
4348 testsuite_teardown(void)
4349 {
4350         if (test_params->pkt_eth_hdr != NULL) {
4351                 free(test_params->pkt_eth_hdr);
4352                 test_params->pkt_eth_hdr = NULL;
4353         }
4354
4355         /* Clean up and remove slaves from bonded device */
4356         return remove_slaves_and_stop_bonded_device();
4357 }
4358
4359
4360 static struct unit_test_suite link_bonding_test_suite  = {
4361         .suite_name = "Link Bonding Unit Test Suite",
4362         .setup = test_setup,
4363         .teardown = testsuite_teardown,
4364         .unit_test_cases = {
4365                 TEST_CASE(test_create_bonded_device),
4366                 TEST_CASE(test_create_bonded_device_with_invalid_params),
4367                 TEST_CASE(test_add_slave_to_bonded_device),
4368                 TEST_CASE(test_add_slave_to_invalid_bonded_device),
4369                 TEST_CASE(test_remove_slave_from_bonded_device),
4370                 TEST_CASE(test_remove_slave_from_invalid_bonded_device),
4371                 TEST_CASE(test_get_slaves_from_bonded_device),
4372                 TEST_CASE(test_add_already_bonded_slave_to_bonded_device),
4373                 TEST_CASE(test_add_remove_multiple_slaves_to_from_bonded_device),
4374                 TEST_CASE(test_start_bonded_device),
4375                 TEST_CASE(test_stop_bonded_device),
4376                 TEST_CASE(test_set_bonding_mode),
4377                 TEST_CASE(test_set_primary_slave),
4378                 TEST_CASE(test_set_explicit_bonded_mac),
4379                 TEST_CASE(test_status_interrupt),
4380                 TEST_CASE(test_adding_slave_after_bonded_device_started),
4381                 TEST_CASE(test_roundrobin_tx_burst),
4382                 TEST_CASE(test_roundrobin_tx_burst_slave_tx_fail),
4383                 TEST_CASE(test_roundrobin_rx_burst_on_single_slave),
4384                 TEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves),
4385                 TEST_CASE(test_roundrobin_verify_promiscuous_enable_disable),
4386                 TEST_CASE(test_roundrobin_verify_mac_assignment),
4387                 TEST_CASE(test_roundrobin_verify_slave_link_status_change_behaviour),
4388                 TEST_CASE(test_roundrobin_verfiy_polling_slave_link_status_change),
4389                 TEST_CASE(test_activebackup_tx_burst),
4390                 TEST_CASE(test_activebackup_rx_burst),
4391                 TEST_CASE(test_activebackup_verify_promiscuous_enable_disable),
4392                 TEST_CASE(test_activebackup_verify_mac_assignment),
4393                 TEST_CASE(test_activebackup_verify_slave_link_status_change_failover),
4394                 TEST_CASE(test_balance_xmit_policy_configuration),
4395                 TEST_CASE(test_balance_l2_tx_burst),
4396                 TEST_CASE(test_balance_l23_tx_burst_ipv4_toggle_ip_addr),
4397                 TEST_CASE(test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr),
4398                 TEST_CASE(test_balance_l23_tx_burst_ipv6_toggle_ip_addr),
4399                 TEST_CASE(test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr),
4400                 TEST_CASE(test_balance_l23_tx_burst_toggle_mac_addr),
4401                 TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_ip_addr),
4402                 TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_udp_port),
4403                 TEST_CASE(test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr),
4404                 TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr),
4405                 TEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr),
4406                 TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port),
4407                 TEST_CASE(test_balance_tx_burst_slave_tx_fail),
4408                 TEST_CASE(test_balance_rx_burst),
4409                 TEST_CASE(test_balance_verify_promiscuous_enable_disable),
4410                 TEST_CASE(test_balance_verify_mac_assignment),
4411                 TEST_CASE(test_balance_verify_slave_link_status_change_behaviour),
4412 #ifdef RTE_MBUF_REFCNT
4413                 TEST_CASE(test_broadcast_tx_burst),
4414                 TEST_CASE(test_broadcast_tx_burst_slave_tx_fail),
4415                 TEST_CASE(test_broadcast_rx_burst),
4416                 TEST_CASE(test_broadcast_verify_promiscuous_enable_disable),
4417                 TEST_CASE(test_broadcast_verify_mac_assignment),
4418                 TEST_CASE(test_broadcast_verify_slave_link_status_change_behaviour),
4419 #endif
4420                 TEST_CASE(test_reconfigure_bonded_device),
4421                 TEST_CASE(test_close_bonded_device),
4422
4423                 { NULL, NULL, NULL, NULL, NULL } /**< NULL terminate unit test array */
4424         }
4425 };
4426
4427
4428 static int
4429 test_link_bonding(void)
4430 {
4431         return unit_test_suite_runner(&link_bonding_test_suite);
4432 }
4433
4434 static struct test_command link_bonding_cmd = {
4435         .command = "link_bonding_autotest",
4436         .callback = test_link_bonding,
4437 };
4438 REGISTER_TEST_COMMAND(link_bonding_cmd);