4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
41 #include <rte_cycles.h>
42 #include <sys/queue.h>
44 #include <rte_byteorder.h>
45 #include <rte_common.h>
46 #include <rte_debug.h>
47 #include <rte_ethdev.h>
49 #include <rte_lcore.h>
50 #include <rte_memory.h>
52 #include <rte_string_fns.h>
54 #include <rte_eth_ring.h>
55 #include <rte_errno.h>
56 #include <rte_eth_bond.h>
57 #include <rte_eth_bond_8023ad.h>
59 #include "packet_burst_generator.h"
63 #define SLAVE_COUNT (4)
65 #define RX_RING_SIZE 128
66 #define TX_RING_SIZE 512
68 #define MBUF_CACHE_SIZE (250)
69 #define BURST_SIZE (32)
71 #define TEST_RX_DESC_MAX (2048)
72 #define TEST_TX_DESC_MAX (2048)
73 #define MAX_PKT_BURST (32)
74 #define DEF_PKT_BURST (16)
76 #define BONDED_DEV_NAME ("unit_test_mode4_bond_dev")
78 #define SLAVE_DEV_NAME_FMT ("unit_test_mode4_slave_%d")
79 #define SLAVE_RX_QUEUE_FMT ("unit_test_mode4_slave_%d_rx")
80 #define SLAVE_TX_QUEUE_FMT ("unit_test_mode4_slave_%d_tx")
82 #define INVALID_SOCKET_ID (-1)
83 #define INVALID_PORT_ID (0xFF)
84 #define INVALID_BONDING_MODE (-1)
86 static const struct ether_addr slave_mac_default
= {
87 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 }
90 static const struct ether_addr parnter_mac_default
= {
91 { 0x22, 0xBB, 0xFF, 0xBB, 0x00, 0x00 }
94 static const struct ether_addr parnter_system
= {
95 { 0x33, 0xFF, 0xBB, 0xFF, 0x00, 0x00 }
98 static const struct ether_addr slow_protocol_mac_addr
= {
99 { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
103 struct rte_ring
*rx_queue
;
104 struct rte_ring
*tx_queue
;
108 uint8_t lacp_parnter_state
;
111 struct ether_vlan_hdr
{
112 struct ether_hdr pkt_eth_hdr
;
113 struct vlan_hdr vlan_hdr
;
116 struct link_bonding_unittest_params
{
117 uint8_t bonded_port_id
;
118 struct slave_conf slave_ports
[SLAVE_COUNT
];
120 struct rte_mempool
*mbuf_pool
;
123 #define TEST_DEFAULT_SLAVE_COUNT RTE_DIM(test_params.slave_ports)
124 #define TEST_RX_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT
125 #define TEST_TX_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
126 #define TEST_MARKER_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT
127 #define TEST_EXPIRED_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
128 #define TEST_PROMISC_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
130 static struct link_bonding_unittest_params test_params
= {
131 .bonded_port_id
= INVALID_PORT_ID
,
132 .slave_ports
= { [0 ... SLAVE_COUNT
- 1] = { .port_id
= INVALID_PORT_ID
} },
137 static struct rte_eth_conf default_pmd_conf
= {
139 .mq_mode
= ETH_MQ_RX_NONE
,
140 .max_rx_pkt_len
= ETHER_MAX_LEN
,
142 .header_split
= 0, /**< Header Split disabled */
143 .hw_ip_checksum
= 0, /**< IP checksum offload enabled */
144 .hw_vlan_filter
= 0, /**< VLAN filtering disabled */
145 .jumbo_frame
= 0, /**< Jumbo Frame Support disabled */
146 .hw_strip_crc
= 1, /**< CRC stripped by hardware */
149 .mq_mode
= ETH_MQ_TX_NONE
,
154 static uint8_t lacpdu_rx_count
[RTE_MAX_ETHPORTS
] = {0, };
156 #define FOR_EACH(_i, _item, _array, _size) \
157 for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
159 /* Macro for iterating over every port that can be used as a slave
161 * _i variable used as an index in test_params->slave_ports
162 * _slave pointer to &test_params->slave_ports[_idx]
164 #define FOR_EACH_PORT(_i, _port) \
165 FOR_EACH(_i, _port, test_params.slave_ports, \
166 RTE_DIM(test_params.slave_ports))
168 /* Macro for iterating over every port that can be used as a slave
169 * in this test and satisfy given condition.
171 * _i variable used as an index in test_params->slave_ports
172 * _slave pointer to &test_params->slave_ports[_idx]
173 * _condition condition that need to be checked
175 #define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \
178 /* Macro for iterating over every port that is currently a slave of a bonded
180 * _i variable used as an index in test_params->slave_ports
181 * _slave pointer to &test_params->slave_ports[_idx]
183 #define FOR_EACH_SLAVE(_i, _slave) \
184 FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0)
187 * Returns packets from slaves TX queue.
190 * size size of buffer
191 * return number of packets or negative error number
194 slave_get_pkts(struct slave_conf
*slave
, struct rte_mbuf
**buf
, uint16_t size
)
196 return rte_ring_dequeue_burst(slave
->tx_queue
, (void **)buf
,
201 * Injects given packets into slaves RX queue.
204 * size number of packets to be injected
205 * return number of queued packets or negative error number
208 slave_put_pkts(struct slave_conf
*slave
, struct rte_mbuf
**buf
, uint16_t size
)
210 return rte_ring_enqueue_burst(slave
->rx_queue
, (void **)buf
,
215 bond_rx(struct rte_mbuf
**buf
, uint16_t size
)
217 return rte_eth_rx_burst(test_params
.bonded_port_id
, 0, buf
, size
);
221 bond_tx(struct rte_mbuf
**buf
, uint16_t size
)
223 return rte_eth_tx_burst(test_params
.bonded_port_id
, 0, buf
, size
);
227 free_pkts(struct rte_mbuf
**pkts
, uint16_t count
)
231 for (i
= 0; i
< count
; i
++) {
233 rte_pktmbuf_free(pkts
[i
]);
238 configure_ethdev(uint8_t port_id
, uint8_t start
)
240 TEST_ASSERT(rte_eth_dev_configure(port_id
, 1, 1, &default_pmd_conf
) == 0,
241 "Failed to configure device %u", port_id
);
243 TEST_ASSERT(rte_eth_rx_queue_setup(port_id
, 0, RX_RING_SIZE
,
244 rte_eth_dev_socket_id(port_id
), NULL
, test_params
.mbuf_pool
) == 0,
245 "Failed to setup rx queue.");
247 TEST_ASSERT(rte_eth_tx_queue_setup(port_id
, 0, TX_RING_SIZE
,
248 rte_eth_dev_socket_id(port_id
), NULL
) == 0,
249 "Failed to setup tx queue.");
252 TEST_ASSERT(rte_eth_dev_start(port_id
) == 0,
253 "Failed to start device (%d).", port_id
);
259 add_slave(struct slave_conf
*slave
, uint8_t start
)
261 struct ether_addr addr
, addr_check
;
263 /* Some sanity check */
264 RTE_VERIFY(test_params
.slave_ports
<= slave
&&
265 slave
- test_params
.slave_ports
< (int)RTE_DIM(test_params
.slave_ports
));
266 RTE_VERIFY(slave
->bonded
== 0);
267 RTE_VERIFY(slave
->port_id
!= INVALID_PORT_ID
);
269 ether_addr_copy(&slave_mac_default
, &addr
);
270 addr
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
272 rte_eth_dev_mac_addr_remove(slave
->port_id
, &addr
);
274 TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave
->port_id
, &addr
, 0),
275 "Failed to set slave MAC address");
277 TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params
.bonded_port_id
,
279 "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)",
280 (uint8_t)(slave
- test_params
.slave_ports
), slave
->port_id
,
281 test_params
.bonded_port_id
);
285 TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave
->port_id
),
286 "Failed to start slave %u", slave
->port_id
);
289 rte_eth_macaddr_get(slave
->port_id
, &addr_check
);
290 TEST_ASSERT_EQUAL(is_same_ether_addr(&addr
, &addr_check
), 1,
291 "Slave MAC address is not as expected");
293 RTE_VERIFY(slave
->lacp_parnter_state
== 0);
298 remove_slave(struct slave_conf
*slave
)
300 ptrdiff_t slave_idx
= slave
- test_params
.slave_ports
;
302 RTE_VERIFY(test_params
.slave_ports
<= slave
&&
303 slave_idx
< (ptrdiff_t)RTE_DIM(test_params
.slave_ports
));
305 RTE_VERIFY(slave
->bonded
== 1);
306 RTE_VERIFY(slave
->port_id
!= INVALID_PORT_ID
);
308 TEST_ASSERT_EQUAL(rte_ring_count(slave
->rx_queue
), 0,
309 "Slave %u tx queue not empty while removing from bonding.",
312 TEST_ASSERT_EQUAL(rte_ring_count(slave
->rx_queue
), 0,
313 "Slave %u tx queue not empty while removing from bonding.",
316 TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params
.bonded_port_id
,
318 "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)",
319 (uint8_t)slave_idx
, slave
->port_id
,
320 test_params
.bonded_port_id
);
323 slave
->lacp_parnter_state
= 0;
328 lacp_recv_cb(uint8_t slave_id
, struct rte_mbuf
*lacp_pkt
)
330 struct ether_hdr
*hdr
;
331 struct slow_protocol_frame
*slow_hdr
;
333 RTE_VERIFY(lacp_pkt
!= NULL
);
335 hdr
= rte_pktmbuf_mtod(lacp_pkt
, struct ether_hdr
*);
336 RTE_VERIFY(hdr
->ether_type
== rte_cpu_to_be_16(ETHER_TYPE_SLOW
));
338 slow_hdr
= rte_pktmbuf_mtod(lacp_pkt
, struct slow_protocol_frame
*);
339 RTE_VERIFY(slow_hdr
->slow_protocol
.subtype
== SLOW_SUBTYPE_LACP
);
341 lacpdu_rx_count
[slave_id
]++;
342 rte_pktmbuf_free(lacp_pkt
);
346 initialize_bonded_device_with_slaves(uint8_t slave_count
, uint8_t external_sm
)
350 RTE_VERIFY(test_params
.bonded_port_id
!= INVALID_PORT_ID
);
352 for (i
= 0; i
< slave_count
; i
++) {
353 TEST_ASSERT_SUCCESS(add_slave(&test_params
.slave_ports
[i
], 1),
354 "Failed to add port %u to bonded device.\n",
355 test_params
.slave_ports
[i
].port_id
);
358 /* Reset mode 4 configuration */
359 rte_eth_bond_8023ad_setup(test_params
.bonded_port_id
, NULL
);
360 rte_eth_promiscuous_disable(test_params
.bonded_port_id
);
363 struct rte_eth_bond_8023ad_conf conf
;
365 rte_eth_bond_8023ad_conf_get(test_params
.bonded_port_id
, &conf
);
366 conf
.slowrx_cb
= lacp_recv_cb
;
367 rte_eth_bond_8023ad_setup(test_params
.bonded_port_id
, &conf
);
371 TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params
.bonded_port_id
),
372 "Failed to start bonded device");
378 remove_slaves_and_stop_bonded_device(void)
380 struct slave_conf
*slave
;
382 uint8_t slaves
[RTE_MAX_ETHPORTS
];
385 rte_eth_dev_stop(test_params
.bonded_port_id
);
387 FOR_EACH_SLAVE(i
, slave
)
390 retval
= rte_eth_bond_slaves_get(test_params
.bonded_port_id
, slaves
,
393 TEST_ASSERT_EQUAL(retval
, 0,
394 "Expected bonded device %u have 0 slaves but returned %d.",
395 test_params
.bonded_port_id
, retval
);
397 FOR_EACH_PORT(i
, slave
) {
398 rte_eth_dev_stop(slave
->port_id
);
400 TEST_ASSERT(slave
->bonded
== 0,
401 "Port id=%u is still marked as enslaved.", slave
->port_id
);
410 int retval
, nb_mbuf_per_pool
;
411 char name
[RTE_ETH_NAME_MAX_LEN
];
412 struct slave_conf
*port
;
413 const uint8_t socket_id
= rte_socket_id();
416 if (test_params
.mbuf_pool
== NULL
) {
417 nb_mbuf_per_pool
= TEST_RX_DESC_MAX
+ DEF_PKT_BURST
+
418 TEST_TX_DESC_MAX
+ MAX_PKT_BURST
;
419 test_params
.mbuf_pool
= rte_pktmbuf_pool_create("TEST_MODE4",
420 nb_mbuf_per_pool
, MBUF_CACHE_SIZE
, 0,
421 RTE_MBUF_DEFAULT_BUF_SIZE
, socket_id
);
423 TEST_ASSERT(test_params
.mbuf_pool
!= NULL
,
424 "rte_mempool_create failed\n");
427 /* Create / initialize ring eth devs. */
428 FOR_EACH_PORT(i
, port
) {
429 port
= &test_params
.slave_ports
[i
];
431 if (port
->rx_queue
== NULL
) {
432 retval
= snprintf(name
, RTE_DIM(name
), SLAVE_RX_QUEUE_FMT
, i
);
433 TEST_ASSERT(retval
<= (int)RTE_DIM(name
) - 1, "Name too long");
434 port
->rx_queue
= rte_ring_create(name
, RX_RING_SIZE
, socket_id
, 0);
435 TEST_ASSERT(port
->rx_queue
!= NULL
,
436 "Failed to allocate rx ring '%s': %s", name
,
437 rte_strerror(rte_errno
));
440 if (port
->tx_queue
== NULL
) {
441 retval
= snprintf(name
, RTE_DIM(name
), SLAVE_TX_QUEUE_FMT
, i
);
442 TEST_ASSERT(retval
<= (int)RTE_DIM(name
) - 1, "Name too long");
443 port
->tx_queue
= rte_ring_create(name
, TX_RING_SIZE
, socket_id
, 0);
444 TEST_ASSERT_NOT_NULL(port
->tx_queue
,
445 "Failed to allocate tx ring '%s': %s", name
,
446 rte_strerror(rte_errno
));
449 if (port
->port_id
== INVALID_PORT_ID
) {
450 retval
= snprintf(name
, RTE_DIM(name
), SLAVE_DEV_NAME_FMT
, i
);
451 TEST_ASSERT(retval
< (int)RTE_DIM(name
) - 1, "Name too long");
452 retval
= rte_eth_from_rings(name
, &port
->rx_queue
, 1,
453 &port
->tx_queue
, 1, socket_id
);
454 TEST_ASSERT(retval
>= 0,
455 "Failed to create ring ethdev '%s'\n", name
);
457 port
->port_id
= rte_eth_dev_count() - 1;
460 retval
= configure_ethdev(port
->port_id
, 1);
461 TEST_ASSERT_SUCCESS(retval
, "Failed to configure virtual ethdev %s\n",
465 if (test_params
.bonded_port_id
== INVALID_PORT_ID
) {
466 retval
= rte_eth_bond_create(BONDED_DEV_NAME
, BONDING_MODE_8023AD
,
469 TEST_ASSERT(retval
>= 0, "Failed to create bonded ethdev %s",
472 test_params
.bonded_port_id
= retval
;
473 TEST_ASSERT_SUCCESS(configure_ethdev(test_params
.bonded_port_id
, 0),
474 "Failed to configure bonded ethdev %s", BONDED_DEV_NAME
);
475 } else if (rte_eth_bond_mode_get(test_params
.bonded_port_id
) !=
476 BONDING_MODE_8023AD
) {
477 TEST_ASSERT(rte_eth_bond_mode_set(test_params
.bonded_port_id
,
478 BONDING_MODE_8023AD
) == 0,
479 "Failed to set ethdev %d to mode %d",
480 test_params
.bonded_port_id
, BONDING_MODE_8023AD
);
487 testsuite_teardown(void)
489 struct slave_conf
*port
;
493 * Any cleanup/reset state is done when particular test is
496 rte_eth_dev_stop(test_params
.bonded_port_id
);
498 FOR_EACH_PORT(i
, port
)
499 rte_eth_dev_stop(port
->port_id
);
503 * Check if given LACP packet. If it is, make make replay packet to force
505 * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow
509 make_lacp_reply(struct slave_conf
*slave
, struct rte_mbuf
*pkt
)
511 struct ether_hdr
*hdr
;
512 struct slow_protocol_frame
*slow_hdr
;
516 hdr
= rte_pktmbuf_mtod(pkt
, struct ether_hdr
*);
517 if (hdr
->ether_type
!= rte_cpu_to_be_16(ETHER_TYPE_SLOW
))
520 slow_hdr
= rte_pktmbuf_mtod(pkt
, struct slow_protocol_frame
*);
521 /* ignore packets of other types */
522 if (slow_hdr
->slow_protocol
.subtype
!= SLOW_SUBTYPE_LACP
)
525 slow_hdr
= rte_pktmbuf_mtod(pkt
, struct slow_protocol_frame
*);
527 /* Change source address to partner address */
528 ether_addr_copy(&parnter_mac_default
, &slow_hdr
->eth_hdr
.s_addr
);
529 slow_hdr
->eth_hdr
.s_addr
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
531 lacp
= (struct lacpdu
*) &slow_hdr
->slow_protocol
;
532 /* Save last received state */
533 slave
->lacp_parnter_state
= lacp
->actor
.state
;
534 /* Change it into LACP replay by matching parameters. */
535 memcpy(&lacp
->partner
.port_params
, &lacp
->actor
.port_params
,
536 sizeof(struct port_params
));
538 lacp
->partner
.state
= lacp
->actor
.state
;
540 ether_addr_copy(&parnter_system
, &lacp
->actor
.port_params
.system
);
541 lacp
->actor
.state
= STATE_LACP_ACTIVE
|
542 STATE_SYNCHRONIZATION
|
551 * Reads packets from given slave, search for LACP packet and reply them.
553 * Receives burst of packets from slave. Looks for LACP packet. Drops
554 * all other packets. Prepares response LACP and sends it back.
556 * return number of LACP received and replied, -1 on error.
559 bond_handshake_reply(struct slave_conf
*slave
)
562 struct rte_mbuf
*rx_buf
[MAX_PKT_BURST
];
563 struct rte_mbuf
*lacp_tx_buf
[MAX_PKT_BURST
];
564 uint16_t lacp_tx_buf_cnt
= 0, i
;
566 retval
= slave_get_pkts(slave
, rx_buf
, RTE_DIM(rx_buf
));
567 TEST_ASSERT(retval
>= 0, "Getting slave %u packets failed.",
570 for (i
= 0; i
< (uint16_t)retval
; i
++) {
571 if (make_lacp_reply(slave
, rx_buf
[i
]) == 0) {
572 /* reply with actor's LACP */
573 lacp_tx_buf
[lacp_tx_buf_cnt
++] = rx_buf
[i
];
575 rte_pktmbuf_free(rx_buf
[i
]);
578 if (lacp_tx_buf_cnt
== 0)
581 retval
= slave_put_pkts(slave
, lacp_tx_buf
, lacp_tx_buf_cnt
);
582 if (retval
<= lacp_tx_buf_cnt
) {
583 /* retval might be negative */
584 for (i
= RTE_MAX(0, retval
); retval
< lacp_tx_buf_cnt
; retval
++)
585 rte_pktmbuf_free(lacp_tx_buf
[i
]);
588 TEST_ASSERT_EQUAL(retval
, lacp_tx_buf_cnt
,
589 "Failed to equeue lacp packets into slave %u tx queue.",
592 return lacp_tx_buf_cnt
;
596 * Function check if given slave tx queue contains packets that make mode 4
597 * handshake complete. It will drain slave queue.
598 * return 0 if handshake not completed, 1 if handshake was complete,
601 bond_handshake_done(struct slave_conf
*slave
)
603 const uint8_t expected_state
= STATE_LACP_ACTIVE
| STATE_SYNCHRONIZATION
|
604 STATE_AGGREGATION
| STATE_COLLECTING
| STATE_DISTRIBUTING
;
606 return slave
->lacp_parnter_state
== expected_state
;
610 bond_get_update_timeout_ms(void)
612 struct rte_eth_bond_8023ad_conf conf
;
614 rte_eth_bond_8023ad_conf_get(test_params
.bonded_port_id
, &conf
);
615 return conf
.update_timeout_ms
;
619 * Exchanges LACP packets with partner to achieve dynamic port configuration.
620 * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise.
625 struct slave_conf
*slave
;
626 struct rte_mbuf
*buf
[MAX_PKT_BURST
];
628 uint8_t all_slaves_done
, i
, j
;
629 uint8_t status
[RTE_DIM(test_params
.slave_ports
)] = { 0 };
630 const unsigned delay
= bond_get_update_timeout_ms();
632 /* Exchange LACP frames */
634 for (i
= 0; i
< 30 && all_slaves_done
== 0; ++i
) {
638 FOR_EACH_SLAVE(j
, slave
) {
639 /* If response already send, skip slave */
643 if (bond_handshake_reply(slave
) < 0) {
648 status
[j
] = bond_handshake_done(slave
);
653 nb_pkts
= bond_tx(NULL
, 0);
654 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets transmitted unexpectedly");
656 nb_pkts
= bond_rx(buf
, RTE_DIM(buf
));
657 free_pkts(buf
, nb_pkts
);
658 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets received unexpectedly");
660 /* If response didn't send - report failure */
661 TEST_ASSERT_EQUAL(all_slaves_done
, 1, "Bond handshake failed\n");
663 /* If flags doesn't match - report failure */
664 return all_slaves_done
= 1 ? TEST_SUCCESS
: TEST_FAILED
;
667 #define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports)
669 test_mode4_lacp(void)
673 retval
= initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT
, 0);
674 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
676 /* Test LACP handshake function */
677 retval
= bond_handshake();
678 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
680 retval
= remove_slaves_and_stop_bonded_device();
681 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
687 generate_packets(struct ether_addr
*src_mac
,
688 struct ether_addr
*dst_mac
, uint16_t count
, struct rte_mbuf
**buf
)
690 uint16_t pktlen
= PACKET_BURST_GEN_PKT_LEN
;
691 uint8_t vlan_enable
= 0;
692 uint16_t vlan_id
= 0;
693 uint8_t ip4_type
= 1; /* 0 - ipv6 */
695 uint16_t src_port
= 10, dst_port
= 20;
697 uint32_t ip_src
[4] = { [0 ... 2] = 0xDEADBEEF, [3] = IPv4(192, 168, 0, 1) };
698 uint32_t ip_dst
[4] = { [0 ... 2] = 0xFEEDFACE, [3] = IPv4(192, 168, 0, 2) };
700 struct ether_hdr pkt_eth_hdr
;
701 struct udp_hdr pkt_udp_hdr
;
709 initialize_eth_header(&pkt_eth_hdr
, src_mac
, dst_mac
, ip4_type
,
710 vlan_enable
, vlan_id
);
713 initialize_ipv4_header(&pkt_ip_hdr
.v4
, ip_src
[3], ip_dst
[3], pktlen
);
715 initialize_ipv6_header(&pkt_ip_hdr
.v6
, (uint8_t *)ip_src
,
716 (uint8_t *)&ip_dst
, pktlen
);
718 initialize_udp_header(&pkt_udp_hdr
, src_port
, dst_port
, 16);
720 retval
= generate_packet_burst(test_params
.mbuf_pool
, buf
,
721 &pkt_eth_hdr
, vlan_enable
, &pkt_ip_hdr
, 1, &pkt_udp_hdr
,
724 if (retval
> 0 && retval
!= count
)
725 free_pkts(&buf
[count
- retval
], retval
);
727 TEST_ASSERT_EQUAL(retval
, count
, "Failed to generate %u packets",
734 generate_and_put_packets(struct slave_conf
*slave
, struct ether_addr
*src_mac
,
735 struct ether_addr
*dst_mac
, uint16_t count
)
737 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
740 retval
= generate_packets(src_mac
, dst_mac
, count
, pkts
);
741 if (retval
!= (int)count
)
744 retval
= slave_put_pkts(slave
, pkts
, count
);
745 if (retval
> 0 && retval
!= count
)
746 free_pkts(&pkts
[retval
], count
- retval
);
748 TEST_ASSERT_EQUAL(retval
, count
,
749 "Failed to enqueue packets into slave %u RX queue", slave
->port_id
);
757 struct slave_conf
*slave
;
760 uint16_t expected_pkts_cnt
;
761 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
765 struct ether_hdr
*hdr
;
767 struct ether_addr src_mac
= { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
768 struct ether_addr dst_mac
;
769 struct ether_addr bonded_mac
;
771 retval
= initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT
,
773 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
775 retval
= bond_handshake();
776 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
778 rte_eth_macaddr_get(test_params
.bonded_port_id
, &bonded_mac
);
779 ether_addr_copy(&bonded_mac
, &dst_mac
);
781 /* Assert that dst address is not bonding address. Do not set the
782 * least significant bit of the zero byte as this would create a
785 dst_mac
.addr_bytes
[0] += 2;
787 /* First try with promiscuous mode enabled.
788 * Add 2 packets to each slave. First with bonding MAC address, second with
789 * different. Check if we received all of them. */
790 rte_eth_promiscuous_enable(test_params
.bonded_port_id
);
792 expected_pkts_cnt
= 0;
793 FOR_EACH_SLAVE(i
, slave
) {
794 retval
= generate_and_put_packets(slave
, &src_mac
, &bonded_mac
, 1);
795 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
798 retval
= generate_and_put_packets(slave
, &src_mac
, &dst_mac
, 1);
799 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
802 /* Expect 2 packets per slave */
803 expected_pkts_cnt
+= 2;
806 retval
= rte_eth_rx_burst(test_params
.bonded_port_id
, 0, pkts
,
809 if (retval
== expected_pkts_cnt
) {
810 int cnt
[2] = { 0, 0 };
812 for (i
= 0; i
< expected_pkts_cnt
; i
++) {
813 hdr
= rte_pktmbuf_mtod(pkts
[i
], struct ether_hdr
*);
814 cnt
[is_same_ether_addr(&hdr
->d_addr
, &bonded_mac
)]++;
817 free_pkts(pkts
, expected_pkts_cnt
);
819 /* For division by 2 expected_pkts_cnt must be even */
820 RTE_VERIFY((expected_pkts_cnt
& 1) == 0);
821 TEST_ASSERT(cnt
[0] == expected_pkts_cnt
/ 2 &&
822 cnt
[1] == expected_pkts_cnt
/ 2,
823 "Expected %u packets with the same MAC and %u with different but "
824 "got %u with the same and %u with diffrent MAC",
825 expected_pkts_cnt
/ 2, expected_pkts_cnt
/ 2, cnt
[1], cnt
[0]);
826 } else if (retval
> 0)
827 free_pkts(pkts
, retval
);
829 TEST_ASSERT_EQUAL(retval
, expected_pkts_cnt
,
830 "Expected %u packets but received only %d", expected_pkts_cnt
, retval
);
832 /* Now, disable promiscuous mode. When promiscuous mode is disabled we
833 * expect to receive only packets that are directed to bonding port. */
834 rte_eth_promiscuous_disable(test_params
.bonded_port_id
);
836 expected_pkts_cnt
= 0;
837 FOR_EACH_SLAVE(i
, slave
) {
838 retval
= generate_and_put_packets(slave
, &src_mac
, &bonded_mac
, 1);
839 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
842 retval
= generate_and_put_packets(slave
, &src_mac
, &dst_mac
, 1);
843 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
846 /* Expect only one packet per slave */
847 expected_pkts_cnt
+= 1;
850 retval
= rte_eth_rx_burst(test_params
.bonded_port_id
, 0, pkts
,
853 if (retval
== expected_pkts_cnt
) {
856 for (i
= 0; i
< expected_pkts_cnt
; i
++) {
857 hdr
= rte_pktmbuf_mtod(pkts
[i
], struct ether_hdr
*);
858 eq_cnt
+= is_same_ether_addr(&hdr
->d_addr
, &bonded_mac
);
861 free_pkts(pkts
, expected_pkts_cnt
);
862 TEST_ASSERT_EQUAL(eq_cnt
, expected_pkts_cnt
, "Packet address mismatch");
863 } else if (retval
> 0)
864 free_pkts(pkts
, retval
);
866 TEST_ASSERT_EQUAL(retval
, expected_pkts_cnt
,
867 "Expected %u packets but received only %d", expected_pkts_cnt
, retval
);
869 /* Link down test: simulate link down for first slave. */
870 delay
= bond_get_update_timeout_ms();
872 uint8_t slave_down_id
= INVALID_PORT_ID
;
874 /* Find first slave and make link down on it*/
875 FOR_EACH_SLAVE(i
, slave
) {
876 rte_eth_dev_set_link_down(slave
->port_id
);
877 slave_down_id
= slave
->port_id
;
881 RTE_VERIFY(slave_down_id
!= INVALID_PORT_ID
);
883 /* Give some time to rearrange bonding */
884 for (i
= 0; i
< 3; i
++) {
889 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
891 /* Put packet to each slave */
892 FOR_EACH_SLAVE(i
, slave
) {
895 dst_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
896 retval
= generate_and_put_packets(slave
, &src_mac
, &dst_mac
, 1);
897 TEST_ASSERT_SUCCESS(retval
, "Failed to generate test packet burst.");
899 src_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
900 retval
= generate_and_put_packets(slave
, &src_mac
, &bonded_mac
, 1);
901 TEST_ASSERT_SUCCESS(retval
, "Failed to generate test packet burst.");
903 retval
= bond_rx(pkts
, RTE_DIM(pkts
));
907 free_pkts(pkts
, retval
);
909 while (rte_ring_dequeue(slave
->rx_queue
, (void **)&pkt
) == 0)
910 rte_pktmbuf_free(pkt
);
912 if (slave_down_id
== slave
->port_id
)
913 TEST_ASSERT_EQUAL(retval
, 0, "Packets received unexpectedly.");
915 TEST_ASSERT_NOT_EQUAL(retval
, 0,
916 "Expected to receive some packets on slave %u.",
918 rte_eth_dev_start(slave
->port_id
);
920 for (j
= 0; j
< 5; j
++) {
921 TEST_ASSERT(bond_handshake_reply(slave
) >= 0,
922 "Handshake after link up");
924 if (bond_handshake_done(slave
) == 1)
928 TEST_ASSERT(j
< 5, "Failed to agregate slave after link up");
931 remove_slaves_and_stop_bonded_device();
936 test_mode4_tx_burst(void)
938 struct slave_conf
*slave
;
941 uint16_t exp_pkts_cnt
, pkts_cnt
= 0;
942 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
946 struct ether_addr dst_mac
= { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
947 struct ether_addr bonded_mac
;
949 retval
= initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT
, 0);
950 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
952 retval
= bond_handshake();
953 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
955 rte_eth_macaddr_get(test_params
.bonded_port_id
, &bonded_mac
);
958 for (pkts_cnt
= 0; pkts_cnt
< RTE_DIM(pkts
); pkts_cnt
++) {
959 dst_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = pkts_cnt
;
960 retval
= generate_packets(&bonded_mac
, &dst_mac
, 1, &pkts
[pkts_cnt
]);
963 free_pkts(pkts
, pkts_cnt
);
965 TEST_ASSERT_EQUAL(retval
, 1, "Failed to generate packet %u", pkts_cnt
);
967 exp_pkts_cnt
= pkts_cnt
;
969 /* Transmit packets on bonded device */
970 retval
= bond_tx(pkts
, pkts_cnt
);
971 if (retval
> 0 && retval
< pkts_cnt
)
972 free_pkts(&pkts
[retval
], pkts_cnt
- retval
);
974 TEST_ASSERT_EQUAL(retval
, pkts_cnt
, "TX on bonded device failed");
976 /* Check if packets were transmitted properly. Every slave should have
977 * at least one packet, and sum must match. Under normal operation
978 * there should be no LACP nor MARKER frames. */
980 FOR_EACH_SLAVE(i
, slave
) {
981 uint16_t normal_cnt
, slow_cnt
;
983 retval
= slave_get_pkts(slave
, pkts
, RTE_DIM(pkts
));
987 for (j
= 0; j
< retval
; j
++) {
988 if (make_lacp_reply(slave
, pkts
[j
]) == 1)
994 free_pkts(pkts
, normal_cnt
+ slow_cnt
);
995 TEST_ASSERT_EQUAL(slow_cnt
, 0,
996 "slave %u unexpectedly transmitted %d SLOW packets", slave
->port_id
,
999 TEST_ASSERT_NOT_EQUAL(normal_cnt
, 0,
1000 "slave %u did not transmitted any packets", slave
->port_id
);
1002 pkts_cnt
+= normal_cnt
;
1005 TEST_ASSERT_EQUAL(exp_pkts_cnt
, pkts_cnt
,
1006 "Expected %u packets but transmitted only %d", exp_pkts_cnt
, pkts_cnt
);
1009 * simulate link down for first slave. */
1010 delay
= bond_get_update_timeout_ms();
1012 uint8_t slave_down_id
= INVALID_PORT_ID
;
1014 FOR_EACH_SLAVE(i
, slave
) {
1015 rte_eth_dev_set_link_down(slave
->port_id
);
1016 slave_down_id
= slave
->port_id
;
1020 RTE_VERIFY(slave_down_id
!= INVALID_PORT_ID
);
1022 /* Give some time to rearrange bonding. */
1023 for (i
= 0; i
< 3; i
++) {
1025 rte_delay_ms(delay
);
1028 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
1030 /* Prepare burst. */
1031 for (pkts_cnt
= 0; pkts_cnt
< RTE_DIM(pkts
); pkts_cnt
++) {
1032 dst_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = pkts_cnt
;
1033 retval
= generate_packets(&bonded_mac
, &dst_mac
, 1, &pkts
[pkts_cnt
]);
1036 free_pkts(pkts
, pkts_cnt
);
1038 TEST_ASSERT_EQUAL(retval
, 1, "Failed to generate test packet %u",
1041 exp_pkts_cnt
= pkts_cnt
;
1043 /* Transmit packets on bonded device. */
1044 retval
= bond_tx(pkts
, pkts_cnt
);
1045 if (retval
> 0 && retval
< pkts_cnt
)
1046 free_pkts(&pkts
[retval
], pkts_cnt
- retval
);
1048 TEST_ASSERT_EQUAL(retval
, pkts_cnt
, "TX on bonded device failed");
1050 /* Check if packets was transmitted properly. Every slave should have
1051 * at least one packet, and sum must match. Under normal operation
1052 * there should be no LACP nor MARKER frames. */
1054 FOR_EACH_SLAVE(i
, slave
) {
1055 uint16_t normal_cnt
, slow_cnt
;
1057 retval
= slave_get_pkts(slave
, pkts
, RTE_DIM(pkts
));
1061 for (j
= 0; j
< retval
; j
++) {
1062 if (make_lacp_reply(slave
, pkts
[j
]) == 1)
1068 free_pkts(pkts
, normal_cnt
+ slow_cnt
);
1070 if (slave_down_id
== slave
->port_id
) {
1071 TEST_ASSERT_EQUAL(normal_cnt
+ slow_cnt
, 0,
1072 "slave %u enexpectedly transmitted %u packets",
1073 normal_cnt
+ slow_cnt
, slave
->port_id
);
1075 TEST_ASSERT_EQUAL(slow_cnt
, 0,
1076 "slave %u unexpectedly transmitted %d SLOW packets",
1077 slave
->port_id
, slow_cnt
);
1079 TEST_ASSERT_NOT_EQUAL(normal_cnt
, 0,
1080 "slave %u did not transmitted any packets", slave
->port_id
);
1083 pkts_cnt
+= normal_cnt
;
1086 TEST_ASSERT_EQUAL(exp_pkts_cnt
, pkts_cnt
,
1087 "Expected %u packets but transmitted only %d", exp_pkts_cnt
, pkts_cnt
);
1089 return remove_slaves_and_stop_bonded_device();
1093 init_marker(struct rte_mbuf
*pkt
, struct slave_conf
*slave
)
1095 struct marker_header
*marker_hdr
= rte_pktmbuf_mtod(pkt
,
1096 struct marker_header
*);
1098 /* Copy multicast destination address */
1099 ether_addr_copy(&slow_protocol_mac_addr
, &marker_hdr
->eth_hdr
.d_addr
);
1101 /* Init source address */
1102 ether_addr_copy(&parnter_mac_default
, &marker_hdr
->eth_hdr
.s_addr
);
1103 marker_hdr
->eth_hdr
.s_addr
.addr_bytes
[ETHER_ADDR_LEN
-1] = slave
->port_id
;
1105 marker_hdr
->eth_hdr
.ether_type
= rte_cpu_to_be_16(ETHER_TYPE_SLOW
);
1107 marker_hdr
->marker
.subtype
= SLOW_SUBTYPE_MARKER
;
1108 marker_hdr
->marker
.version_number
= 1;
1109 marker_hdr
->marker
.tlv_type_marker
= MARKER_TLV_TYPE_INFO
;
1110 marker_hdr
->marker
.info_length
=
1111 offsetof(struct marker
, reserved_90
) -
1112 offsetof(struct marker
, requester_port
);
1113 RTE_VERIFY(marker_hdr
->marker
.info_length
== 16);
1114 marker_hdr
->marker
.requester_port
= slave
->port_id
+ 1;
1115 marker_hdr
->marker
.tlv_type_terminator
= TLV_TYPE_TERMINATOR_INFORMATION
;
1116 marker_hdr
->marker
.terminator_length
= 0;
1120 test_mode4_marker(void)
1122 struct slave_conf
*slave
;
1123 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
1124 struct rte_mbuf
*marker_pkt
;
1125 struct marker_header
*marker_hdr
;
1131 const uint16_t ethtype_slow_be
= rte_be_to_cpu_16(ETHER_TYPE_SLOW
);
1133 retval
= initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT
,
1135 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
1137 /* Test LACP handshake function */
1138 retval
= bond_handshake();
1139 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
1141 delay
= bond_get_update_timeout_ms();
1142 FOR_EACH_SLAVE(i
, slave
) {
1143 marker_pkt
= rte_pktmbuf_alloc(test_params
.mbuf_pool
);
1144 TEST_ASSERT_NOT_NULL(marker_pkt
, "Failed to allocate marker packet");
1145 init_marker(marker_pkt
, slave
);
1147 retval
= slave_put_pkts(slave
, &marker_pkt
, 1);
1149 rte_pktmbuf_free(marker_pkt
);
1151 TEST_ASSERT_EQUAL(retval
, 1,
1152 "Failed to send marker packet to slave %u", slave
->port_id
);
1154 for (j
= 0; j
< 20; ++j
) {
1155 rte_delay_ms(delay
);
1156 retval
= rte_eth_rx_burst(test_params
.bonded_port_id
, 0, pkts
,
1160 free_pkts(pkts
, retval
);
1162 TEST_ASSERT_EQUAL(retval
, 0, "Received packets unexpectedly");
1164 retval
= rte_eth_tx_burst(test_params
.bonded_port_id
, 0, NULL
, 0);
1165 TEST_ASSERT_EQUAL(retval
, 0,
1166 "Requested TX of 0 packets but %d transmitted", retval
);
1168 /* Check if LACP packet was send by state machines
1169 First and only packet must be a maker response */
1170 retval
= slave_get_pkts(slave
, pkts
, MAX_PKT_BURST
);
1174 free_pkts(pkts
, retval
);
1176 TEST_ASSERT_EQUAL(retval
, 1, "failed to get slave packets");
1179 marker_hdr
= rte_pktmbuf_mtod(pkts
[0], struct marker_header
*);
1180 /* Check if it's slow packet*/
1181 if (marker_hdr
->eth_hdr
.ether_type
!= ethtype_slow_be
)
1183 /* Check if it's marker packet */
1184 else if (marker_hdr
->marker
.subtype
!= SLOW_SUBTYPE_MARKER
)
1186 else if (marker_hdr
->marker
.tlv_type_marker
!= MARKER_TLV_TYPE_RESP
)
1189 free_pkts(pkts
, nb_pkts
);
1191 TEST_ASSERT_NOT_EQUAL(retval
, -1, "Unexpected protocol type");
1192 TEST_ASSERT_NOT_EQUAL(retval
, -2, "Unexpected sub protocol type");
1193 TEST_ASSERT_NOT_EQUAL(retval
, -3, "Unexpected marker type");
1197 TEST_ASSERT(j
< 20, "Marker response not found");
1200 retval
= remove_slaves_and_stop_bonded_device();
1201 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
1203 return TEST_SUCCESS
;
1207 test_mode4_expired(void)
1209 struct slave_conf
*slave
, *exp_slave
= NULL
;
1210 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
1217 struct rte_eth_bond_8023ad_conf conf
;
1219 retval
= initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT
,
1221 /* Set custom timeouts to make test last shorter. */
1222 rte_eth_bond_8023ad_conf_get(test_params
.bonded_port_id
, &conf
);
1223 conf
.fast_periodic_ms
= 100;
1224 conf
.slow_periodic_ms
= 600;
1225 conf
.short_timeout_ms
= 300;
1226 conf
.long_timeout_ms
= 900;
1227 conf
.aggregate_wait_timeout_ms
= 200;
1228 conf
.tx_period_ms
= 100;
1229 old_delay
= conf
.update_timeout_ms
;
1230 conf
.update_timeout_ms
= 10;
1231 rte_eth_bond_8023ad_setup(test_params
.bonded_port_id
, &conf
);
1233 /* Wait for new settings to be applied. */
1234 for (i
= 0; i
< old_delay
/conf
.update_timeout_ms
* 2; i
++) {
1235 FOR_EACH_SLAVE(j
, slave
)
1236 bond_handshake_reply(slave
);
1238 rte_delay_ms(conf
.update_timeout_ms
);
1241 retval
= bond_handshake();
1242 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
1244 /* Find first slave */
1245 FOR_EACH_SLAVE(i
, slave
) {
1250 RTE_VERIFY(exp_slave
!= NULL
);
1252 /* When one of partners do not send or respond to LACP frame in
1253 * conf.long_timeout_ms time, internal state machines should detect this
1254 * and transit to expired state. */
1255 for (j
= 0; j
< conf
.long_timeout_ms
/conf
.update_timeout_ms
+ 2; j
++) {
1256 rte_delay_ms(conf
.update_timeout_ms
);
1258 retval
= bond_tx(NULL
, 0);
1259 TEST_ASSERT_EQUAL(retval
, 0, "Unexpectedly received %d packets",
1262 FOR_EACH_SLAVE(i
, slave
) {
1263 retval
= bond_handshake_reply(slave
);
1264 TEST_ASSERT(retval
>= 0, "Handshake failed");
1266 /* Remove replay for slave that supose to be expired. */
1267 if (slave
== exp_slave
) {
1268 while (rte_ring_count(slave
->rx_queue
) > 0) {
1271 rte_ring_dequeue(slave
->rx_queue
, &pkt
);
1272 rte_pktmbuf_free(pkt
);
1277 retval
= bond_rx(pkts
, RTE_DIM(pkts
));
1279 free_pkts(pkts
, retval
);
1281 TEST_ASSERT_EQUAL(retval
, 0, "Unexpectedly received %d packets",
1285 /* After test only expected slave should be in EXPIRED state */
1286 FOR_EACH_SLAVE(i
, slave
) {
1287 if (slave
== exp_slave
)
1288 TEST_ASSERT(slave
->lacp_parnter_state
& STATE_EXPIRED
,
1289 "Slave %u should be in expired.", slave
->port_id
);
1291 TEST_ASSERT_EQUAL(bond_handshake_done(slave
), 1,
1292 "Slave %u should be operational.", slave
->port_id
);
1295 retval
= remove_slaves_and_stop_bonded_device();
1296 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
1298 return TEST_SUCCESS
;
1302 test_mode4_ext_ctrl(void)
1305 * configure bonded interface without the external sm enabled
1306 * . try to transmit lacpdu (should fail)
1307 * . try to set collecting and distributing flags (should fail)
1308 * reconfigure w/external sm
1309 * . transmit one lacpdu on each slave using new api
1310 * . make sure each slave receives one lacpdu using the callback api
1311 * . transmit one data pdu on each slave (should fail)
1312 * . enable distribution and collection, send one data pdu each again
1316 struct slave_conf
*slave
= NULL
;
1319 struct rte_mbuf
*lacp_tx_buf
[SLAVE_COUNT
];
1320 struct ether_addr src_mac
, dst_mac
;
1321 struct lacpdu_header lacpdu
= {
1323 .subtype
= SLOW_SUBTYPE_LACP
,
1327 ether_addr_copy(&parnter_system
, &src_mac
);
1328 ether_addr_copy(&slow_protocol_mac_addr
, &dst_mac
);
1330 initialize_eth_header(&lacpdu
.eth_hdr
, &src_mac
, &dst_mac
,
1331 ETHER_TYPE_SLOW
, 0, 0);
1333 for (i
= 0; i
< SLAVE_COUNT
; i
++) {
1334 lacp_tx_buf
[i
] = rte_pktmbuf_alloc(test_params
.mbuf_pool
);
1335 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf
[i
], char *),
1336 &lacpdu
, sizeof(lacpdu
));
1337 rte_pktmbuf_pkt_len(lacp_tx_buf
[i
]) = sizeof(lacpdu
);
1340 retval
= initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT
, 0);
1341 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
1343 FOR_EACH_SLAVE(i
, slave
) {
1344 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_slowtx(
1345 test_params
.bonded_port_id
,
1346 slave
->port_id
, lacp_tx_buf
[i
]),
1347 "Slave should not allow manual LACP xmit");
1348 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_collect(
1349 test_params
.bonded_port_id
,
1351 "Slave should not allow external state controls");
1354 free_pkts(lacp_tx_buf
, RTE_DIM(lacp_tx_buf
));
1356 retval
= remove_slaves_and_stop_bonded_device();
1357 TEST_ASSERT_SUCCESS(retval
, "Bonded device cleanup failed.");
1359 return TEST_SUCCESS
;
1364 test_mode4_ext_lacp(void)
1367 struct slave_conf
*slave
= NULL
;
1368 uint8_t all_slaves_done
= 0, i
;
1370 const unsigned int delay
= bond_get_update_timeout_ms();
1372 struct rte_mbuf
*lacp_tx_buf
[SLAVE_COUNT
];
1373 struct rte_mbuf
*buf
[SLAVE_COUNT
];
1374 struct ether_addr src_mac
, dst_mac
;
1375 struct lacpdu_header lacpdu
= {
1377 .subtype
= SLOW_SUBTYPE_LACP
,
1381 ether_addr_copy(&parnter_system
, &src_mac
);
1382 ether_addr_copy(&slow_protocol_mac_addr
, &dst_mac
);
1384 initialize_eth_header(&lacpdu
.eth_hdr
, &src_mac
, &dst_mac
,
1385 ETHER_TYPE_SLOW
, 0, 0);
1387 for (i
= 0; i
< SLAVE_COUNT
; i
++) {
1388 lacp_tx_buf
[i
] = rte_pktmbuf_alloc(test_params
.mbuf_pool
);
1389 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf
[i
], char *),
1390 &lacpdu
, sizeof(lacpdu
));
1391 rte_pktmbuf_pkt_len(lacp_tx_buf
[i
]) = sizeof(lacpdu
);
1394 retval
= initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT
, 1);
1395 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
1397 memset(lacpdu_rx_count
, 0, sizeof(lacpdu_rx_count
));
1399 /* Wait for new settings to be applied. */
1400 for (i
= 0; i
< 30; ++i
)
1401 rte_delay_ms(delay
);
1403 FOR_EACH_SLAVE(i
, slave
) {
1404 retval
= rte_eth_bond_8023ad_ext_slowtx(
1405 test_params
.bonded_port_id
,
1406 slave
->port_id
, lacp_tx_buf
[i
]);
1407 TEST_ASSERT_SUCCESS(retval
,
1408 "Slave should allow manual LACP xmit");
1411 nb_pkts
= bond_tx(NULL
, 0);
1412 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets transmitted unexpectedly");
1414 FOR_EACH_SLAVE(i
, slave
) {
1415 nb_pkts
= slave_get_pkts(slave
, buf
, RTE_DIM(buf
));
1416 TEST_ASSERT_EQUAL(nb_pkts
, 1, "found %u packets on slave %d\n",
1418 slave_put_pkts(slave
, buf
, nb_pkts
);
1421 nb_pkts
= bond_rx(buf
, RTE_DIM(buf
));
1422 free_pkts(buf
, nb_pkts
);
1423 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets received unexpectedly");
1425 /* wait for the periodic callback to run */
1426 for (i
= 0; i
< 30 && all_slaves_done
== 0; ++i
) {
1427 uint8_t s
, total
= 0;
1429 rte_delay_ms(delay
);
1430 FOR_EACH_SLAVE(s
, slave
) {
1431 total
+= lacpdu_rx_count
[slave
->port_id
];
1434 if (total
>= SLAVE_COUNT
)
1435 all_slaves_done
= 1;
1438 FOR_EACH_SLAVE(i
, slave
) {
1439 TEST_ASSERT_EQUAL(lacpdu_rx_count
[slave
->port_id
], 1,
1440 "Slave port %u should have received 1 lacpdu (count=%u)",
1442 lacpdu_rx_count
[slave
->port_id
]);
1445 retval
= remove_slaves_and_stop_bonded_device();
1446 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
1448 return TEST_SUCCESS
;
1452 check_environment(void)
1454 struct slave_conf
*port
;
1455 uint8_t i
, env_state
;
1456 uint8_t slaves
[RTE_DIM(test_params
.slave_ports
)];
1460 FOR_EACH_PORT(i
, port
) {
1461 if (rte_ring_count(port
->rx_queue
) != 0)
1464 if (rte_ring_count(port
->tx_queue
) != 0)
1467 if (port
->bonded
!= 0)
1470 if (port
->lacp_parnter_state
!= 0)
1477 slaves_count
= rte_eth_bond_slaves_get(test_params
.bonded_port_id
,
1478 slaves
, RTE_DIM(slaves
));
1480 if (slaves_count
!= 0)
1483 TEST_ASSERT_EQUAL(env_state
, 0,
1484 "Environment not clean (port %u):%s%s%s%s%s",
1486 env_state
& 0x01 ? " slave rx queue not clean" : "",
1487 env_state
& 0x02 ? " slave tx queue not clean" : "",
1488 env_state
& 0x04 ? " port marked as enslaved" : "",
1489 env_state
& 0x80 ? " slave state is not reset" : "",
1490 env_state
& 0x10 ? " slave count not equal 0" : ".");
1493 return TEST_SUCCESS
;
1497 test_mode4_executor(int (*test_func
)(void))
1499 struct slave_conf
*port
;
1504 /* Check if environment is clean. Fail to launch a test if there was
1505 * a critical error before that prevented to reset environment. */
1506 TEST_ASSERT_SUCCESS(check_environment(),
1507 "Refusing to launch test in dirty environment.");
1509 RTE_VERIFY(test_func
!= NULL
);
1510 test_result
= (*test_func
)();
1512 /* If test succeed check if environment wast left in good condition. */
1513 if (test_result
== TEST_SUCCESS
)
1514 test_result
= check_environment();
1516 /* Reset environment in case test failed to do that. */
1517 if (test_result
!= TEST_SUCCESS
) {
1518 TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
1519 "Failed to stop bonded device");
1521 FOR_EACH_PORT(i
, port
) {
1522 while (rte_ring_count(port
->rx_queue
) != 0) {
1523 if (rte_ring_dequeue(port
->rx_queue
, &pkt
) == 0)
1524 rte_pktmbuf_free(pkt
);
1527 while (rte_ring_count(port
->tx_queue
) != 0) {
1528 if (rte_ring_dequeue(port
->tx_queue
, &pkt
) == 0)
1529 rte_pktmbuf_free(pkt
);
1538 test_mode4_lacp_wrapper(void)
1540 return test_mode4_executor(&test_mode4_lacp
);
1544 test_mode4_marker_wrapper(void)
1546 return test_mode4_executor(&test_mode4_marker
);
1550 test_mode4_rx_wrapper(void)
1552 return test_mode4_executor(&test_mode4_rx
);
1556 test_mode4_tx_burst_wrapper(void)
1558 return test_mode4_executor(&test_mode4_tx_burst
);
1562 test_mode4_expired_wrapper(void)
1564 return test_mode4_executor(&test_mode4_expired
);
1568 test_mode4_ext_ctrl_wrapper(void)
1570 return test_mode4_executor(&test_mode4_ext_ctrl
);
1574 test_mode4_ext_lacp_wrapper(void)
1576 return test_mode4_executor(&test_mode4_ext_lacp
);
1579 static struct unit_test_suite link_bonding_mode4_test_suite
= {
1580 .suite_name
= "Link Bonding mode 4 Unit Test Suite",
1581 .setup
= test_setup
,
1582 .teardown
= testsuite_teardown
,
1583 .unit_test_cases
= {
1584 TEST_CASE_NAMED("test_mode4_lacp", test_mode4_lacp_wrapper
),
1585 TEST_CASE_NAMED("test_mode4_rx", test_mode4_rx_wrapper
),
1586 TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper
),
1587 TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper
),
1588 TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper
),
1589 TEST_CASE_NAMED("test_mode4_ext_ctrl",
1590 test_mode4_ext_ctrl_wrapper
),
1591 TEST_CASE_NAMED("test_mode4_ext_lacp",
1592 test_mode4_ext_lacp_wrapper
),
1594 TEST_CASES_END() /**< NULL terminate unit test array */
1599 test_link_bonding_mode4(void)
1601 return unit_test_suite_runner(&link_bonding_mode4_test_suite
);
1604 REGISTER_TEST_COMMAND(link_bonding_mode4_autotest
, test_link_bonding_mode4
);