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