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