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