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