app/test: convert all tests to register system
[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                                                         BONDING_MODE_BROADCAST };
792
793         /* Test supported link bonding modes */
794         for (i = 0; i < (int)RTE_DIM(bonding_modes);    i++) {
795                 /* Invalid port ID */
796                 retval = rte_eth_bond_mode_set(INVALID_PORT_ID, bonding_modes[i]);
797                 if (retval == 0) {
798                         printf("Expected call to failed as invalid port (%d) specified.\n",
799                                         INVALID_PORT_ID);
800                         return -1;
801                 }
802
803                 /* Non bonded device */
804                 retval = rte_eth_bond_mode_set(test_params->slave_port_ids[0],
805                                 bonding_modes[i]);
806                 if (retval == 0) {
807                         printf("Expected call to failed as invalid port (%d) specified.\n",
808                                         test_params->slave_port_ids[0]);
809                         return -1;
810                 }
811
812                 retval = rte_eth_bond_mode_set(test_params->bonded_port_id,
813                                 bonding_modes[i]);
814                 if (retval != 0) {
815                         printf("Failed to set link bonding mode on port (%d) to (%d).\n",
816                                         test_params->bonded_port_id, bonding_modes[i]);
817                         return -1;
818                 }
819
820                 bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
821                 if (bonding_mode != bonding_modes[i]) {
822                         printf("Link bonding mode (%d) of port (%d) is not expected value (%d).\n",
823                                         bonding_mode, test_params->bonded_port_id,
824                                         bonding_modes[i]);
825                         return -1;
826                 }
827
828
829                 /* Invalid port ID */
830                 bonding_mode = rte_eth_bond_mode_get(INVALID_PORT_ID);
831                 if (bonding_mode >= 0) {
832                         printf("Expected call to failed as invalid port (%d) specified.\n",
833                                         INVALID_PORT_ID);
834                         return -1;
835                 }
836
837
838                 /* Non bonded device */
839                 bonding_mode = rte_eth_bond_mode_get(test_params->slave_port_ids[0]);
840                 if (bonding_mode >= 0) {
841                         printf("Expected call to failed as invalid port (%d) specified.\n",
842                                         test_params->slave_port_ids[0]);
843                         return -1;
844                 }
845
846         }
847
848         return remove_slaves_and_stop_bonded_device();
849 }
850
851 static int
852 test_set_primary_slave(void)
853 {
854         int i, j, retval;
855         struct ether_addr read_mac_addr;
856         struct ether_addr *expected_mac_addr;
857
858         /* Add 4 slaves to bonded device */
859         for (i = test_params->bonded_slave_count; i < 4; i++) {
860                 retval = test_add_slave_to_bonded_device();
861                 if (retval != 0) {
862                         printf("Failed to add slave to bonded device.\n");
863                         return -1;
864                 }
865         }
866         retval = rte_eth_bond_mode_set(test_params->bonded_port_id,
867                         BONDING_MODE_ROUND_ROBIN);
868         if (retval != 0) {
869                 printf("Failed to set link bonding mode on port (%d) to (%d).\n",
870                                 test_params->bonded_port_id, BONDING_MODE_ROUND_ROBIN);
871                 return -1;
872         }
873
874         /* Invalid port ID */
875         retval = rte_eth_bond_primary_set(INVALID_PORT_ID,
876                         test_params->slave_port_ids[i]);
877         if (retval == 0) {
878                 printf("Expected call to failed as invalid port specified.\n");
879                 return -1;
880         }
881
882         /* Set slave as primary
883          * Verify slave it is now primary slave
884          * Verify that MAC address of bonded device is that of primary slave
885          * Verify that MAC address of all bonded slaves are that of primary slave
886          */
887         for (i = 0; i < 4; i++) {
888
889                 /* Non bonded device */
890                 retval = rte_eth_bond_primary_set(test_params->slave_port_ids[i],
891                                 test_params->slave_port_ids[i]);
892                 if (retval == 0) {
893                         printf("Expected call to failed as invalid port specified.\n");
894                         return -1;
895                 }
896
897                 retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
898                                 test_params->slave_port_ids[i]);
899                 if (retval != 0) {
900                         printf("Failed to set bonded port (%d) primary port to (%d)\n",
901                                         test_params->bonded_port_id,
902                                         test_params->slave_port_ids[i]);
903                         return -1;
904                 }
905
906                 retval = rte_eth_bond_primary_get(test_params->bonded_port_id);
907                 if (retval < 0) {
908                         printf("Failed to read primary port from bonded port (%d)\n",
909                                         test_params->bonded_port_id);
910                         return -1;
911                 } else if (retval != test_params->slave_port_ids[i]) {
912                         printf("Bonded port (%d) primary port (%d) not expected value (%d)\n",
913                                         test_params->bonded_port_id, retval,
914                                         test_params->slave_port_ids[i]);
915                         return -1;
916                 }
917
918                 /* stop/start bonded eth dev to apply new MAC */
919                 rte_eth_dev_stop(test_params->bonded_port_id);
920                 if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
921                         return -1;
922
923                 expected_mac_addr = (struct ether_addr *)&slave_mac;
924                 expected_mac_addr->addr_bytes[ETHER_ADDR_LEN-1] =
925                                 test_params->slave_port_ids[i];
926
927                 /* Check primary slave MAC */
928                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
929                 if (memcmp(expected_mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
930                         printf("bonded port mac address not set to that of primary port\n");
931                         return -1;
932                 }
933
934                 /* Check bonded MAC */
935                 rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
936                 if (memcmp(&read_mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
937                         printf("bonded port mac address not set to that of primary port\n");
938                         return -1;
939                 }
940
941                 /* Check other slaves MACs */
942                 for (j = 0; j < 4; j++) {
943                         if (j != i) {
944                                 rte_eth_macaddr_get(test_params->slave_port_ids[j],
945                                                 &read_mac_addr);
946                                 if (memcmp(expected_mac_addr, &read_mac_addr,
947                                                 sizeof(read_mac_addr))) {
948                                         printf("slave port mac address not set to that of primary port\n");
949                                         return -1;
950                                 }
951                         }
952                 }
953         }
954
955
956         /* Test with none existent port */
957         retval = rte_eth_bond_primary_get(test_params->bonded_port_id + 10);
958         if (retval >= 0) {
959                 printf("read primary port from expectedly\n");
960                 return -1;
961         }
962
963         /* Test with slave port */
964         retval = rte_eth_bond_primary_get(test_params->slave_port_ids[0]);
965         if (retval >= 0) {
966                 printf("read primary port from expectedly\n");
967                 return -1;
968         }
969
970         if (remove_slaves_and_stop_bonded_device() != 0)
971                 return -1;
972
973         /* No slaves  */
974         retval = rte_eth_bond_primary_get(test_params->bonded_port_id);
975         if (retval >= 0) {
976                 printf("read primary port from expectedly\n");
977                 return -1;
978         }
979
980         return 0;
981 }
982
983 static int
984 test_set_explicit_bonded_mac(void)
985 {
986         int i, retval;
987         struct ether_addr read_mac_addr;
988         struct ether_addr *mac_addr;
989
990         uint8_t explicit_bonded_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01 };
991
992         mac_addr = (struct ether_addr *)explicit_bonded_mac;
993
994         /* Invalid port ID */
995         retval = rte_eth_bond_mac_address_set(INVALID_PORT_ID, mac_addr);
996         if (retval == 0) {
997                 printf("Expected call to failed as invalid port specified.\n");
998                 return -1;
999         }
1000
1001         /* Non bonded device */
1002         retval = rte_eth_bond_mac_address_set(test_params->slave_port_ids[0],
1003                         mac_addr);
1004         if (retval == 0) {
1005                 printf("Expected call to failed as invalid port specified.\n");
1006                 return -1;
1007         }
1008
1009         /* NULL MAC address */
1010         retval = rte_eth_bond_mac_address_set(test_params->bonded_port_id, NULL);
1011         if (retval == 0) {
1012                 printf("Expected call to failed as NULL MAC specified\n");
1013                 return -1;
1014         }
1015
1016         retval = rte_eth_bond_mac_address_set(test_params->bonded_port_id,
1017                         mac_addr);
1018         if (retval != 0) {
1019                 printf("Failed to set MAC address on bonded port (%d)\n",
1020                                 test_params->bonded_port_id);
1021                 return -1;
1022         }
1023
1024         /* Add 4 slaves to bonded device */
1025         for (i = test_params->bonded_slave_count; i < 4; i++) {
1026                 retval = test_add_slave_to_bonded_device();
1027                 if (retval != 0) {
1028                         printf("Failed to add slave to bonded device.\n");
1029                         return -1;
1030                 }
1031         }
1032
1033         /* Check bonded MAC */
1034         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
1035         if (memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
1036                 printf("bonded port mac address not set to that of primary port\n");
1037                 return -1;
1038         }
1039
1040         /* Check other slaves MACs */
1041         for (i = 0; i < 4; i++) {
1042                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1043                 if (memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr))) {
1044                         printf("slave port mac address not set to that of primary port\n");
1045                         return -1;
1046                 }
1047         }
1048
1049         /* test resetting mac address on bonded device */
1050         if (rte_eth_bond_mac_address_reset(test_params->bonded_port_id) != 0) {
1051                 printf("Failed to reset MAC address on bonded port (%d)\n",
1052                                 test_params->bonded_port_id);
1053
1054                 return -1;
1055         }
1056
1057         if (rte_eth_bond_mac_address_reset(test_params->slave_port_ids[0]) == 0) {
1058                 printf("Reset MAC address on bonded port (%d) unexpectedly\n",
1059                                 test_params->slave_port_ids[1]);
1060
1061                 return -1;
1062         }
1063
1064         /* test resetting mac address on bonded device with no slaves */
1065
1066         if (remove_slaves_and_stop_bonded_device() != 0)
1067                 return -1;
1068
1069         if (rte_eth_bond_mac_address_reset(test_params->bonded_port_id) != 0) {
1070                 printf("Failed to reset MAC address on bonded port (%d)\n",
1071                                 test_params->bonded_port_id);
1072
1073                 return -1;
1074         }
1075
1076         return 0;
1077 }
1078
1079
1080 static int
1081 initialize_bonded_device_with_slaves(uint8_t bonding_mode,
1082                 uint8_t number_of_slaves, uint8_t enable_slave)
1083 {
1084         /* configure bonded device */
1085         TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0),
1086                         "Failed to configure bonding port (%d) in mode %d "
1087                         "with (%d) slaves.", test_params->bonded_port_id, bonding_mode,
1088                         number_of_slaves);
1089
1090         while (number_of_slaves > test_params->bonded_slave_count) {
1091                 /* Add slaves to bonded device */
1092                 TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
1093                                 "Failed to add slave (%d to  bonding port (%d).",
1094                                 test_params->bonded_slave_count - 1,
1095                                 test_params->bonded_port_id);
1096         }
1097
1098         /* Set link bonding mode  */
1099         TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
1100                         bonding_mode),
1101                         "Failed to set link bonding mode on port (%d) to (%d).",
1102                         test_params->bonded_port_id, bonding_mode);
1103
1104         TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
1105                 "Failed to start bonded pmd eth device %d.",
1106                 test_params->bonded_port_id);
1107
1108         if (enable_slave)
1109                 enable_bonded_slaves();
1110
1111         return 0;
1112 }
1113
1114 static int
1115 test_adding_slave_after_bonded_device_started(void)
1116 {
1117         int i;
1118
1119         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 0) !=
1120                         0)
1121                 return -1;
1122
1123         /* Enabled slave devices */
1124         for (i = 0; i < test_params->bonded_slave_count + 1; i++) {
1125                 virtual_ethdev_simulate_link_status_interrupt(
1126                                 test_params->slave_port_ids[i], 1);
1127         }
1128
1129         if (rte_eth_bond_slave_add(test_params->bonded_port_id,
1130                         test_params->slave_port_ids[test_params->bonded_slave_count]) !=
1131                                         0) {
1132                 printf("\t Failed to add slave to bonded port.\n");
1133                 return -1;
1134         }
1135
1136         rte_eth_stats_reset(
1137                         test_params->slave_port_ids[test_params->bonded_slave_count]);
1138
1139         test_params->bonded_slave_count++;
1140
1141         return remove_slaves_and_stop_bonded_device();
1142 }
1143
1144 static int
1145 generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size,
1146                 uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac,
1147                 uint8_t toggle_ip_addr, uint8_t toggle_udp_port)
1148 {
1149         uint16_t pktlen, generated_burst_size;
1150         void *ip_hdr;
1151
1152         if (toggle_dst_mac)
1153                 initialize_eth_header(test_params->pkt_eth_hdr,
1154                                 (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1,
1155                                 vlan, vlan_id);
1156         else
1157                 initialize_eth_header(test_params->pkt_eth_hdr,
1158                                 (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0,
1159                                 vlan, vlan_id);
1160
1161
1162         if (toggle_udp_port)
1163                 pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
1164                                 dst_port_1, 64);
1165         else
1166                 pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
1167                                 dst_port_0, 64);
1168
1169         if (ipv4) {
1170                 if (toggle_ip_addr)
1171                         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
1172                                         dst_addr_1, pktlen);
1173                 else
1174                         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
1175                                         dst_addr_0, pktlen);
1176
1177                 ip_hdr = test_params->pkt_ipv4_hdr;
1178         } else {
1179                 if (toggle_ip_addr)
1180                         pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
1181                                         (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_1,
1182                                         pktlen);
1183                 else
1184                         pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
1185                                         (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_0,
1186                                         pktlen);
1187
1188                 ip_hdr = test_params->pkt_ipv6_hdr;
1189         }
1190
1191         /* Generate burst of packets to transmit */
1192         generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
1193                         pkts_burst,     test_params->pkt_eth_hdr, vlan, ip_hdr, ipv4,
1194                         test_params->pkt_udp_hdr, burst_size);
1195         if (generated_burst_size != burst_size) {
1196                 printf("Failed to generate packet burst");
1197                 return -1;
1198         }
1199
1200         return generated_burst_size;
1201 }
1202
1203 /** Round Robin Mode Tests */
1204
1205 static int
1206 test_roundrobin_tx_burst(void)
1207 {
1208         int i, burst_size, nb_tx;
1209         struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
1210         struct rte_eth_stats port_stats;
1211
1212         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 2, 1)
1213                         != 0)
1214                 return -1;
1215
1216         burst_size = 20 * test_params->bonded_slave_count;
1217
1218         if (burst_size > MAX_PKT_BURST) {
1219                 printf("Burst size specified is greater than supported.\n");
1220                 return -1;
1221         }
1222
1223         /* Generate test bursts of packets to transmit */
1224         if (generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0) != burst_size)
1225                 return -1;
1226
1227         /* Send burst on bonded port */
1228         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
1229                         burst_size);
1230         if (nb_tx != burst_size)
1231                 return -1;
1232
1233         /* Verify bonded port tx stats */
1234         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1235         if (port_stats.opackets != (uint64_t)burst_size) {
1236                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
1237                                 test_params->bonded_port_id, (unsigned int)port_stats.opackets,
1238                                 burst_size);
1239                 return -1;
1240         }
1241
1242         /* Verify slave ports tx stats */
1243         for (i = 0; i < test_params->bonded_slave_count; i++) {
1244                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
1245                 if (port_stats.opackets !=
1246                                 (uint64_t)burst_size / test_params->bonded_slave_count) {
1247                         printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
1248                                         test_params->bonded_port_id,
1249                                         (unsigned int)port_stats.opackets,
1250                                         burst_size / test_params->bonded_slave_count);
1251                         return -1;
1252                 }
1253         }
1254
1255         /* Put all slaves down and try and transmit */
1256         for (i = 0; i < test_params->bonded_slave_count; i++) {
1257                 virtual_ethdev_simulate_link_status_interrupt(
1258                                 test_params->slave_port_ids[i], 0);
1259         }
1260
1261         /* Send burst on bonded port */
1262         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
1263                         burst_size);
1264         if (nb_tx != 0)
1265                 return -1;
1266
1267         /* Clean up and remove slaves from bonded device */
1268         return remove_slaves_and_stop_bonded_device();
1269 }
1270
1271 static int
1272 test_roundrobin_rx_burst_on_single_slave(void)
1273 {
1274         struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
1275         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1276
1277         struct rte_eth_stats port_stats;
1278
1279         int i, j, nb_rx, burst_size = 25;
1280
1281         /* Initialize bonded device with 4 slaves in round robin mode */
1282         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1) !=
1283                         0)
1284                 return -1;
1285
1286         /* Generate test bursts of packets to transmit */
1287         if (generate_test_burst(gen_pkt_burst, burst_size, 0, 1, 0, 0, 0) !=
1288                         burst_size)
1289                 return -1;
1290
1291         for (i = 0; i < test_params->bonded_slave_count; i++) {
1292                 /* Add rx data to slave */
1293                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1294                                 &gen_pkt_burst[0], burst_size);
1295
1296                 /* Call rx burst on bonded device */
1297                 /* Send burst on bonded port */
1298                 nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
1299                                 MAX_PKT_BURST);
1300                 if (nb_rx != burst_size) {
1301                         printf("round-robin rx burst failed");
1302                         return -1;
1303                 }
1304
1305                 /* Verify bonded device rx count */
1306                 rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1307                 if (port_stats.ipackets != (uint64_t)burst_size) {
1308                         printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
1309                                         test_params->bonded_port_id,
1310                                         (unsigned int)port_stats.ipackets, burst_size);
1311                         return -1;
1312                 }
1313
1314
1315                 /* Verify bonded slave devices rx count */
1316                 /* Verify slave ports tx stats */
1317                 for (j = 0; j < test_params->bonded_slave_count; j++) {
1318                         rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
1319
1320                         if (i == j) {
1321                                 if (port_stats.ipackets != (uint64_t)burst_size) {
1322                                         printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1323                                                         test_params->slave_port_ids[i],
1324                                                         (unsigned int)port_stats.ipackets, burst_size);
1325                                         return -1;
1326                                 }
1327                         } else {
1328                                 if (port_stats.ipackets != 0) {
1329                                         printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1330                                                         test_params->slave_port_ids[i],
1331                                                         (unsigned int)port_stats.ipackets, 0);
1332                                         return -1;
1333                                 }
1334                         }
1335
1336                         /* Reset bonded slaves stats */
1337                         rte_eth_stats_reset(test_params->slave_port_ids[j]);
1338                 }
1339                 /* reset bonded device stats */
1340                 rte_eth_stats_reset(test_params->bonded_port_id);
1341         }
1342
1343         /* free mbufs */
1344         for (i = 0; i < MAX_PKT_BURST; i++) {
1345                 if (gen_pkt_burst[i] != NULL)
1346                         rte_pktmbuf_free(gen_pkt_burst[i]);
1347
1348                 if (rx_pkt_burst[i] != NULL)
1349                         rte_pktmbuf_free(rx_pkt_burst[i]);
1350         }
1351
1352
1353         /* Clean up and remove slaves from bonded device */
1354         return remove_slaves_and_stop_bonded_device();
1355 }
1356
1357 #define TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT (3)
1358
1359 static int
1360 test_roundrobin_rx_burst_on_multiple_slaves(void)
1361 {
1362         struct rte_mbuf *gen_pkt_burst[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
1363
1364         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1365         struct rte_eth_stats port_stats;
1366
1367         int burst_size[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT] = { 15, 13, 36 };
1368         int i, nb_rx;
1369
1370
1371         /* Initialize bonded device with 4 slaves in round robin mode */
1372         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1) !=
1373                         0)
1374                 return -1;
1375
1376         /* Generate test bursts of packets to transmit */
1377         for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
1378                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size[i], 0, 1, 0, 0,
1379                                 0) != burst_size[i])
1380                         return -1;
1381         }
1382
1383         /* Add rx data to slaves */
1384         for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
1385                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1386                                 &gen_pkt_burst[i][0], burst_size[i]);
1387         }
1388
1389         /* Call rx burst on bonded device */
1390         /* Send burst on bonded port */
1391         nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
1392                         MAX_PKT_BURST);
1393         if (nb_rx != burst_size[0] + burst_size[1] + burst_size[2]) {
1394                 printf("round-robin rx burst failed (%d != %d)\n", nb_rx,
1395                                 burst_size[0] + burst_size[1] + burst_size[2]);
1396                 return -1;
1397         }
1398
1399         /* Verify bonded device rx count */
1400         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1401         if (port_stats.ipackets != (uint64_t)(burst_size[0] + burst_size[1] +
1402                         burst_size[2])) {
1403                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
1404                                 test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
1405                                 burst_size[0] + burst_size[1] + burst_size[2]);
1406                 return -1;
1407         }
1408
1409
1410         /* Verify bonded slave devices rx counts */
1411         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
1412         if (port_stats.ipackets != (uint64_t)burst_size[0]) {
1413                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1414                                 test_params->slave_port_ids[0],
1415                                 (unsigned int)port_stats.ipackets, burst_size[0]);
1416                 return -1;
1417         }
1418
1419         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
1420         if (port_stats.ipackets != (uint64_t)burst_size[1]) {
1421                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1422                                 test_params->slave_port_ids[1],
1423                                 (unsigned int)port_stats.ipackets, burst_size[1]);
1424                 return -1;
1425         }
1426
1427         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
1428         if (port_stats.ipackets != (uint64_t)burst_size[2]) {
1429                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1430                                 test_params->slave_port_ids[2],
1431                                 (unsigned int)port_stats.ipackets, burst_size[2]);
1432                 return -1;
1433         }
1434
1435         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
1436         if (port_stats.ipackets != 0) {
1437                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1438                                 test_params->slave_port_ids[3],
1439                                 (unsigned int)port_stats.ipackets, 0);
1440                 return -1;
1441         }
1442
1443         /* free mbufs */
1444         for (i = 0; i < MAX_PKT_BURST; i++) {
1445                 if (rx_pkt_burst[i] != NULL)
1446                         rte_pktmbuf_free(rx_pkt_burst[i]);
1447         }
1448
1449         /* Clean up and remove slaves from bonded device */
1450         return remove_slaves_and_stop_bonded_device();
1451 }
1452
1453 static int
1454 test_roundrobin_verify_mac_assignment(void)
1455 {
1456         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_2;
1457
1458         int i, retval;
1459
1460         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
1461         rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_2);
1462
1463         /* Initialize bonded device with 4 slaves in round robin mode */
1464         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1)
1465                         != 0)
1466                 return -1;
1467
1468         /* Verify that all MACs are the same as first slave added to bonded dev */
1469         for (i = 0; i < test_params->bonded_slave_count; i++) {
1470                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1471                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
1472                                 sizeof(read_mac_addr))) {
1473                         printf("slave port (%d) mac address not set to that of primary port\n",
1474                                         test_params->slave_port_ids[i]);
1475                         return -1;
1476                 }
1477         }
1478
1479         /* change primary and verify that MAC addresses haven't changed */
1480         retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
1481                         test_params->slave_port_ids[2]);
1482         if (retval != 0) {
1483                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
1484                                 test_params->bonded_port_id, test_params->slave_port_ids[i]);
1485                 return -1;
1486         }
1487
1488         for (i = 0; i < test_params->bonded_slave_count; i++) {
1489                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1490                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
1491                                 sizeof(read_mac_addr))) {
1492                         printf("slave port (%d) mac address has changed to that of primary port without stop/start toggle of bonded device\n",
1493                                         test_params->slave_port_ids[i]);
1494                         return -1;
1495                 }
1496         }
1497
1498         /* stop / start bonded device and verify that primary MAC address is
1499          * propagate to bonded device and slaves */
1500
1501         rte_eth_dev_stop(test_params->bonded_port_id);
1502
1503         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
1504                 return -1;
1505
1506         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
1507         if (memcmp(&expected_mac_addr_2, &read_mac_addr, sizeof(read_mac_addr))) {
1508                 printf("bonded port (%d) mac address not set to that of new primary port\n",
1509                                 test_params->slave_port_ids[i]);
1510                 return -1;
1511         }
1512
1513         for (i = 0; i < test_params->bonded_slave_count; i++) {
1514                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1515                 if (memcmp(&expected_mac_addr_2, &read_mac_addr,
1516                                 sizeof(read_mac_addr))) {
1517                         printf("slave port (%d) mac address not set to that of new primary port\n",
1518                                         test_params->slave_port_ids[i]);
1519                         return -1;
1520                 }
1521         }
1522
1523         /* Set explicit MAC address */
1524         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
1525                         (struct ether_addr *)bonded_mac) != 0) {
1526                 return -1;
1527         }
1528
1529         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
1530         if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
1531                 printf("bonded port (%d) mac address not set to that of new primary port\n",
1532                                 test_params->slave_port_ids[i]);
1533                 return -1;
1534         }
1535
1536         for (i = 0; i < test_params->bonded_slave_count; i++) {
1537                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
1538                 if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
1539                         printf("slave port (%d) mac address not set to that of new primary port\n",
1540                                         test_params->slave_port_ids[i]);
1541                         return -1;
1542                 }
1543         }
1544
1545         /* Clean up and remove slaves from bonded device */
1546         return remove_slaves_and_stop_bonded_device();
1547 }
1548
1549 static int
1550 test_roundrobin_verify_promiscuous_enable_disable(void)
1551 {
1552         int i, promiscuous_en;
1553
1554         /* Initialize bonded device with 4 slaves in round robin mode */
1555         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1) !=
1556                         0)
1557                 return -1;
1558
1559         rte_eth_promiscuous_enable(test_params->bonded_port_id);
1560
1561         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
1562         if (promiscuous_en != 1) {
1563                 printf("Port (%d) promiscuous mode not enabled\n",
1564                                 test_params->bonded_port_id);
1565                 return -1;
1566         }
1567
1568         for (i = 0; i < test_params->bonded_slave_count; i++) {
1569                 promiscuous_en = rte_eth_promiscuous_get(test_params->slave_port_ids[i]);
1570                 if (promiscuous_en != 1) {
1571                         printf("slave port (%d) promiscuous mode not enabled\n",
1572                                         test_params->slave_port_ids[i]);
1573                         return -1;
1574                 }
1575         }
1576
1577         rte_eth_promiscuous_disable(test_params->bonded_port_id);
1578
1579         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
1580         if (promiscuous_en != 0) {
1581                 printf("Port (%d) promiscuous mode not disabled\n",
1582                                 test_params->bonded_port_id);
1583                 return -1;
1584         }
1585
1586         for (i = 0; i < test_params->bonded_slave_count; i++) {
1587                 promiscuous_en = rte_eth_promiscuous_get(test_params->slave_port_ids[i]);
1588                 if (promiscuous_en != 0) {
1589                         printf("slave port (%d) promiscuous mode not disabled\n",
1590                                         test_params->slave_port_ids[i]);
1591                         return -1;
1592                 }
1593         }
1594
1595         /* Clean up and remove slaves from bonded device */
1596         return remove_slaves_and_stop_bonded_device();
1597 }
1598
1599 #define TEST_RR_LINK_STATUS_SLAVE_COUNT (4)
1600 #define TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT (2)
1601
1602 static int
1603 test_roundrobin_verify_slave_link_status_change_behaviour(void)
1604 {
1605         struct rte_mbuf *tx_pkt_burst[MAX_PKT_BURST] = { NULL };
1606         struct rte_mbuf *gen_pkt_burst[TEST_RR_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST];
1607         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1608
1609         struct rte_eth_stats port_stats;
1610         uint8_t slaves[RTE_MAX_ETHPORTS];
1611
1612         int i, burst_size, slave_count;
1613
1614         /* NULL all pointers in array to simplify cleanup */
1615         memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
1616
1617         /* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves
1618          * in round robin mode */
1619         if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN,
1620                         TEST_RR_LINK_STATUS_SLAVE_COUNT, 1) != 0)
1621                 return -1;
1622
1623         /* Verify Current Slaves Count /Active Slave Count is */
1624         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
1625                         RTE_MAX_ETHPORTS);
1626         if (slave_count != TEST_RR_LINK_STATUS_SLAVE_COUNT) {
1627                 printf("Number of slaves (%d) is not as expected (%d).\n", slave_count,
1628                                 TEST_RR_LINK_STATUS_SLAVE_COUNT);
1629                 return -1;
1630         }
1631
1632         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
1633                         slaves, RTE_MAX_ETHPORTS);
1634         if (slave_count != TEST_RR_LINK_STATUS_SLAVE_COUNT) {
1635                 printf("Number of active slaves (%d) is not as expected (%d).\n",
1636                                 slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT);
1637                 return -1;
1638         }
1639
1640         /* Set 2 slaves eth_devs link status to down */
1641         virtual_ethdev_simulate_link_status_interrupt(
1642                         test_params->slave_port_ids[1], 0);
1643         virtual_ethdev_simulate_link_status_interrupt(
1644                         test_params->slave_port_ids[3], 0);
1645
1646         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
1647                         slaves, RTE_MAX_ETHPORTS) !=
1648                                         TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) {
1649                 printf("Number of active slaves (%d) is not as expected (%d).\n",
1650                                 slave_count, TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT);
1651                 return -1;
1652         }
1653
1654         burst_size = 20;
1655
1656         /* Verify that pkts are not sent on slaves with link status down:
1657          *
1658          * 1. Generate test burst of traffic
1659          * 2. Transmit burst on bonded eth_dev
1660          * 3. Verify stats for bonded eth_dev (opackets = burst_size)
1661          * 4. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
1662          */
1663         if (generate_test_burst(tx_pkt_burst, burst_size, 0, 1, 0, 0, 0) !=
1664                         burst_size) {
1665                 printf("generate_test_burst failed\n");
1666                 return -1;
1667         }
1668
1669         rte_eth_stats_reset(test_params->bonded_port_id);
1670
1671         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, tx_pkt_burst,
1672                         burst_size) != burst_size) {
1673                 printf("rte_eth_tx_burst failed\n");
1674                 return -1;
1675         }
1676
1677         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1678         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
1679                         "Port (%d) opackets stats (%d) not expected (%d) value",
1680                         test_params->bonded_port_id, (int)port_stats.opackets,
1681                         burst_size);
1682
1683         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
1684         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
1685                         "Port (%d) opackets stats (%d) not expected (%d) value",
1686                         test_params->slave_port_ids[0], (int)port_stats.opackets, 10);
1687
1688         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
1689         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
1690                         "Port (%d) opackets stats (%d) not expected (%d) value",
1691                         test_params->slave_port_ids[1], (int)port_stats.opackets, 0);
1692
1693         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
1694         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
1695                         "Port (%d) opackets stats (%d) not expected (%d) value",
1696                         test_params->slave_port_ids[2], (int)port_stats.opackets, 10);
1697
1698         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
1699         TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
1700                         "Port (%d) opackets stats (%d) not expected (%d) value",
1701                         test_params->slave_port_ids[3], (int)port_stats.opackets, 0);
1702
1703         /* Verify that pkts are not sent on slaves with link status down:
1704          *
1705          * 1. Generate test bursts of traffic
1706          * 2. Add bursts on to virtual eth_devs
1707          * 3. Rx burst on bonded eth_dev, expected (burst_ size *
1708          *    TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) received
1709          * 4. Verify stats for bonded eth_dev
1710          * 6. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
1711          */
1712         for (i = 0; i < TEST_RR_LINK_STATUS_SLAVE_COUNT; i++) {
1713                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0)
1714                                 != burst_size) {
1715                         return -1;
1716                 }
1717                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1718                                 &gen_pkt_burst[i][0], burst_size);
1719         }
1720
1721         if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
1722                         MAX_PKT_BURST) != burst_size + burst_size) {
1723                 printf("rte_eth_rx_burst\n");
1724                 return -1;
1725         }
1726
1727         /* Verify bonded device rx count */
1728         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1729         if (port_stats.ipackets != (uint64_t)(burst_size + burst_size)) {
1730                 printf("(%d) port_stats.ipackets not as expected\n",
1731                                 test_params->bonded_port_id);
1732                 return -1;
1733         }
1734
1735         /* free mbufs */
1736         for (i = 0; i < MAX_PKT_BURST; i++) {
1737                 if (rx_pkt_burst[i] != NULL)
1738                         rte_pktmbuf_free(rx_pkt_burst[i]);
1739
1740                 if (gen_pkt_burst[1][i] != NULL)
1741                         rte_pktmbuf_free(gen_pkt_burst[1][i]);
1742
1743                 if (gen_pkt_burst[3][i] != NULL)
1744                         rte_pktmbuf_free(gen_pkt_burst[1][i]);
1745         }
1746
1747         /* Clean up and remove slaves from bonded device */
1748         return remove_slaves_and_stop_bonded_device();
1749 }
1750
1751 /** Active Backup Mode Tests */
1752
1753 static int
1754 test_activebackup_tx_burst(void)
1755 {
1756         int i, retval, pktlen, primary_port, burst_size, generated_burst_size, nb_tx;
1757         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1758         struct rte_eth_stats port_stats;
1759
1760         retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 2, 1);
1761         if (retval != 0) {
1762                 printf("Failed to initialize_bonded_device_with_slaves.\n");
1763                 return -1;
1764         }
1765
1766         initialize_eth_header(test_params->pkt_eth_hdr,
1767                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0);
1768         pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
1769                         dst_port_0, 16);
1770         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
1771                         dst_addr_0, pktlen);
1772
1773         burst_size = 20 * test_params->bonded_slave_count;
1774
1775         if (burst_size > MAX_PKT_BURST) {
1776                 printf("Burst size specified is greater than supported.\n");
1777                 return -1;
1778         }
1779
1780         /* Generate a burst of packets to transmit */
1781         generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
1782                         pkts_burst,     test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
1783                         1, test_params->pkt_udp_hdr, burst_size);
1784         if (generated_burst_size != burst_size)
1785                 return -1;
1786
1787         /* Send burst on bonded port */
1788         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
1789                         burst_size);
1790         if (nb_tx != burst_size)
1791                 return -1;
1792
1793         /* Verify bonded port tx stats */
1794         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1795         if (port_stats.opackets != (uint64_t)burst_size) {
1796                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
1797                                 test_params->bonded_port_id, (unsigned int)port_stats.opackets,
1798                                 burst_size);
1799                 return -1;
1800         }
1801
1802         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
1803
1804         /* Verify slave ports tx stats */
1805         for (i = 0; i < test_params->bonded_slave_count; i++) {
1806                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
1807                 if (test_params->slave_port_ids[i] == primary_port) {
1808                         if (port_stats.opackets != (uint64_t)burst_size) {
1809                                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
1810                                                 test_params->bonded_port_id,
1811                                                 (unsigned int)port_stats.opackets,
1812                                                 burst_size / test_params->bonded_slave_count);
1813                                 return -1;
1814                         }
1815                 } else {
1816                         if (port_stats.opackets != 0) {
1817                                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
1818                                                 test_params->bonded_port_id,
1819                                                 (unsigned int)port_stats.opackets, 0);
1820                                 return -1;
1821                         }
1822                 }
1823         }
1824
1825         /* Put all slaves down and try and transmit */
1826         for (i = 0; i < test_params->bonded_slave_count; i++) {
1827
1828                 virtual_ethdev_simulate_link_status_interrupt(
1829                                 test_params->slave_port_ids[i], 0);
1830         }
1831
1832         /* Send burst on bonded port */
1833         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
1834                         burst_size);
1835         if (nb_tx != 0)
1836                 return -1;
1837
1838         /* Clean up and remove slaves from bonded device */
1839         return remove_slaves_and_stop_bonded_device();
1840 }
1841
1842 #define TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT (4)
1843
1844 static int
1845 test_activebackup_rx_burst(void)
1846 {
1847         struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
1848         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
1849
1850         struct rte_eth_stats port_stats;
1851
1852         int primary_port;
1853
1854         int i, j, nb_rx, burst_size = 17;
1855
1856         /* Initialize bonded device with 4 slaves in round robin mode */
1857         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
1858                         TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
1859                         != 0)
1860                 return -1;
1861
1862
1863         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
1864         if (primary_port < 0) {
1865                 printf("failed to get primary slave for bonded port (%d)",
1866                                 test_params->bonded_port_id);
1867         }
1868
1869         for (i = 0; i < test_params->bonded_slave_count; i++) {
1870                 /* Generate test bursts of packets to transmit */
1871                 if (generate_test_burst(&gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0)
1872                                 != burst_size) {
1873                         return -1;
1874                 }
1875
1876                 /* Add rx data to slave */
1877                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
1878                                 &gen_pkt_burst[0], burst_size);
1879
1880                 /* Call rx burst on bonded device */
1881                 nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0,
1882                                 &rx_pkt_burst[0], MAX_PKT_BURST);
1883                 if (nb_rx < 0) {
1884                         printf("rte_eth_rx_burst failed\n");
1885                         return -1;
1886                 }
1887
1888                 if (test_params->slave_port_ids[i] == primary_port) {
1889                         /* Verify bonded device rx count */
1890                         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
1891                         if (port_stats.ipackets != (uint64_t)burst_size) {
1892                                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
1893                                                 test_params->bonded_port_id,
1894                                                 (unsigned int)port_stats.ipackets, burst_size);
1895                                 return -1;
1896                         }
1897
1898                         /* Verify bonded slave devices rx count */
1899                         for (j = 0; j < test_params->bonded_slave_count; j++) {
1900                                 rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
1901                                 if (i == j) {
1902                                         if (port_stats.ipackets != (uint64_t)burst_size) {
1903                                                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1904                                                                 test_params->slave_port_ids[i],
1905                                                                 (unsigned int)port_stats.ipackets, burst_size);
1906                                                 return -1;
1907                                         }
1908                                 } else {
1909                                         if (port_stats.ipackets != 0) {
1910                                                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1911                                                                 test_params->slave_port_ids[i],
1912                                                                 (unsigned int)port_stats.ipackets, 0);
1913                                                 return -1;
1914                                         }
1915                                 }
1916                         }
1917                 } else {
1918                         for (j = 0; j < test_params->bonded_slave_count; j++) {
1919                                 rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
1920                                 if (port_stats.ipackets != 0) {
1921                                         printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
1922                                                         test_params->slave_port_ids[i],
1923                                                         (unsigned int)port_stats.ipackets, 0);
1924                                         return -1;
1925                                 }
1926                         }
1927                 }
1928
1929                 /* free mbufs */
1930                 for (i = 0; i < MAX_PKT_BURST; i++) {
1931                         if (rx_pkt_burst[i] != NULL) {
1932                                 rte_pktmbuf_free(rx_pkt_burst[i]);
1933                                 rx_pkt_burst[i] = NULL;
1934                         }
1935                 }
1936
1937                 /* reset bonded device stats */
1938                 rte_eth_stats_reset(test_params->bonded_port_id);
1939         }
1940
1941         /* Clean up and remove slaves from bonded device */
1942         return remove_slaves_and_stop_bonded_device();
1943 }
1944
1945 static int
1946 test_activebackup_verify_promiscuous_enable_disable(void)
1947 {
1948         int i, primary_port, promiscuous_en;
1949
1950         /* Initialize bonded device with 4 slaves in round robin mode */
1951         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 4, 1)
1952                         != 0)
1953                 return -1;
1954
1955         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
1956         if (primary_port < 0) {
1957                 printf("failed to get primary slave for bonded port (%d)",
1958                                 test_params->bonded_port_id);
1959         }
1960
1961         rte_eth_promiscuous_enable(test_params->bonded_port_id);
1962
1963         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
1964         if (promiscuous_en != 1) {
1965                 printf("Port (%d) promiscuous mode not enabled\n",
1966                                 test_params->bonded_port_id);
1967                 return -1;
1968         }
1969
1970         for (i = 0; i < test_params->bonded_slave_count; i++) {
1971                 promiscuous_en = rte_eth_promiscuous_get(
1972                                 test_params->slave_port_ids[i]);
1973                 if (primary_port == test_params->slave_port_ids[i]) {
1974                         if (promiscuous_en != 1) {
1975                                 printf("slave port (%d) promiscuous mode not enabled\n",
1976                                                 test_params->slave_port_ids[i]);
1977                                 return -1;
1978                         }
1979                 } else {
1980                         if (promiscuous_en != 0) {
1981                                 printf("slave port (%d) promiscuous mode enabled\n",
1982                                                 test_params->slave_port_ids[i]);
1983                                 return -1;
1984                         }
1985                 }
1986
1987         }
1988
1989         rte_eth_promiscuous_disable(test_params->bonded_port_id);
1990
1991         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
1992         if (promiscuous_en != 0) {
1993                 printf("Port (%d) promiscuous mode not disabled\n",
1994                                 test_params->bonded_port_id);
1995                 return -1;
1996         }
1997
1998         for (i = 0; i < test_params->bonded_slave_count; i++) {
1999                 promiscuous_en = rte_eth_promiscuous_get(
2000                                 test_params->slave_port_ids[i]);
2001                 if (promiscuous_en != 0) {
2002                         printf("slave port (%d) promiscuous mode not disabled\n",
2003                                         test_params->slave_port_ids[i]);
2004                         return -1;
2005                 }
2006         }
2007
2008         /* Clean up and remove slaves from bonded device */
2009         return remove_slaves_and_stop_bonded_device();
2010 }
2011
2012 static int
2013 test_activebackup_verify_mac_assignment(void)
2014 {
2015         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1;
2016
2017         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
2018         rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1);
2019
2020         /* Initialize bonded device with 2 slaves in active backup mode */
2021         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 2, 1)
2022                         != 0)
2023                 return -1;
2024
2025         /* Verify that bonded MACs is that of first slave and that the other slave
2026          * MAC hasn't been changed */
2027         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2028         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2029                 printf("bonded port (%d) mac address not set to that of primary port\n",
2030                                 test_params->bonded_port_id);
2031                 return -1;
2032         }
2033
2034         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2035         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2036                 printf("slave port (%d) mac address not set to that of primary port\n",
2037                                 test_params->slave_port_ids[0]);
2038                 return -1;
2039         }
2040
2041         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2042         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2043                 printf("slave port (%d) mac address not as expected\n",
2044                                 test_params->slave_port_ids[1]);
2045                 return -1;
2046         }
2047
2048         /* change primary and verify that MAC addresses haven't changed */
2049         if (rte_eth_bond_primary_set(test_params->bonded_port_id,
2050                         test_params->slave_port_ids[1]) != 0) {
2051                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
2052                                 test_params->bonded_port_id, test_params->slave_port_ids[1]);
2053                 return -1;
2054         }
2055
2056         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2057         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2058                 printf("bonded port (%d) mac address not set to that of primary port\n",
2059                                 test_params->bonded_port_id);
2060                 return -1;
2061         }
2062
2063         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2064         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2065                 printf("slave port (%d) mac address not set to that of primary port\n",
2066                                 test_params->slave_port_ids[0]);
2067                 return -1;
2068         }
2069
2070         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2071         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2072                 printf("slave port (%d) mac address not as expected\n",
2073                                 test_params->slave_port_ids[1]);
2074                 return -1;
2075         }
2076
2077         /* stop / start bonded device and verify that primary MAC address is
2078          * propagated to bonded device and slaves */
2079
2080         rte_eth_dev_stop(test_params->bonded_port_id);
2081
2082         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
2083                 return -1;
2084
2085         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2086         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2087                 printf("bonded port (%d) mac address not set to that of primary port\n",
2088                                 test_params->bonded_port_id);
2089                 return -1;
2090         }
2091
2092         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2093         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2094                 printf("slave port (%d) mac address not as expected\n",
2095                                 test_params->slave_port_ids[0]);
2096                 return -1;
2097         }
2098
2099         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2100         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2101                 printf("slave port (%d) mac address not set to that of primary port\n",
2102                                 test_params->slave_port_ids[1]);
2103                 return -1;
2104         }
2105
2106         /* Set explicit MAC address */
2107         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
2108                         (struct ether_addr *)bonded_mac) != 0) {
2109                 return -1;
2110         }
2111
2112         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2113         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
2114                 printf("bonded port (%d) mac address not set to that of bonded port\n",
2115                                 test_params->bonded_port_id);
2116                 return -1;
2117         }
2118
2119         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2120         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2121                 printf("slave port (%d) mac address not as expected\n",
2122                                 test_params->slave_port_ids[0]);
2123                 return -1;
2124         }
2125
2126         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2127         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
2128                 printf("slave port (%d) mac address not set to that of bonded port\n",
2129                                 test_params->slave_port_ids[1]);
2130                 return -1;
2131         }
2132
2133         /* Clean up and remove slaves from bonded device */
2134         return remove_slaves_and_stop_bonded_device();
2135 }
2136
2137 static int
2138 test_activebackup_verify_slave_link_status_change_failover(void)
2139 {
2140         struct rte_mbuf *pkt_burst[TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
2141         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
2142         struct rte_eth_stats port_stats;
2143
2144         uint8_t slaves[RTE_MAX_ETHPORTS];
2145
2146         int i, j, burst_size, slave_count, primary_port;
2147
2148         burst_size = 21;
2149
2150         memset(pkt_burst, 0, sizeof(pkt_burst));
2151
2152         /* Generate packet burst for testing */
2153         if (generate_test_burst(&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0) !=
2154                         burst_size) {
2155                 printf("generate_test_burst failed\n");
2156                 return -1;
2157         }
2158
2159         /* Initialize bonded device with 4 slaves in round robin mode */
2160         if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
2161                         TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
2162                         != 0)
2163                 return -1;
2164
2165         /* Verify Current Slaves Count /Active Slave Count is */
2166         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
2167                         RTE_MAX_ETHPORTS);
2168         if (slave_count != 4) {
2169                 printf("Number of slaves (%d) is not as expected (%d).\n",
2170                                 slave_count, 4);
2171                 return -1;
2172         }
2173
2174         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
2175                         slaves, RTE_MAX_ETHPORTS);
2176         if (slave_count != 4) {
2177                 printf("Number of active slaves (%d) is not as expected (%d).\n",
2178                                 slave_count, 4);
2179                 return -1;
2180         }
2181
2182         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2183         if (primary_port != test_params->slave_port_ids[0])
2184                 printf("Primary port not as expected");
2185
2186         /* Bring 2 slaves down and verify active slave count */
2187         virtual_ethdev_simulate_link_status_interrupt(
2188                         test_params->slave_port_ids[1], 0);
2189         virtual_ethdev_simulate_link_status_interrupt(
2190                         test_params->slave_port_ids[3], 0);
2191
2192         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves,
2193                         RTE_MAX_ETHPORTS) != 2) {
2194                 printf("Number of active slaves (%d) is not as expected (%d).\n",
2195                                 slave_count, 2);
2196                 return -1;
2197         }
2198
2199         virtual_ethdev_simulate_link_status_interrupt(
2200                         test_params->slave_port_ids[1], 1);
2201         virtual_ethdev_simulate_link_status_interrupt(
2202                         test_params->slave_port_ids[3], 1);
2203
2204
2205         /* Bring primary port down, verify that active slave count is 3 and primary
2206          *  has changed */
2207         virtual_ethdev_simulate_link_status_interrupt(
2208                         test_params->slave_port_ids[0], 0);
2209
2210         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves,
2211                         RTE_MAX_ETHPORTS) != 3) {
2212                 printf("Number of active slaves (%d) is not as expected (%d).\n",
2213                                 slave_count, 3);
2214                 return -1;
2215         }
2216
2217         primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
2218         if (primary_port != test_params->slave_port_ids[2])
2219                 printf("Primary port not as expected");
2220
2221         /* Verify that pkts are sent on new primary slave */
2222
2223         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size)
2224                         != burst_size) {
2225                 printf("rte_eth_tx_burst failed\n");
2226                 return -1;
2227         }
2228
2229         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
2230         if (port_stats.opackets != (uint64_t)burst_size) {
2231                 printf("(%d) port_stats.opackets not as expected\n",
2232                                 test_params->slave_port_ids[2]);
2233                 return -1;
2234         }
2235
2236         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2237         if (port_stats.opackets != 0) {
2238                 printf("(%d) port_stats.opackets not as expected\n",
2239                                 test_params->slave_port_ids[0]);
2240                 return -1;
2241         }
2242         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2243         if (port_stats.opackets != 0) {
2244                 printf("(%d) port_stats.opackets not as expected\n",
2245                                 test_params->slave_port_ids[1]);
2246                 return -1;
2247         }
2248         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
2249         if (port_stats.opackets != 0) {
2250                 printf("(%d) port_stats.opackets not as expected\n",
2251                                 test_params->slave_port_ids[3]);
2252                 return -1;
2253         }
2254
2255         /* Generate packet burst for testing */
2256
2257         for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) {
2258                 if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0) !=
2259                                 burst_size)
2260                         return -1;
2261
2262                 virtual_ethdev_add_mbufs_to_rx_queue(
2263                         test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size);
2264         }
2265
2266         if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
2267                         MAX_PKT_BURST) != burst_size) {
2268                 printf("rte_eth_rx_burst\n");
2269                 return -1;
2270         }
2271
2272         /* Verify bonded device rx count */
2273         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2274         if (port_stats.ipackets != (uint64_t)burst_size) {
2275                 printf("(%d) port_stats.ipackets not as expected\n",
2276                                 test_params->bonded_port_id);
2277                 return -1;
2278         }
2279
2280         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
2281         if (port_stats.opackets != (uint64_t)burst_size) {
2282                 printf("(%d) port_stats.opackets not as expected\n",
2283                                 test_params->slave_port_ids[2]);
2284                 return -1;
2285         }
2286
2287         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2288         if (port_stats.opackets != 0) {
2289                 printf("(%d) port_stats.opackets not as expected\n",
2290                                 test_params->slave_port_ids[0]);
2291                 return -1;
2292         }
2293
2294         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2295         if (port_stats.opackets != 0) {
2296                 printf("(%d) port_stats.opackets not as expected\n",
2297                                 test_params->slave_port_ids[1]);
2298                 return -1;
2299         }
2300
2301         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
2302         if (port_stats.opackets != 0) {
2303                 printf("(%d) port_stats.opackets not as expected\n",
2304                                 test_params->slave_port_ids[3]);
2305                 return -1;
2306         }
2307
2308         /* free mbufs */
2309
2310         for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) {
2311                 for (j = 0; j < MAX_PKT_BURST; j++) {
2312                         if (pkt_burst[i][j] != NULL) {
2313                                 rte_pktmbuf_free(pkt_burst[i][j]);
2314                                 pkt_burst[i][j] = NULL;
2315                         }
2316                 }
2317         }
2318
2319
2320         /* Clean up and remove slaves from bonded device */
2321         return remove_slaves_and_stop_bonded_device();
2322 }
2323
2324 /** Balance Mode Tests */
2325
2326 static int
2327 test_balance_xmit_policy_configuration(void)
2328 {
2329         int retval;
2330
2331         retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
2332                         2, 1);
2333         if (retval != 0) {
2334                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2335                 return -1;
2336         }
2337
2338         /* Invalid port id */
2339         retval = rte_eth_bond_xmit_policy_set(INVALID_PORT_ID,
2340                         BALANCE_XMIT_POLICY_LAYER2);
2341         if (retval == 0) {
2342                 printf("Expected call to failed as invalid port specified.\n");
2343                 return -1;
2344         }
2345
2346         /* Set xmit policy on non bonded device */
2347         retval = rte_eth_bond_xmit_policy_set(test_params->slave_port_ids[0],
2348                         BALANCE_XMIT_POLICY_LAYER2);
2349         if (retval == 0) {
2350                 printf("Expected call to failed as invalid port specified.\n");
2351                 return -1;
2352         }
2353
2354         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2355                         BALANCE_XMIT_POLICY_LAYER2);
2356         if (retval != 0) {
2357                 printf("Failed to set balance xmit policy.\n");
2358                 return -1;
2359         }
2360         if (rte_eth_bond_xmit_policy_get(test_params->bonded_port_id) !=
2361                         BALANCE_XMIT_POLICY_LAYER2) {
2362                 printf("balance xmit policy not as expected.\n");
2363                 return -1;
2364         }
2365
2366         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2367                         BALANCE_XMIT_POLICY_LAYER23);
2368         if (retval != 0) {
2369                 printf("Failed to set balance xmit policy.\n");
2370                 return -1;
2371         }
2372         if (rte_eth_bond_xmit_policy_get(test_params->bonded_port_id) !=
2373                         BALANCE_XMIT_POLICY_LAYER23) {
2374                 printf("balance xmit policy not as expected.\n");
2375                 return -1;
2376         }
2377
2378         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2379                         BALANCE_XMIT_POLICY_LAYER34);
2380         if (retval != 0) {
2381                 printf("Failed to set balance xmit policy.\n");
2382                 return -1;
2383         }
2384         if (rte_eth_bond_xmit_policy_get(test_params->bonded_port_id) !=
2385                         BALANCE_XMIT_POLICY_LAYER34) {
2386                 printf("balance xmit policy not as expected.\n");
2387                 return -1;
2388         }
2389
2390         /* Invalid port id */
2391         if (rte_eth_bond_xmit_policy_get(INVALID_PORT_ID) >= 0)
2392                 return -1;
2393
2394         /* Clean up and remove slaves from bonded device */
2395         return remove_slaves_and_stop_bonded_device();
2396 }
2397
2398 #define TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT (2)
2399
2400 static int
2401 test_balance_l2_tx_burst(void)
2402 {
2403         struct rte_mbuf *pkts_burst[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
2404         int burst_size[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT] = { 10, 15 };
2405
2406         uint16_t pktlen;
2407
2408         int retval, i;
2409         struct rte_eth_stats port_stats;
2410
2411         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE,
2412                         TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1);
2413         if (retval != 0) {
2414                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2415                 return -1;
2416         }
2417
2418         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2419                         BALANCE_XMIT_POLICY_LAYER2);
2420         if (retval != 0) {
2421                 printf("Failed to set balance xmit policy.\n");
2422                 return -1;
2423         }
2424
2425
2426         initialize_eth_header(test_params->pkt_eth_hdr,
2427                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0);
2428         pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
2429                         dst_port_0, 16);
2430         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
2431                         dst_addr_0, pktlen);
2432
2433         /* Generate a burst 1 of packets to transmit */
2434         if (generate_packet_burst(test_params->mbuf_pool, &pkts_burst[0][0],
2435                         test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
2436                         test_params->pkt_udp_hdr, burst_size[0]) != burst_size[0])
2437                 return -1;
2438
2439         initialize_eth_header(test_params->pkt_eth_hdr,
2440                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, 0, 0);
2441
2442         /* Generate a burst 2 of packets to transmit */
2443         if (generate_packet_burst(test_params->mbuf_pool, &pkts_burst[1][0],
2444                         test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
2445                         test_params->pkt_udp_hdr, burst_size[1]) != burst_size[1])
2446                 return -1;
2447
2448         /* Send burst 1 on bonded port */
2449         for (i = 0; i < TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT; i++) {
2450                 if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkts_burst[i][0],
2451                         burst_size[i]) != burst_size[i])
2452                         return -1;
2453         }
2454         /* Verify bonded port tx stats */
2455         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2456         if (port_stats.opackets != (uint64_t)(burst_size[0] + burst_size[1])) {
2457                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
2458                                 test_params->bonded_port_id,
2459                                 (unsigned int)port_stats.opackets, burst_size[0] + burst_size[1]);
2460                 return -1;
2461         }
2462
2463
2464         /* Verify slave ports tx stats */
2465         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2466         if (port_stats.opackets != (uint64_t)burst_size[0]) {
2467                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2468                                 test_params->slave_port_ids[0],
2469                                 (unsigned int)port_stats.opackets, burst_size[0]);
2470                 return -1;
2471         }
2472
2473         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2474         if (port_stats.opackets != (uint64_t)burst_size[1]) {
2475                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2476                                 test_params->slave_port_ids[1], (
2477                                                 unsigned int)port_stats.opackets, burst_size[1]);
2478                 return -1;
2479         }
2480
2481         /* Put all slaves down and try and transmit */
2482         for (i = 0; i < test_params->bonded_slave_count; i++) {
2483
2484                 virtual_ethdev_simulate_link_status_interrupt(
2485                                 test_params->slave_port_ids[i], 0);
2486         }
2487
2488         /* Send burst on bonded port */
2489         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkts_burst[0][0],
2490                         burst_size[0]) != 0)
2491                 return -1;
2492
2493         /* Clean up and remove slaves from bonded device */
2494         return remove_slaves_and_stop_bonded_device();
2495 }
2496
2497 static int
2498 balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
2499                 uint8_t toggle_mac_addr, uint8_t toggle_ip_addr)
2500 {
2501         int retval, i;
2502         int burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
2503
2504         struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
2505         struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
2506
2507         struct rte_eth_stats port_stats;
2508
2509         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1);
2510         if (retval != 0) {
2511                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2512                 return -1;
2513         }
2514
2515         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2516                         BALANCE_XMIT_POLICY_LAYER23);
2517         if (retval != 0) {
2518                 printf("Failed to set balance xmit policy.\n");
2519                 return -1;
2520         }
2521
2522         burst_size_1 = 20;
2523         burst_size_2 = 10;
2524
2525         if (burst_size_1 > MAX_PKT_BURST || burst_size_2 > MAX_PKT_BURST) {
2526                 printf("Burst size specified is greater than supported.\n");
2527                 return -1;
2528         }
2529
2530         /* Generate test bursts of packets to transmit */
2531         if (generate_test_burst(pkts_burst_1, burst_size_1, vlan_enabled, ipv4,
2532                         0, 0, 0) != burst_size_1)
2533                 return -1;
2534
2535         if (generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4,
2536                         toggle_mac_addr, toggle_ip_addr, 0) != burst_size_2)
2537                 return -1;
2538
2539         /* Send burst 1 on bonded port */
2540         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
2541                         burst_size_1);
2542         if (nb_tx_1 != burst_size_1)
2543                 return -1;
2544
2545         /* Send burst 2 on bonded port */
2546         nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
2547                         burst_size_2);
2548         if (nb_tx_2 != burst_size_2)
2549                 return -1;
2550
2551         /* Verify bonded port tx stats */
2552         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2553         if (port_stats.opackets != (uint64_t)(nb_tx_1 + nb_tx_2)) {
2554                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
2555                                 test_params->bonded_port_id,
2556                                 (unsigned int)port_stats.opackets, nb_tx_1 + nb_tx_2);
2557                 return -1;
2558         }
2559
2560         /* Verify slave ports tx stats */
2561         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2562         if (port_stats.opackets != (uint64_t)nb_tx_1) {
2563                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2564                                 test_params->slave_port_ids[0],
2565                                 (unsigned int)port_stats.opackets, nb_tx_1);
2566                 return -1;
2567         }
2568
2569         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2570         if (port_stats.opackets != (uint64_t)nb_tx_2) {
2571                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2572                                 test_params->slave_port_ids[1],
2573                                 (unsigned int)port_stats.opackets, nb_tx_2);
2574                 return -1;
2575         }
2576
2577         /* Put all slaves down and try and transmit */
2578         for (i = 0; i < test_params->bonded_slave_count; i++) {
2579
2580                 virtual_ethdev_simulate_link_status_interrupt(
2581                                 test_params->slave_port_ids[i], 0);
2582         }
2583
2584         /* Send burst on bonded port */
2585         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
2586                         burst_size_1);
2587         if (nb_tx_1 != 0)
2588                 return -1;
2589
2590         /* Clean up and remove slaves from bonded device */
2591         return remove_slaves_and_stop_bonded_device();
2592 }
2593
2594 static int
2595 test_balance_l23_tx_burst_ipv4_toggle_ip_addr(void)
2596 {
2597         return balance_l23_tx_burst(0, 1, 1, 0);
2598 }
2599
2600 static int
2601 test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr(void)
2602 {
2603         return balance_l23_tx_burst(1, 1, 0, 1);
2604 }
2605
2606 static int
2607 test_balance_l23_tx_burst_ipv6_toggle_ip_addr(void)
2608 {
2609         return balance_l23_tx_burst(0, 0, 0, 1);
2610 }
2611
2612 static int
2613 test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr(void)
2614 {
2615         return balance_l23_tx_burst(1, 0, 0, 1);
2616 }
2617
2618 static int
2619 test_balance_l23_tx_burst_toggle_mac_addr(void)
2620 {
2621         return balance_l23_tx_burst(0, 0, 1, 0);
2622 }
2623
2624 static int
2625 balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
2626                 uint8_t toggle_mac_addr, uint8_t toggle_ip_addr,
2627                 uint8_t toggle_udp_port)
2628 {
2629         int retval, i;
2630         int burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
2631
2632         struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
2633         struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
2634
2635         struct rte_eth_stats port_stats;
2636
2637         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1);
2638         if (retval != 0) {
2639                 printf("Failed to initialize_bonded_device_with_slaves.\n");
2640                 return -1;
2641         }
2642
2643         retval = rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
2644                         BALANCE_XMIT_POLICY_LAYER34);
2645         if (retval != 0) {
2646                 printf("Failed to set balance xmit policy.\n");
2647                 return -1;
2648         }
2649
2650         burst_size_1 = 20;
2651         burst_size_2 = 10;
2652
2653         if (burst_size_1 > MAX_PKT_BURST || burst_size_2 > MAX_PKT_BURST) {
2654                 printf("Burst size specified is greater than supported.\n");
2655                 return -1;
2656         }
2657
2658         /* Generate test bursts of packets to transmit */
2659         if (generate_test_burst(pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0,
2660                         0, 0) != burst_size_1)
2661                 return -1;
2662
2663         if (generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4,
2664                         toggle_mac_addr, toggle_ip_addr, toggle_udp_port) != burst_size_2)
2665                 return -1;
2666
2667         /* Send burst 1 on bonded port */
2668         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
2669                         burst_size_1);
2670         if (nb_tx_1 != burst_size_1)
2671                 return -1;
2672
2673         /* Send burst 2 on bonded port */
2674         nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
2675                         burst_size_2);
2676         if (nb_tx_2 != burst_size_2)
2677                 return -1;
2678
2679
2680         /* Verify bonded port tx stats */
2681         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2682         if (port_stats.opackets != (uint64_t)(nb_tx_1 + nb_tx_2)) {
2683                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
2684                                 test_params->bonded_port_id,
2685                                 (unsigned int)port_stats.opackets, nb_tx_1 + nb_tx_2);
2686                 return -1;
2687         }
2688
2689         /* Verify slave ports tx stats */
2690         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2691         if (port_stats.opackets != (uint64_t)nb_tx_1) {
2692                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2693                                 test_params->slave_port_ids[0],
2694                                 (unsigned int)port_stats.opackets, nb_tx_1);
2695                 return -1;
2696         }
2697
2698         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2699         if (port_stats.opackets != (uint64_t)nb_tx_2) {
2700                 printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
2701                                 test_params->slave_port_ids[1],
2702                                 (unsigned int)port_stats.opackets, nb_tx_2);
2703                 return -1;
2704         }
2705
2706         /* Put all slaves down and try and transmit */
2707         for (i = 0; i < test_params->bonded_slave_count; i++) {
2708
2709                 virtual_ethdev_simulate_link_status_interrupt(
2710                                 test_params->slave_port_ids[i], 0);
2711         }
2712
2713         /* Send burst on bonded port */
2714         nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
2715                         burst_size_1);
2716         if (nb_tx_1 != 0)
2717                 return -1;
2718
2719         /* Clean up and remove slaves from bonded device */
2720         return remove_slaves_and_stop_bonded_device();
2721 }
2722
2723 static int
2724 test_balance_l34_tx_burst_ipv4_toggle_ip_addr(void)
2725 {
2726         return balance_l34_tx_burst(0, 1, 0, 1, 0);
2727 }
2728
2729 static int
2730 test_balance_l34_tx_burst_ipv4_toggle_udp_port(void)
2731 {
2732         return balance_l34_tx_burst(0, 1, 0, 0, 1);
2733 }
2734
2735 static int
2736 test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr(void)
2737 {
2738         return balance_l34_tx_burst(1, 1, 0, 1, 0);
2739 }
2740
2741 static int
2742 test_balance_l34_tx_burst_ipv6_toggle_ip_addr(void)
2743 {
2744         return balance_l34_tx_burst(0, 0, 0, 1, 0);
2745 }
2746
2747 static int
2748 test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr(void)
2749 {
2750         return balance_l34_tx_burst(1, 0, 0, 1, 0);
2751 }
2752
2753 static int
2754 test_balance_l34_tx_burst_ipv6_toggle_udp_port(void)
2755 {
2756         return balance_l34_tx_burst(0, 0, 0, 0, 1);
2757 }
2758
2759 #define TEST_BALANCE_RX_BURST_SLAVE_COUNT (3)
2760
2761 static int
2762 test_balance_rx_burst(void)
2763 {
2764         struct rte_mbuf *gen_pkt_burst[TEST_BALANCE_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
2765
2766         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
2767         struct rte_eth_stats port_stats;
2768
2769         int burst_size[TEST_BALANCE_RX_BURST_SLAVE_COUNT] = { 10, 5, 30 };
2770         int i, j, nb_rx;
2771
2772         memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
2773
2774         /* Initialize bonded device with 4 slaves in round robin mode */
2775         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 3, 1)
2776                         != 0)
2777                 return -1;
2778
2779         /* Generate test bursts of packets to transmit */
2780         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
2781                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size[i], 0, 0, 1,
2782                                 0, 0) != burst_size[i])
2783                         return -1;
2784         }
2785         /* Add rx data to slaves */
2786         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
2787                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
2788                                 &gen_pkt_burst[i][0], burst_size[i]);
2789         }
2790
2791         /* Call rx burst on bonded device */
2792         /* Send burst on bonded port */
2793         nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
2794                         MAX_PKT_BURST);
2795         if (nb_rx != burst_size[0] + burst_size[1] + burst_size[2]) {
2796                 printf("balance rx burst failed\n");
2797                 return -1;
2798         }
2799
2800         /* Verify bonded device rx count */
2801         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
2802         if (port_stats.ipackets != (uint64_t)(burst_size[0] + burst_size[1] +
2803                         burst_size[2])) {
2804                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
2805                                 test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
2806                                 burst_size[0] + burst_size[1] + burst_size[2]);
2807                 return -1;
2808         }
2809
2810
2811         /* Verify bonded slave devices rx counts */
2812         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
2813         if (port_stats.ipackets != (uint64_t)burst_size[0]) {
2814                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2815                                 test_params->slave_port_ids[0],
2816                                 (unsigned int)port_stats.ipackets, burst_size[0]);
2817                 return -1;
2818         }
2819
2820         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
2821         if (port_stats.ipackets != (uint64_t)burst_size[1]) {
2822                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2823                                 test_params->slave_port_ids[1],
2824                                 (unsigned int)port_stats.ipackets, burst_size[1]);
2825                 return -1;
2826         }
2827
2828         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
2829         if (port_stats.ipackets != (uint64_t)burst_size[2]) {
2830                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2831                                 test_params->slave_port_ids[2],
2832                                 (unsigned int)port_stats.ipackets, burst_size[2]);
2833                 return -1;
2834         }
2835
2836         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
2837         if (port_stats.ipackets != 0) {
2838                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
2839                                 test_params->slave_port_ids[3],
2840                                 (unsigned int)port_stats.ipackets, 0);
2841                 return -1;
2842         }
2843
2844         /* free mbufs */
2845         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
2846                 for (j = 0; j < MAX_PKT_BURST; j++) {
2847                         if (gen_pkt_burst[i][j] != NULL) {
2848                                 rte_pktmbuf_free(gen_pkt_burst[i][j]);
2849                                 gen_pkt_burst[i][j] = NULL;
2850                         }
2851                 }
2852         }
2853
2854         /* Clean up and remove slaves from bonded device */
2855         return remove_slaves_and_stop_bonded_device();
2856 }
2857
2858 static int
2859 test_balance_verify_promiscuous_enable_disable(void)
2860 {
2861         int i, promiscuous_en;
2862
2863         /* Initialize bonded device with 4 slaves in round robin mode */
2864         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 4, 1) != 0)
2865                 return -1;
2866
2867         rte_eth_promiscuous_enable(test_params->bonded_port_id);
2868
2869         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
2870         if (promiscuous_en != 1) {
2871                 printf("Port (%d) promiscuous mode not enabled\n",
2872                                 test_params->bonded_port_id);
2873                 return -1;
2874         }
2875
2876         for (i = 0; i < test_params->bonded_slave_count; i++) {
2877                 promiscuous_en = rte_eth_promiscuous_get(
2878                                 test_params->slave_port_ids[i]);
2879                 if (promiscuous_en != 1) {
2880                         printf("slave port (%d) promiscuous mode not enabled\n",
2881                                         test_params->slave_port_ids[i]);
2882                         return -1;
2883                 }
2884         }
2885
2886         rte_eth_promiscuous_disable(test_params->bonded_port_id);
2887
2888         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
2889         if (promiscuous_en != 0) {
2890                 printf("Port (%d) promiscuous mode not disabled\n",
2891                                 test_params->bonded_port_id);
2892                 return -1;
2893         }
2894
2895         for (i = 0; i < test_params->bonded_slave_count; i++) {
2896                 promiscuous_en = rte_eth_promiscuous_get(
2897                                 test_params->slave_port_ids[i]);
2898                 if (promiscuous_en != 0) {
2899                         printf("slave port (%d) promiscuous mode not disabled\n",
2900                                         test_params->slave_port_ids[i]);
2901                         return -1;
2902                 }
2903         }
2904
2905         /* Clean up and remove slaves from bonded device */
2906         return remove_slaves_and_stop_bonded_device();
2907 }
2908
2909 static int
2910 test_balance_verify_mac_assignment(void)
2911 {
2912         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1;
2913
2914         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
2915         rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1);
2916
2917         /* Initialize bonded device with 2 slaves in active backup mode */
2918         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1) != 0)
2919                 return -1;
2920
2921         /* Verify that bonded MACs is that of first slave and that the other slave
2922          * MAC hasn't been changed */
2923         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2924         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2925                 printf("bonded port (%d) mac address not set to that of primary port\n",
2926                                 test_params->bonded_port_id);
2927                 return -1;
2928         }
2929
2930         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2931         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2932                 printf("slave port (%d) mac address not set to that of primary port\n",
2933                                 test_params->slave_port_ids[0]);
2934                 return -1;
2935         }
2936
2937         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2938         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2939                 printf("slave port (%d) mac address not set to that of primary port\n",
2940                                 test_params->slave_port_ids[1]);
2941                 return -1;
2942         }
2943
2944         /* change primary and verify that MAC addresses haven't changed */
2945         if (rte_eth_bond_primary_set(test_params->bonded_port_id,
2946                         test_params->slave_port_ids[1]) != 0) {
2947                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
2948                                 test_params->bonded_port_id, test_params->slave_port_ids[1]);
2949                 return -1;
2950         }
2951
2952         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2953         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2954                 printf("bonded port (%d) mac address not set to that of primary port\n",
2955                                 test_params->bonded_port_id);
2956                 return -1;
2957         }
2958
2959         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2960         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2961                 printf("slave port (%d) mac address not set to that of primary port\n",
2962                                 test_params->slave_port_ids[0]);
2963                 return -1;
2964         }
2965
2966         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2967         if (memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr))) {
2968                 printf("slave port (%d) mac address not set to that of primary port\n",
2969                                 test_params->slave_port_ids[1]);
2970                 return -1;
2971         }
2972
2973         /* stop / start bonded device and verify that primary MAC address is
2974          * propagated to bonded device and slaves */
2975
2976         rte_eth_dev_stop(test_params->bonded_port_id);
2977
2978         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
2979                 return -1;
2980
2981         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
2982         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2983                 printf("bonded port (%d) mac address not set to that of primary port\n",
2984                                 test_params->bonded_port_id);
2985                 return -1;
2986         }
2987
2988         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
2989         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2990                 printf("slave port (%d) mac address not set to that of primary port\n",
2991                                 test_params->slave_port_ids[0]);
2992                 return -1;
2993         }
2994
2995         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
2996         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
2997                 printf("slave port (%d) mac address not set to that of primary port\n",
2998                                 test_params->slave_port_ids[1]);
2999                 return -1;
3000         }
3001
3002         /* Set explicit MAC address */
3003         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
3004                         (struct ether_addr *)bonded_mac) != 0)
3005                 return -1;
3006
3007         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3008         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3009                 printf("bonded port (%d) mac address not set to that of bonded port\n",
3010                                 test_params->bonded_port_id);
3011                 return -1;
3012         }
3013
3014         rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr);
3015         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3016                 printf("slave port (%d) mac address not as expected\n",
3017                                 test_params->slave_port_ids[0]);
3018                 return -1;
3019         }
3020
3021         rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr);
3022         if (memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3023                 printf("slave port (%d) mac address not set to that of bonded port\n",
3024                                 test_params->slave_port_ids[1]);
3025                 return -1;
3026         }
3027
3028         /* Clean up and remove slaves from bonded device */
3029         return remove_slaves_and_stop_bonded_device();
3030 }
3031
3032 #define TEST_BALANCE_LINK_STATUS_SLAVE_COUNT (4)
3033
3034 static int
3035 test_balance_verify_slave_link_status_change_behaviour(void)
3036 {
3037         struct rte_mbuf *pkt_burst[TEST_BALANCE_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST];
3038         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
3039         struct rte_eth_stats port_stats;
3040
3041         uint8_t slaves[RTE_MAX_ETHPORTS];
3042
3043         int i, j, burst_size, slave_count;
3044
3045         memset(pkt_burst, 0, sizeof(pkt_burst));
3046
3047         /* Initialize bonded device with 4 slaves in round robin mode */
3048         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE,
3049                         TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1) != 0)
3050                 return -1;
3051
3052         if (rte_eth_bond_xmit_policy_set(test_params->bonded_port_id,
3053                         BALANCE_XMIT_POLICY_LAYER2)) {
3054                 printf("Failed to set balance xmit policy.\n");
3055                 return -1;
3056         }
3057
3058         /* Verify Current Slaves Count /Active Slave Count is */
3059         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
3060                         RTE_MAX_ETHPORTS);
3061         if (slave_count != TEST_BALANCE_LINK_STATUS_SLAVE_COUNT) {
3062                 printf("Number of slaves (%d) is not as expected (%d).\n", slave_count,
3063                                 TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
3064                 return -1;
3065         }
3066
3067         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
3068                         slaves, RTE_MAX_ETHPORTS);
3069         if (slave_count != TEST_BALANCE_LINK_STATUS_SLAVE_COUNT) {
3070                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3071                                 slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
3072                 return -1;
3073         }
3074
3075         /* Set 2 slaves link status to down */
3076         virtual_ethdev_simulate_link_status_interrupt(
3077                         test_params->slave_port_ids[1], 0);
3078         virtual_ethdev_simulate_link_status_interrupt(
3079                         test_params->slave_port_ids[3], 0);
3080
3081         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
3082                         slaves, RTE_MAX_ETHPORTS) != 2) {
3083                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3084                                 slave_count, 2);
3085                 return -1;
3086         }
3087
3088         /* Send to sets of packet burst and verify that they are balanced across
3089          *  slaves */
3090         burst_size = 21;
3091
3092         if (generate_test_burst(&pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0) !=
3093                         burst_size) {
3094                 printf("generate_test_burst failed\n");
3095                 return -1;
3096         }
3097
3098         if (generate_test_burst(&pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0) !=
3099                         burst_size) {
3100                 printf("generate_test_burst failed\n");
3101                 return -1;
3102         }
3103
3104         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0],
3105                         burst_size) != burst_size) {
3106                 printf("rte_eth_tx_burst failed\n");
3107                 return -1;
3108         }
3109
3110         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[1][0],
3111                         burst_size) != burst_size) {
3112                 printf("rte_eth_tx_burst failed\n");
3113                 return -1;
3114         }
3115
3116         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3117         if (port_stats.opackets != (uint64_t)(burst_size + burst_size)) {
3118                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3119                                 test_params->bonded_port_id, (int)port_stats.opackets,
3120                                 burst_size + burst_size);
3121                 return -1;
3122         }
3123
3124         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3125         if (port_stats.opackets != (uint64_t)burst_size) {
3126                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3127                                 test_params->slave_port_ids[0], (int)port_stats.opackets,
3128                                 burst_size);
3129                 return -1;
3130         }
3131
3132         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3133         if (port_stats.opackets != (uint64_t)burst_size) {
3134                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3135                                 test_params->slave_port_ids[2], (int)port_stats.opackets,
3136                                 burst_size);
3137                 return -1;
3138         }
3139
3140         /* verify that all packets get send on primary slave when no other slaves
3141          * are available */
3142         virtual_ethdev_simulate_link_status_interrupt(
3143                         test_params->slave_port_ids[2], 0);
3144
3145         if (rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves,
3146                         RTE_MAX_ETHPORTS) != 1) {
3147                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3148                                 slave_count, 1);
3149                 return -1;
3150         }
3151
3152         if (generate_test_burst(&pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0) !=
3153                         burst_size) {
3154                 printf("generate_test_burst failed\n");
3155                 return -1;
3156         }
3157
3158         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[1][0],
3159                         burst_size) != burst_size) {
3160                 printf("rte_eth_tx_burst failed\n");
3161                 return -1;
3162         }
3163
3164         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3165         if (port_stats.opackets != (uint64_t)(burst_size + burst_size +
3166                         burst_size)) {
3167                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3168                                 test_params->bonded_port_id, (int)port_stats.opackets,
3169                                 burst_size + burst_size + burst_size);
3170                 return -1;
3171         }
3172
3173         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3174         if (port_stats.opackets != (uint64_t)(burst_size + burst_size)) {
3175                 printf("(%d) port_stats.opackets (%d) not as expected (%d).\n",
3176                                 test_params->slave_port_ids[0], (int)port_stats.opackets,
3177                                 burst_size + burst_size);
3178                 return -1;
3179         }
3180
3181
3182         virtual_ethdev_simulate_link_status_interrupt(
3183                         test_params->slave_port_ids[0], 0);
3184         virtual_ethdev_simulate_link_status_interrupt(
3185                         test_params->slave_port_ids[1], 1);
3186         virtual_ethdev_simulate_link_status_interrupt(
3187                         test_params->slave_port_ids[2], 1);
3188         virtual_ethdev_simulate_link_status_interrupt(
3189                         test_params->slave_port_ids[3], 1);
3190
3191         for (i = 0; i < TEST_BALANCE_LINK_STATUS_SLAVE_COUNT; i++) {
3192                 if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0) !=
3193                                 burst_size)
3194                         return -1;
3195
3196                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
3197                                 &pkt_burst[i][0], burst_size);
3198         }
3199
3200
3201
3202         /* Verify that pkts are not received on slaves with link status down */
3203
3204         rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
3205                         MAX_PKT_BURST);
3206
3207         /* Verify bonded device rx count */
3208         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3209         if (port_stats.ipackets != (uint64_t)(burst_size * 3)) {
3210                 printf("(%d) port_stats.ipackets (%d) not as expected (%d)\n",
3211                                 test_params->bonded_port_id, (int)port_stats.ipackets,
3212                                 burst_size * 3);
3213                 return -1;
3214         }
3215
3216         /* free mbufs allocate for rx testing */
3217         for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
3218                 for (j = 0; j < MAX_PKT_BURST; j++) {
3219                         if (pkt_burst[i][j] != NULL) {
3220                                 rte_pktmbuf_free(pkt_burst[i][j]);
3221                                 pkt_burst[i][j] = NULL;
3222                         }
3223                 }
3224         }
3225
3226         /* Clean up and remove slaves from bonded device */
3227         return remove_slaves_and_stop_bonded_device();
3228 }
3229
3230 /** Broadcast Mode Tests */
3231
3232 static int
3233 test_broadcast_tx_burst(void)
3234 {
3235         int i, pktlen, retval, burst_size, generated_burst_size, nb_tx;
3236         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
3237
3238         struct rte_eth_stats port_stats;
3239
3240         retval = initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 2, 1);
3241         if (retval != 0) {
3242                 printf("Failed to initialize_bonded_device_with_slaves.\n");
3243                 return -1;
3244         }
3245
3246         initialize_eth_header(test_params->pkt_eth_hdr,
3247                         (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, 0, 0);
3248
3249         pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
3250                         dst_port_0, 16);
3251         pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
3252                         dst_addr_0, pktlen);
3253
3254         burst_size = 20 * test_params->bonded_slave_count;
3255
3256         if (burst_size > MAX_PKT_BURST) {
3257                 printf("Burst size specified is greater than supported.\n");
3258                 return -1;
3259         }
3260
3261         /* Generate a burst of packets to transmit */
3262         generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
3263                         pkts_burst,     test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
3264                         1, test_params->pkt_udp_hdr, burst_size);
3265         if (generated_burst_size != burst_size)
3266                 return -1;
3267
3268         /* Send burst on bonded port */
3269         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
3270                         burst_size);
3271         if (nb_tx != burst_size * test_params->bonded_slave_count) {
3272                 printf("Bonded Port (%d) rx burst failed, packets transmitted value (%u) not as expected (%d)\n",
3273                                 test_params->bonded_port_id,
3274                                 nb_tx, burst_size);
3275                 return -1;
3276         }
3277
3278         /* Verify bonded port tx stats */
3279         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3280         if (port_stats.opackets != (uint64_t)burst_size *
3281                         test_params->bonded_slave_count) {
3282                 printf("Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
3283                                 test_params->bonded_port_id, (unsigned int)port_stats.opackets,
3284                                 burst_size);
3285         }
3286
3287         /* Verify slave ports tx stats */
3288         for (i = 0; i < test_params->bonded_slave_count; i++) {
3289                 rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
3290                 if (port_stats.opackets != (uint64_t)burst_size) {
3291                         printf("Slave Port (%d) opackets value (%u) not as expected (%d)\n",
3292                                         test_params->bonded_port_id,
3293                                         (unsigned int)port_stats.opackets, burst_size);
3294                 }
3295         }
3296
3297         /* Put all slaves down and try and transmit */
3298         for (i = 0; i < test_params->bonded_slave_count; i++) {
3299
3300                 virtual_ethdev_simulate_link_status_interrupt(
3301                                 test_params->slave_port_ids[i], 0);
3302         }
3303
3304         /* Send burst on bonded port */
3305         nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
3306                         burst_size);
3307         if (nb_tx != 0)
3308                 return -1;
3309
3310         /* Clean up and remove slaves from bonded device */
3311         return remove_slaves_and_stop_bonded_device();
3312 }
3313
3314 #define BROADCAST_RX_BURST_NUM_OF_SLAVES (3)
3315
3316 static int
3317 test_broadcast_rx_burst(void)
3318 {
3319         struct rte_mbuf *gen_pkt_burst[BROADCAST_RX_BURST_NUM_OF_SLAVES][MAX_PKT_BURST];
3320
3321         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
3322         struct rte_eth_stats port_stats;
3323
3324         int burst_size[BROADCAST_RX_BURST_NUM_OF_SLAVES] = { 10, 5, 30 };
3325         int i, j, nb_rx;
3326
3327         memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
3328
3329         /* Initialize bonded device with 4 slaves in round robin mode */
3330         if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 3, 1) != 0)
3331                 return -1;
3332
3333
3334         /* Generate test bursts of packets to transmit */
3335         for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
3336                 if (generate_test_burst(&gen_pkt_burst[i][0], burst_size[i], 0, 0, 1, 0,
3337                                 0) != burst_size[i])
3338                         return -1;
3339         }
3340
3341         /* Add rx data to slave 0 */
3342         for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
3343                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
3344                                 &gen_pkt_burst[i][0], burst_size[i]);
3345         }
3346
3347
3348         /* Call rx burst on bonded device */
3349         /* Send burst on bonded port */
3350         nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
3351                         MAX_PKT_BURST);
3352         if (nb_rx != burst_size[0] + burst_size[1] + burst_size[2]) {
3353                 printf("round-robin rx burst failed");
3354                 return -1;
3355         }
3356
3357         /* Verify bonded device rx count */
3358         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3359         if (port_stats.ipackets != (uint64_t)(burst_size[0] + burst_size[1] +
3360                         burst_size[2])) {
3361                 printf("Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
3362                                 test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
3363                                 burst_size[0] + burst_size[1] + burst_size[2]);
3364                 return -1;
3365         }
3366
3367
3368         /* Verify bonded slave devices rx counts */
3369         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3370         if (port_stats.ipackets != (uint64_t)burst_size[0]) {
3371                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3372                                 test_params->slave_port_ids[0],
3373                                 (unsigned int)port_stats.ipackets, burst_size[0]);
3374                 return -1;
3375         }
3376
3377         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3378         if (port_stats.ipackets != (uint64_t)burst_size[1]) {
3379                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3380                                 test_params->slave_port_ids[1],
3381                                 (unsigned int)port_stats.ipackets, burst_size[1]);
3382                 return -1;
3383         }
3384
3385         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3386         if (port_stats.ipackets != (uint64_t)burst_size[2]) {
3387                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3388                                 test_params->slave_port_ids[2],
3389                                 (unsigned int)port_stats.ipackets,
3390                                 burst_size[2]);
3391                 return -1;
3392         }
3393
3394         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
3395         if (port_stats.ipackets != 0) {
3396                 printf("Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
3397                                 test_params->slave_port_ids[3],
3398                                 (unsigned int)port_stats.ipackets, 0);
3399                 return -1;
3400         }
3401
3402         /* free mbufs allocate for rx testing */
3403         for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
3404                 for (j = 0; j < MAX_PKT_BURST; j++) {
3405                         if (gen_pkt_burst[i][j] != NULL) {
3406                                 rte_pktmbuf_free(gen_pkt_burst[i][j]);
3407                                 gen_pkt_burst[i][j] = NULL;
3408                         }
3409                 }
3410         }
3411
3412         /* Clean up and remove slaves from bonded device */
3413         return remove_slaves_and_stop_bonded_device();
3414 }
3415
3416 static int
3417 test_broadcast_verify_promiscuous_enable_disable(void)
3418 {
3419         int i, promiscuous_en;
3420
3421         /* Initialize bonded device with 4 slaves in round robin mode */
3422         if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 4, 1) != 0)
3423                 return -1;
3424
3425         rte_eth_promiscuous_enable(test_params->bonded_port_id);
3426
3427         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
3428         if (promiscuous_en != 1) {
3429                 printf("Port (%d) promiscuous mode not enabled\n",
3430                                 test_params->bonded_port_id);
3431                 return -1;
3432         }
3433
3434         for (i = 0; i < test_params->bonded_slave_count; i++) {
3435                 promiscuous_en = rte_eth_promiscuous_get(
3436                                 test_params->slave_port_ids[i]);
3437                 if (promiscuous_en != 1) {
3438                         printf("slave port (%d) promiscuous mode not enabled\n",
3439                                         test_params->slave_port_ids[i]);
3440                         return -1;
3441                 }
3442         }
3443
3444         rte_eth_promiscuous_disable(test_params->bonded_port_id);
3445
3446         promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
3447         if (promiscuous_en != 0) {
3448                 printf("Port (%d) promiscuous mode not disabled\n",
3449                                 test_params->bonded_port_id);
3450                 return -1;
3451         }
3452
3453         for (i = 0; i < test_params->bonded_slave_count; i++) {
3454                 promiscuous_en = rte_eth_promiscuous_get(
3455                                 test_params->slave_port_ids[i]);
3456                 if (promiscuous_en != 0) {
3457                         printf("slave port (%d) promiscuous mode not disabled\n",
3458                                         test_params->slave_port_ids[i]);
3459                         return -1;
3460                 }
3461         }
3462
3463         /* Clean up and remove slaves from bonded device */
3464         return remove_slaves_and_stop_bonded_device();
3465 }
3466
3467 static int
3468 test_broadcast_verify_mac_assignment(void)
3469 {
3470         struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1;
3471
3472         int i, retval;
3473
3474         rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0);
3475         rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_1);
3476
3477         /* Initialize bonded device with 4 slaves in round robin mode */
3478         if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 4, 1) != 0)
3479                 return -1;
3480
3481         /* Verify that all MACs are the same as first slave added to bonded
3482          * device */
3483         for (i = 0; i < test_params->bonded_slave_count; i++) {
3484                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
3485                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
3486                                 sizeof(read_mac_addr))) {
3487                         printf("slave port (%d) mac address not set to that of primary port\n",
3488                                         test_params->slave_port_ids[i]);
3489                         return -1;
3490                 }
3491         }
3492
3493         /* change primary and verify that MAC addresses haven't changed */
3494         retval = rte_eth_bond_primary_set(test_params->bonded_port_id,
3495                         test_params->slave_port_ids[2]);
3496         if (retval != 0) {
3497                 printf("Failed to set bonded port (%d) primary port to (%d)\n",
3498                                 test_params->bonded_port_id, test_params->slave_port_ids[i]);
3499                 return -1;
3500         }
3501
3502         for (i = 0; i < test_params->bonded_slave_count; i++) {
3503                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
3504                 if (memcmp(&expected_mac_addr_0, &read_mac_addr,
3505                                 sizeof(read_mac_addr))) {
3506                         printf("slave port (%d) mac address has changed to that of primary"
3507                                         "port without stop/start toggle of bonded device\n",
3508                                         test_params->slave_port_ids[i]);
3509                         return -1;
3510                 }
3511         }
3512
3513         /* stop / start bonded device and verify that primary MAC address is
3514          * propagated to bonded device and slaves */
3515
3516         rte_eth_dev_stop(test_params->bonded_port_id);
3517
3518         if (rte_eth_dev_start(test_params->bonded_port_id) != 0)
3519                 return -1;
3520
3521         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3522         if (memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr))) {
3523                 printf("bonded port (%d) mac address not set to that of new primary"
3524                                 " port\n", test_params->slave_port_ids[i]);
3525                 return -1;
3526         }
3527
3528         for (i = 0; i < test_params->bonded_slave_count; i++) {
3529                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
3530                 if (memcmp(&expected_mac_addr_1, &read_mac_addr,
3531                                 sizeof(read_mac_addr))) {
3532                         printf("slave port (%d) mac address not set to that of new primary"
3533                                         "port\n", test_params->slave_port_ids[i]);
3534                         return -1;
3535                 }
3536         }
3537
3538         /* Set explicit MAC address */
3539         if (rte_eth_bond_mac_address_set(test_params->bonded_port_id,
3540                         (struct ether_addr *)bonded_mac) != 0)
3541                 return -1;
3542
3543         rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr);
3544         if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3545                 printf("bonded port (%d) mac address not set to that of new primary port\n",
3546                                 test_params->slave_port_ids[i]);
3547                 return -1;
3548         }
3549
3550         for (i = 0; i < test_params->bonded_slave_count; i++) {
3551                 rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr);
3552                 if (memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr))) {
3553                         printf("slave port (%d) mac address not set to that of new primary port\n",
3554                                         test_params->slave_port_ids[i]);
3555                         return -1;
3556                 }
3557         }
3558
3559         /* Clean up and remove slaves from bonded device */
3560         return remove_slaves_and_stop_bonded_device();
3561 }
3562
3563 #define BROADCAST_LINK_STATUS_NUM_OF_SLAVES (4)
3564 static int
3565 test_broadcast_verify_slave_link_status_change_behaviour(void)
3566 {
3567         struct rte_mbuf *pkt_burst[BROADCAST_LINK_STATUS_NUM_OF_SLAVES][MAX_PKT_BURST];
3568         struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
3569         struct rte_eth_stats port_stats;
3570
3571         uint8_t slaves[RTE_MAX_ETHPORTS];
3572
3573         int i, j, burst_size, slave_count;
3574
3575         memset(pkt_burst, 0, sizeof(pkt_burst));
3576
3577         /* Initialize bonded device with 4 slaves in round robin mode */
3578         if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST,
3579                         BROADCAST_LINK_STATUS_NUM_OF_SLAVES, 1) != 0)
3580                 return -1;
3581
3582         /* Verify Current Slaves Count /Active Slave Count is */
3583         slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
3584                         RTE_MAX_ETHPORTS);
3585         if (slave_count != 4) {
3586                 printf("Number of slaves (%d) is not as expected (%d).\n",
3587                                 slave_count, 4);
3588                 return -1;
3589         }
3590
3591         slave_count = rte_eth_bond_active_slaves_get(
3592                         test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
3593         if (slave_count != 4) {
3594                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3595                                 slave_count, 4);
3596                 return -1;
3597         }
3598
3599         /* Set 2 slaves link status to down */
3600         virtual_ethdev_simulate_link_status_interrupt(
3601                         test_params->slave_port_ids[1], 0);
3602         virtual_ethdev_simulate_link_status_interrupt(
3603                         test_params->slave_port_ids[3], 0);
3604
3605         slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
3606                         slaves, RTE_MAX_ETHPORTS);
3607         if (slave_count != 2) {
3608                 printf("Number of active slaves (%d) is not as expected (%d).\n",
3609                                 slave_count, 2);
3610                 return -1;
3611         }
3612
3613         for (i = 0; i < test_params->bonded_slave_count; i++)
3614                 rte_eth_stats_reset(test_params->slave_port_ids[i]);
3615
3616         /* Verify that pkts are not sent on slaves with link status down */
3617         burst_size = 21;
3618
3619         if (generate_test_burst(&pkt_burst[0][0], burst_size, 0, 0, 1, 0, 0) !=
3620                         burst_size) {
3621                 printf("generate_test_burst failed\n");
3622                 return -1;
3623         }
3624
3625         if (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0],
3626                         burst_size) != (burst_size * slave_count)) {
3627                 printf("rte_eth_tx_burst failed\n");
3628                 return -1;
3629         }
3630
3631         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3632         if (port_stats.opackets != (uint64_t)(burst_size * slave_count)) {
3633                 printf("(%d) port_stats.opackets (%d) not as expected (%d)\n",
3634                                 test_params->bonded_port_id, (int)port_stats.opackets,
3635                                 burst_size * slave_count);
3636                 return -1;
3637         }
3638
3639         rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
3640         if (port_stats.opackets != (uint64_t)burst_size) {
3641                 printf("(%d) port_stats.opackets not as expected\n",
3642                                 test_params->slave_port_ids[0]);
3643                 return -1;
3644         }
3645
3646         rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
3647         if (port_stats.opackets != 0) {
3648                 printf("(%d) port_stats.opackets not as expected\n",
3649                                 test_params->slave_port_ids[1]);
3650                 return -1;
3651         }
3652
3653         rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
3654         if (port_stats.opackets != (uint64_t)burst_size) {
3655                 printf("(%d) port_stats.opackets not as expected\n",
3656                                 test_params->slave_port_ids[2]);
3657                 return -1;
3658         }
3659
3660         rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
3661         if (port_stats.opackets != 0) {
3662                 printf("(%d) port_stats.opackets not as expected\n",
3663                                 test_params->slave_port_ids[3]);
3664                 return -1;
3665         }
3666
3667         for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) {
3668                 if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 0, 1, 0, 0) !=
3669                                 burst_size) {
3670                         return -1;
3671                 }
3672
3673                 virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
3674                                 &pkt_burst[i][0], burst_size);
3675         }
3676
3677         /* Verify that pkts are not received on slaves with link status down */
3678
3679         if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
3680                         MAX_PKT_BURST) !=
3681                         burst_size + burst_size) {
3682                 printf("rte_eth_rx_burst\n");
3683                 return -1;
3684         }
3685
3686         /* Verify bonded device rx count */
3687         rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
3688         if (port_stats.ipackets != (uint64_t)(burst_size + burst_size)) {
3689                 printf("(%d) port_stats.ipackets not as expected\n",
3690                                 test_params->bonded_port_id);
3691                 return -1;
3692         }
3693
3694         /* free mbufs allocate for rx testing */
3695         for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) {
3696                 for (j = 0; j < MAX_PKT_BURST; j++) {
3697                         if (pkt_burst[i][j] != NULL) {
3698                                 rte_pktmbuf_free(pkt_burst[i][j]);
3699                                 pkt_burst[i][j] = NULL;
3700                         }
3701                 }
3702         }
3703
3704         /* Clean up and remove slaves from bonded device */
3705         return remove_slaves_and_stop_bonded_device();
3706 }
3707
3708 static int
3709 test_reconfigure_bonded_device(void)
3710 {
3711         test_params->nb_rx_q = 4;
3712         test_params->nb_tx_q = 4;
3713
3714         if (configure_ethdev(test_params->bonded_port_id, 0)  != 0) {
3715                 printf("failed to reconfigure bonded device");
3716                 return -1;
3717         }
3718
3719
3720         test_params->nb_rx_q = 2;
3721         test_params->nb_tx_q = 2;
3722
3723         if (configure_ethdev(test_params->bonded_port_id, 0)  != 0) {
3724                 printf("failed to reconfigure bonded device with less rx/tx queues");
3725                 return -1;
3726         }
3727
3728         return 0;
3729 }
3730
3731
3732 static int
3733 test_close_bonded_device(void)
3734 {
3735         rte_eth_dev_close(test_params->bonded_port_id);
3736         return 0;
3737 }
3738
3739 static int
3740 testsuite_teardown(void)
3741 {
3742         if (test_params->pkt_eth_hdr != NULL) {
3743                 free(test_params->pkt_eth_hdr);
3744                 test_params->pkt_eth_hdr = NULL;
3745         }
3746
3747         /* Clean up and remove slaves from bonded device */
3748         return remove_slaves_and_stop_bonded_device();
3749 }
3750
3751
3752 static struct unit_test_suite link_bonding_test_suite  = {
3753         .suite_name = "Link Bonding Unit Test Suite",
3754         .setup = test_setup,
3755         .teardown = testsuite_teardown,
3756         .unit_test_cases = {
3757                 TEST_CASE(test_create_bonded_device),
3758                 TEST_CASE(test_create_bonded_device_with_invalid_params),
3759                 TEST_CASE(test_add_slave_to_bonded_device),
3760                 TEST_CASE(test_add_slave_to_invalid_bonded_device),
3761                 TEST_CASE(test_remove_slave_from_bonded_device),
3762                 TEST_CASE(test_remove_slave_from_invalid_bonded_device),
3763                 TEST_CASE(test_get_slaves_from_bonded_device),
3764                 TEST_CASE(test_add_already_bonded_slave_to_bonded_device),
3765                 TEST_CASE(test_add_remove_multiple_slaves_to_from_bonded_device),
3766                 TEST_CASE(test_start_bonded_device),
3767                 TEST_CASE(test_stop_bonded_device),
3768                 TEST_CASE(test_set_bonding_mode),
3769                 TEST_CASE(test_set_primary_slave),
3770                 TEST_CASE(test_set_explicit_bonded_mac),
3771                 TEST_CASE(test_adding_slave_after_bonded_device_started),
3772                 TEST_CASE(test_roundrobin_tx_burst),
3773                 TEST_CASE(test_roundrobin_rx_burst_on_single_slave),
3774                 TEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves),
3775                 TEST_CASE(test_roundrobin_verify_promiscuous_enable_disable),
3776                 TEST_CASE(test_roundrobin_verify_mac_assignment),
3777                 TEST_CASE(test_roundrobin_verify_slave_link_status_change_behaviour),
3778                 TEST_CASE(test_activebackup_tx_burst),
3779                 TEST_CASE(test_activebackup_rx_burst),
3780                 TEST_CASE(test_activebackup_verify_promiscuous_enable_disable),
3781                 TEST_CASE(test_activebackup_verify_mac_assignment),
3782                 TEST_CASE(test_activebackup_verify_slave_link_status_change_failover),
3783                 TEST_CASE(test_balance_xmit_policy_configuration),
3784                 TEST_CASE(test_balance_l2_tx_burst),
3785                 TEST_CASE(test_balance_l23_tx_burst_ipv4_toggle_ip_addr),
3786                 TEST_CASE(test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr),
3787                 TEST_CASE(test_balance_l23_tx_burst_ipv6_toggle_ip_addr),
3788                 TEST_CASE(test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr),
3789                 TEST_CASE(test_balance_l23_tx_burst_toggle_mac_addr),
3790                 TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_ip_addr),
3791                 TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_udp_port),
3792                 TEST_CASE(test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr),
3793                 TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr),
3794                 TEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr),
3795                 TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port),
3796                 TEST_CASE(test_balance_rx_burst),
3797                 TEST_CASE(test_balance_verify_promiscuous_enable_disable),
3798                 TEST_CASE(test_balance_verify_mac_assignment),
3799                 TEST_CASE(test_balance_verify_slave_link_status_change_behaviour),
3800                 TEST_CASE(test_broadcast_tx_burst),
3801                 TEST_CASE(test_broadcast_rx_burst),
3802                 TEST_CASE(test_broadcast_verify_promiscuous_enable_disable),
3803                 TEST_CASE(test_broadcast_verify_mac_assignment),
3804                 TEST_CASE(test_broadcast_verify_slave_link_status_change_behaviour),
3805                 TEST_CASE(test_reconfigure_bonded_device),
3806                 TEST_CASE(test_close_bonded_device),
3807
3808                 { NULL, NULL, NULL, NULL, NULL } /**< NULL terminate unit test array */
3809         }
3810 };
3811
3812
3813 static int
3814 test_link_bonding(void)
3815 {
3816         return unit_test_suite_runner(&link_bonding_test_suite);
3817 }
3818
3819 static struct test_command link_bonding_cmd = {
3820         .command = "link_bonding_autotest",
3821         .callback = test_link_bonding,
3822 };
3823 REGISTER_TEST_COMMAND(link_bonding_cmd);