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