1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
12 #include <rte_cycles.h>
13 #include <sys/queue.h>
15 #include <rte_byteorder.h>
16 #include <rte_common.h>
17 #include <rte_debug.h>
18 #include <rte_ethdev.h>
20 #include <rte_lcore.h>
21 #include <rte_memory.h>
23 #include <rte_string_fns.h>
25 #include <rte_eth_ring.h>
26 #include <rte_errno.h>
27 #include <rte_eth_bond.h>
28 #include <rte_eth_bond_8023ad.h>
30 #include "packet_burst_generator.h"
34 #define SLAVE_COUNT (4)
36 #define RX_RING_SIZE 1024
37 #define TX_RING_SIZE 1024
39 #define MBUF_CACHE_SIZE (250)
40 #define BURST_SIZE (32)
42 #define TEST_RX_DESC_MAX (2048)
43 #define TEST_TX_DESC_MAX (2048)
44 #define MAX_PKT_BURST (32)
45 #define DEF_PKT_BURST (16)
47 #define BONDED_DEV_NAME ("net_bonding_m4_bond_dev")
49 #define SLAVE_DEV_NAME_FMT ("net_virt_%d")
50 #define SLAVE_RX_QUEUE_FMT ("net_virt_%d_rx")
51 #define SLAVE_TX_QUEUE_FMT ("net_virt_%d_tx")
53 #define INVALID_SOCKET_ID (-1)
54 #define INVALID_PORT_ID (0xFF)
55 #define INVALID_BONDING_MODE (-1)
57 static const struct ether_addr slave_mac_default
= {
58 { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 }
61 static const struct ether_addr parnter_mac_default
= {
62 { 0x22, 0xBB, 0xFF, 0xBB, 0x00, 0x00 }
65 static const struct ether_addr parnter_system
= {
66 { 0x33, 0xFF, 0xBB, 0xFF, 0x00, 0x00 }
69 static const struct ether_addr slow_protocol_mac_addr
= {
70 { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
74 struct rte_ring
*rx_queue
;
75 struct rte_ring
*tx_queue
;
79 uint8_t lacp_parnter_state
;
82 struct ether_vlan_hdr
{
83 struct ether_hdr pkt_eth_hdr
;
84 struct vlan_hdr vlan_hdr
;
87 struct link_bonding_unittest_params
{
88 uint8_t bonded_port_id
;
89 struct slave_conf slave_ports
[SLAVE_COUNT
];
91 struct rte_mempool
*mbuf_pool
;
94 #define TEST_DEFAULT_SLAVE_COUNT RTE_DIM(test_params.slave_ports)
95 #define TEST_RX_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT
96 #define TEST_TX_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
97 #define TEST_MARKER_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT
98 #define TEST_EXPIRED_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
99 #define TEST_PROMISC_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
101 static struct link_bonding_unittest_params test_params
= {
102 .bonded_port_id
= INVALID_PORT_ID
,
103 .slave_ports
= { [0 ... SLAVE_COUNT
- 1] = { .port_id
= INVALID_PORT_ID
} },
108 static struct rte_eth_conf default_pmd_conf
= {
110 .mq_mode
= ETH_MQ_RX_NONE
,
111 .max_rx_pkt_len
= ETHER_MAX_LEN
,
115 .mq_mode
= ETH_MQ_TX_NONE
,
120 static uint8_t lacpdu_rx_count
[RTE_MAX_ETHPORTS
] = {0, };
122 #define FOR_EACH(_i, _item, _array, _size) \
123 for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
125 /* Macro for iterating over every port that can be used as a slave
127 * _i variable used as an index in test_params->slave_ports
128 * _slave pointer to &test_params->slave_ports[_idx]
130 #define FOR_EACH_PORT(_i, _port) \
131 FOR_EACH(_i, _port, test_params.slave_ports, \
132 RTE_DIM(test_params.slave_ports))
134 /* Macro for iterating over every port that can be used as a slave
135 * in this test and satisfy given condition.
137 * _i variable used as an index in test_params->slave_ports
138 * _slave pointer to &test_params->slave_ports[_idx]
139 * _condition condition that need to be checked
141 #define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \
144 /* Macro for iterating over every port that is currently a slave of a bonded
146 * _i variable used as an index in test_params->slave_ports
147 * _slave pointer to &test_params->slave_ports[_idx]
149 #define FOR_EACH_SLAVE(_i, _slave) \
150 FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0)
153 * Returns packets from slaves TX queue.
156 * size size of buffer
157 * return number of packets or negative error number
160 slave_get_pkts(struct slave_conf
*slave
, struct rte_mbuf
**buf
, uint16_t size
)
162 return rte_ring_dequeue_burst(slave
->tx_queue
, (void **)buf
,
167 * Injects given packets into slaves RX queue.
170 * size number of packets to be injected
171 * return number of queued packets or negative error number
174 slave_put_pkts(struct slave_conf
*slave
, struct rte_mbuf
**buf
, uint16_t size
)
176 return rte_ring_enqueue_burst(slave
->rx_queue
, (void **)buf
,
181 bond_rx(struct rte_mbuf
**buf
, uint16_t size
)
183 return rte_eth_rx_burst(test_params
.bonded_port_id
, 0, buf
, size
);
187 bond_tx(struct rte_mbuf
**buf
, uint16_t size
)
189 return rte_eth_tx_burst(test_params
.bonded_port_id
, 0, buf
, size
);
193 free_pkts(struct rte_mbuf
**pkts
, uint16_t count
)
197 for (i
= 0; i
< count
; i
++) {
199 rte_pktmbuf_free(pkts
[i
]);
204 configure_ethdev(uint16_t port_id
, uint8_t start
)
206 TEST_ASSERT(rte_eth_dev_configure(port_id
, 1, 1, &default_pmd_conf
) == 0,
207 "Failed to configure device %u", port_id
);
209 TEST_ASSERT(rte_eth_rx_queue_setup(port_id
, 0, RX_RING_SIZE
,
210 rte_eth_dev_socket_id(port_id
), NULL
, test_params
.mbuf_pool
) == 0,
211 "Failed to setup rx queue.");
213 TEST_ASSERT(rte_eth_tx_queue_setup(port_id
, 0, TX_RING_SIZE
,
214 rte_eth_dev_socket_id(port_id
), NULL
) == 0,
215 "Failed to setup tx queue.");
218 TEST_ASSERT(rte_eth_dev_start(port_id
) == 0,
219 "Failed to start device (%d).", port_id
);
225 add_slave(struct slave_conf
*slave
, uint8_t start
)
227 struct ether_addr addr
, addr_check
;
229 /* Some sanity check */
230 RTE_VERIFY(test_params
.slave_ports
<= slave
&&
231 slave
- test_params
.slave_ports
< (int)RTE_DIM(test_params
.slave_ports
));
232 RTE_VERIFY(slave
->bonded
== 0);
233 RTE_VERIFY(slave
->port_id
!= INVALID_PORT_ID
);
235 ether_addr_copy(&slave_mac_default
, &addr
);
236 addr
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
238 rte_eth_dev_mac_addr_remove(slave
->port_id
, &addr
);
240 TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave
->port_id
, &addr
, 0),
241 "Failed to set slave MAC address");
243 TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params
.bonded_port_id
,
245 "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)",
246 (uint8_t)(slave
- test_params
.slave_ports
), slave
->port_id
,
247 test_params
.bonded_port_id
);
251 TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave
->port_id
),
252 "Failed to start slave %u", slave
->port_id
);
255 rte_eth_macaddr_get(slave
->port_id
, &addr_check
);
256 TEST_ASSERT_EQUAL(is_same_ether_addr(&addr
, &addr_check
), 1,
257 "Slave MAC address is not as expected");
259 RTE_VERIFY(slave
->lacp_parnter_state
== 0);
264 remove_slave(struct slave_conf
*slave
)
266 ptrdiff_t slave_idx
= slave
- test_params
.slave_ports
;
268 RTE_VERIFY(test_params
.slave_ports
<= slave
&&
269 slave_idx
< (ptrdiff_t)RTE_DIM(test_params
.slave_ports
));
271 RTE_VERIFY(slave
->bonded
== 1);
272 RTE_VERIFY(slave
->port_id
!= INVALID_PORT_ID
);
274 TEST_ASSERT_EQUAL(rte_ring_count(slave
->rx_queue
), 0,
275 "Slave %u tx queue not empty while removing from bonding.",
278 TEST_ASSERT_EQUAL(rte_ring_count(slave
->rx_queue
), 0,
279 "Slave %u tx queue not empty while removing from bonding.",
282 TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params
.bonded_port_id
,
284 "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)",
285 (uint8_t)slave_idx
, slave
->port_id
,
286 test_params
.bonded_port_id
);
289 slave
->lacp_parnter_state
= 0;
294 lacp_recv_cb(uint16_t slave_id
, struct rte_mbuf
*lacp_pkt
)
296 struct ether_hdr
*hdr
;
297 struct slow_protocol_frame
*slow_hdr
;
299 RTE_VERIFY(lacp_pkt
!= NULL
);
301 hdr
= rte_pktmbuf_mtod(lacp_pkt
, struct ether_hdr
*);
302 RTE_VERIFY(hdr
->ether_type
== rte_cpu_to_be_16(ETHER_TYPE_SLOW
));
304 slow_hdr
= rte_pktmbuf_mtod(lacp_pkt
, struct slow_protocol_frame
*);
305 RTE_VERIFY(slow_hdr
->slow_protocol
.subtype
== SLOW_SUBTYPE_LACP
);
307 lacpdu_rx_count
[slave_id
]++;
308 rte_pktmbuf_free(lacp_pkt
);
312 initialize_bonded_device_with_slaves(uint16_t slave_count
, uint8_t external_sm
)
316 RTE_VERIFY(test_params
.bonded_port_id
!= INVALID_PORT_ID
);
318 for (i
= 0; i
< slave_count
; i
++) {
319 TEST_ASSERT_SUCCESS(add_slave(&test_params
.slave_ports
[i
], 1),
320 "Failed to add port %u to bonded device.\n",
321 test_params
.slave_ports
[i
].port_id
);
324 /* Reset mode 4 configuration */
325 rte_eth_bond_8023ad_setup(test_params
.bonded_port_id
, NULL
);
326 rte_eth_promiscuous_disable(test_params
.bonded_port_id
);
329 struct rte_eth_bond_8023ad_conf conf
;
331 rte_eth_bond_8023ad_conf_get(test_params
.bonded_port_id
, &conf
);
332 conf
.slowrx_cb
= lacp_recv_cb
;
333 rte_eth_bond_8023ad_setup(test_params
.bonded_port_id
, &conf
);
337 TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params
.bonded_port_id
),
338 "Failed to start bonded device");
344 remove_slaves_and_stop_bonded_device(void)
346 struct slave_conf
*slave
;
348 uint16_t slaves
[RTE_MAX_ETHPORTS
];
351 rte_eth_dev_stop(test_params
.bonded_port_id
);
353 FOR_EACH_SLAVE(i
, slave
)
356 retval
= rte_eth_bond_slaves_get(test_params
.bonded_port_id
, slaves
,
359 TEST_ASSERT_EQUAL(retval
, 0,
360 "Expected bonded device %u have 0 slaves but returned %d.",
361 test_params
.bonded_port_id
, retval
);
363 FOR_EACH_PORT(i
, slave
) {
364 rte_eth_dev_stop(slave
->port_id
);
366 TEST_ASSERT(slave
->bonded
== 0,
367 "Port id=%u is still marked as enslaved.", slave
->port_id
);
376 int retval
, nb_mbuf_per_pool
;
377 char name
[RTE_ETH_NAME_MAX_LEN
];
378 struct slave_conf
*port
;
379 const uint8_t socket_id
= rte_socket_id();
382 if (test_params
.mbuf_pool
== NULL
) {
383 nb_mbuf_per_pool
= TEST_RX_DESC_MAX
+ DEF_PKT_BURST
+
384 TEST_TX_DESC_MAX
+ MAX_PKT_BURST
;
385 test_params
.mbuf_pool
= rte_pktmbuf_pool_create("TEST_MODE4",
386 nb_mbuf_per_pool
, MBUF_CACHE_SIZE
, 0,
387 RTE_MBUF_DEFAULT_BUF_SIZE
, socket_id
);
389 TEST_ASSERT(test_params
.mbuf_pool
!= NULL
,
390 "rte_mempool_create failed\n");
393 /* Create / initialize ring eth devs. */
394 FOR_EACH_PORT(i
, port
) {
395 port
= &test_params
.slave_ports
[i
];
397 if (port
->rx_queue
== NULL
) {
398 retval
= snprintf(name
, RTE_DIM(name
), SLAVE_RX_QUEUE_FMT
, i
);
399 TEST_ASSERT(retval
<= (int)RTE_DIM(name
) - 1, "Name too long");
400 port
->rx_queue
= rte_ring_create(name
, RX_RING_SIZE
, socket_id
, 0);
401 TEST_ASSERT(port
->rx_queue
!= NULL
,
402 "Failed to allocate rx ring '%s': %s", name
,
403 rte_strerror(rte_errno
));
406 if (port
->tx_queue
== NULL
) {
407 retval
= snprintf(name
, RTE_DIM(name
), SLAVE_TX_QUEUE_FMT
, i
);
408 TEST_ASSERT(retval
<= (int)RTE_DIM(name
) - 1, "Name too long");
409 port
->tx_queue
= rte_ring_create(name
, TX_RING_SIZE
, socket_id
, 0);
410 TEST_ASSERT_NOT_NULL(port
->tx_queue
,
411 "Failed to allocate tx ring '%s': %s", name
,
412 rte_strerror(rte_errno
));
415 if (port
->port_id
== INVALID_PORT_ID
) {
416 retval
= snprintf(name
, RTE_DIM(name
), SLAVE_DEV_NAME_FMT
, i
);
417 TEST_ASSERT(retval
< (int)RTE_DIM(name
) - 1, "Name too long");
418 retval
= rte_eth_from_rings(name
, &port
->rx_queue
, 1,
419 &port
->tx_queue
, 1, socket_id
);
420 TEST_ASSERT(retval
>= 0,
421 "Failed to create ring ethdev '%s'\n", name
);
423 port
->port_id
= rte_eth_dev_count_avail() - 1;
426 retval
= configure_ethdev(port
->port_id
, 1);
427 TEST_ASSERT_SUCCESS(retval
, "Failed to configure virtual ethdev %s\n",
431 if (test_params
.bonded_port_id
== INVALID_PORT_ID
) {
432 retval
= rte_eth_bond_create(BONDED_DEV_NAME
, BONDING_MODE_8023AD
,
435 TEST_ASSERT(retval
>= 0, "Failed to create bonded ethdev %s",
438 test_params
.bonded_port_id
= retval
;
439 TEST_ASSERT_SUCCESS(configure_ethdev(test_params
.bonded_port_id
, 0),
440 "Failed to configure bonded ethdev %s", BONDED_DEV_NAME
);
441 } else if (rte_eth_bond_mode_get(test_params
.bonded_port_id
) !=
442 BONDING_MODE_8023AD
) {
443 TEST_ASSERT(rte_eth_bond_mode_set(test_params
.bonded_port_id
,
444 BONDING_MODE_8023AD
) == 0,
445 "Failed to set ethdev %d to mode %d",
446 test_params
.bonded_port_id
, BONDING_MODE_8023AD
);
453 testsuite_teardown(void)
455 struct slave_conf
*port
;
459 * Any cleanup/reset state is done when particular test is
462 rte_eth_dev_stop(test_params
.bonded_port_id
);
464 FOR_EACH_PORT(i
, port
)
465 rte_eth_dev_stop(port
->port_id
);
469 * Check if given LACP packet. If it is, make make replay packet to force
471 * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow
475 make_lacp_reply(struct slave_conf
*slave
, struct rte_mbuf
*pkt
)
477 struct ether_hdr
*hdr
;
478 struct slow_protocol_frame
*slow_hdr
;
482 hdr
= rte_pktmbuf_mtod(pkt
, struct ether_hdr
*);
483 if (hdr
->ether_type
!= rte_cpu_to_be_16(ETHER_TYPE_SLOW
))
486 slow_hdr
= rte_pktmbuf_mtod(pkt
, struct slow_protocol_frame
*);
487 /* ignore packets of other types */
488 if (slow_hdr
->slow_protocol
.subtype
!= SLOW_SUBTYPE_LACP
)
491 slow_hdr
= rte_pktmbuf_mtod(pkt
, struct slow_protocol_frame
*);
493 /* Change source address to partner address */
494 ether_addr_copy(&parnter_mac_default
, &slow_hdr
->eth_hdr
.s_addr
);
495 slow_hdr
->eth_hdr
.s_addr
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
497 lacp
= (struct lacpdu
*) &slow_hdr
->slow_protocol
;
498 /* Save last received state */
499 slave
->lacp_parnter_state
= lacp
->actor
.state
;
500 /* Change it into LACP replay by matching parameters. */
501 memcpy(&lacp
->partner
.port_params
, &lacp
->actor
.port_params
,
502 sizeof(struct port_params
));
504 lacp
->partner
.state
= lacp
->actor
.state
;
506 ether_addr_copy(&parnter_system
, &lacp
->actor
.port_params
.system
);
507 lacp
->actor
.state
= STATE_LACP_ACTIVE
|
508 STATE_SYNCHRONIZATION
|
517 * Reads packets from given slave, search for LACP packet and reply them.
519 * Receives burst of packets from slave. Looks for LACP packet. Drops
520 * all other packets. Prepares response LACP and sends it back.
522 * return number of LACP received and replied, -1 on error.
525 bond_handshake_reply(struct slave_conf
*slave
)
528 struct rte_mbuf
*rx_buf
[MAX_PKT_BURST
];
529 struct rte_mbuf
*lacp_tx_buf
[MAX_PKT_BURST
];
530 uint16_t lacp_tx_buf_cnt
= 0, i
;
532 retval
= slave_get_pkts(slave
, rx_buf
, RTE_DIM(rx_buf
));
533 TEST_ASSERT(retval
>= 0, "Getting slave %u packets failed.",
536 for (i
= 0; i
< (uint16_t)retval
; i
++) {
537 if (make_lacp_reply(slave
, rx_buf
[i
]) == 0) {
538 /* reply with actor's LACP */
539 lacp_tx_buf
[lacp_tx_buf_cnt
++] = rx_buf
[i
];
541 rte_pktmbuf_free(rx_buf
[i
]);
544 if (lacp_tx_buf_cnt
== 0)
547 retval
= slave_put_pkts(slave
, lacp_tx_buf
, lacp_tx_buf_cnt
);
548 if (retval
<= lacp_tx_buf_cnt
) {
549 /* retval might be negative */
550 for (i
= RTE_MAX(0, retval
); retval
< lacp_tx_buf_cnt
; retval
++)
551 rte_pktmbuf_free(lacp_tx_buf
[i
]);
554 TEST_ASSERT_EQUAL(retval
, lacp_tx_buf_cnt
,
555 "Failed to equeue lacp packets into slave %u tx queue.",
558 return lacp_tx_buf_cnt
;
562 * Function check if given slave tx queue contains packets that make mode 4
563 * handshake complete. It will drain slave queue.
564 * return 0 if handshake not completed, 1 if handshake was complete,
567 bond_handshake_done(struct slave_conf
*slave
)
569 const uint8_t expected_state
= STATE_LACP_ACTIVE
| STATE_SYNCHRONIZATION
|
570 STATE_AGGREGATION
| STATE_COLLECTING
| STATE_DISTRIBUTING
;
572 return slave
->lacp_parnter_state
== expected_state
;
576 bond_get_update_timeout_ms(void)
578 struct rte_eth_bond_8023ad_conf conf
;
580 rte_eth_bond_8023ad_conf_get(test_params
.bonded_port_id
, &conf
);
581 return conf
.update_timeout_ms
;
585 * Exchanges LACP packets with partner to achieve dynamic port configuration.
586 * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise.
591 struct slave_conf
*slave
;
592 struct rte_mbuf
*buf
[MAX_PKT_BURST
];
594 uint8_t all_slaves_done
, i
, j
;
595 uint8_t status
[RTE_DIM(test_params
.slave_ports
)] = { 0 };
596 const unsigned delay
= bond_get_update_timeout_ms();
598 /* Exchange LACP frames */
600 for (i
= 0; i
< 30 && all_slaves_done
== 0; ++i
) {
604 FOR_EACH_SLAVE(j
, slave
) {
605 /* If response already send, skip slave */
609 if (bond_handshake_reply(slave
) < 0) {
614 status
[j
] = bond_handshake_done(slave
);
619 nb_pkts
= bond_tx(NULL
, 0);
620 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets transmitted unexpectedly");
622 nb_pkts
= bond_rx(buf
, RTE_DIM(buf
));
623 free_pkts(buf
, nb_pkts
);
624 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets received unexpectedly");
626 /* If response didn't send - report failure */
627 TEST_ASSERT_EQUAL(all_slaves_done
, 1, "Bond handshake failed\n");
629 /* If flags doesn't match - report failure */
630 return all_slaves_done
== 1 ? TEST_SUCCESS
: TEST_FAILED
;
633 #define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports)
635 test_mode4_lacp(void)
639 retval
= initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT
, 0);
640 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
642 /* Test LACP handshake function */
643 retval
= bond_handshake();
644 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
646 retval
= remove_slaves_and_stop_bonded_device();
647 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
652 test_mode4_agg_mode_selection(void)
655 /* Test and verify for Stable mode */
656 retval
= initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT
, 0);
657 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
660 retval
= rte_eth_bond_8023ad_agg_selection_set(
661 test_params
.bonded_port_id
, AGG_STABLE
);
662 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bond aggregation mode");
663 retval
= bond_handshake();
664 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
667 retval
= rte_eth_bond_8023ad_agg_selection_get(
668 test_params
.bonded_port_id
);
669 TEST_ASSERT_EQUAL(retval
, AGG_STABLE
,
670 "Wrong agg mode received from bonding device");
672 retval
= remove_slaves_and_stop_bonded_device();
673 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
676 /* test and verify for Bandwidth mode */
677 retval
= initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT
, 0);
678 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
681 retval
= rte_eth_bond_8023ad_agg_selection_set(
682 test_params
.bonded_port_id
,
684 TEST_ASSERT_SUCCESS(retval
,
685 "Failed to initialize bond aggregation mode");
686 retval
= bond_handshake();
687 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
689 retval
= rte_eth_bond_8023ad_agg_selection_get(
690 test_params
.bonded_port_id
);
691 TEST_ASSERT_EQUAL(retval
, AGG_BANDWIDTH
,
692 "Wrong agg mode received from bonding device");
694 retval
= remove_slaves_and_stop_bonded_device();
695 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
697 /* test and verify selection for count mode */
698 retval
= initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT
, 0);
699 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
702 retval
= rte_eth_bond_8023ad_agg_selection_set(
703 test_params
.bonded_port_id
, AGG_COUNT
);
704 TEST_ASSERT_SUCCESS(retval
,
705 "Failed to initialize bond aggregation mode");
706 retval
= bond_handshake();
707 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
709 retval
= rte_eth_bond_8023ad_agg_selection_get(
710 test_params
.bonded_port_id
);
711 TEST_ASSERT_EQUAL(retval
, AGG_COUNT
,
712 "Wrong agg mode received from bonding device");
714 retval
= remove_slaves_and_stop_bonded_device();
715 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
721 generate_packets(struct ether_addr
*src_mac
,
722 struct ether_addr
*dst_mac
, uint16_t count
, struct rte_mbuf
**buf
)
724 uint16_t pktlen
= PACKET_BURST_GEN_PKT_LEN
;
725 uint8_t vlan_enable
= 0;
726 uint16_t vlan_id
= 0;
727 uint8_t ip4_type
= 1; /* 0 - ipv6 */
729 uint16_t src_port
= 10, dst_port
= 20;
731 uint32_t ip_src
[4] = { [0 ... 2] = 0xDEADBEEF, [3] = IPv4(192, 168, 0, 1) };
732 uint32_t ip_dst
[4] = { [0 ... 2] = 0xFEEDFACE, [3] = IPv4(192, 168, 0, 2) };
734 struct ether_hdr pkt_eth_hdr
;
735 struct udp_hdr pkt_udp_hdr
;
743 initialize_eth_header(&pkt_eth_hdr
, src_mac
, dst_mac
, ip4_type
,
744 vlan_enable
, vlan_id
);
747 initialize_ipv4_header(&pkt_ip_hdr
.v4
, ip_src
[3], ip_dst
[3], pktlen
);
749 initialize_ipv6_header(&pkt_ip_hdr
.v6
, (uint8_t *)ip_src
,
750 (uint8_t *)&ip_dst
, pktlen
);
752 initialize_udp_header(&pkt_udp_hdr
, src_port
, dst_port
, 16);
754 retval
= generate_packet_burst(test_params
.mbuf_pool
, buf
,
755 &pkt_eth_hdr
, vlan_enable
, &pkt_ip_hdr
, 1, &pkt_udp_hdr
,
758 if (retval
> 0 && retval
!= count
)
759 free_pkts(&buf
[count
- retval
], retval
);
761 TEST_ASSERT_EQUAL(retval
, count
, "Failed to generate %u packets",
768 generate_and_put_packets(struct slave_conf
*slave
, struct ether_addr
*src_mac
,
769 struct ether_addr
*dst_mac
, uint16_t count
)
771 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
774 retval
= generate_packets(src_mac
, dst_mac
, count
, pkts
);
775 if (retval
!= (int)count
)
778 retval
= slave_put_pkts(slave
, pkts
, count
);
779 if (retval
> 0 && retval
!= count
)
780 free_pkts(&pkts
[retval
], count
- retval
);
782 TEST_ASSERT_EQUAL(retval
, count
,
783 "Failed to enqueue packets into slave %u RX queue", slave
->port_id
);
791 struct slave_conf
*slave
;
794 uint16_t expected_pkts_cnt
;
795 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
799 struct ether_hdr
*hdr
;
801 struct ether_addr src_mac
= { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
802 struct ether_addr dst_mac
;
803 struct ether_addr bonded_mac
;
805 retval
= initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT
,
807 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
809 retval
= bond_handshake();
810 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
812 rte_eth_macaddr_get(test_params
.bonded_port_id
, &bonded_mac
);
813 ether_addr_copy(&bonded_mac
, &dst_mac
);
815 /* Assert that dst address is not bonding address. Do not set the
816 * least significant bit of the zero byte as this would create a
819 dst_mac
.addr_bytes
[0] += 2;
821 /* First try with promiscuous mode enabled.
822 * Add 2 packets to each slave. First with bonding MAC address, second with
823 * different. Check if we received all of them. */
824 rte_eth_promiscuous_enable(test_params
.bonded_port_id
);
826 expected_pkts_cnt
= 0;
827 FOR_EACH_SLAVE(i
, slave
) {
828 retval
= generate_and_put_packets(slave
, &src_mac
, &bonded_mac
, 1);
829 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
832 retval
= generate_and_put_packets(slave
, &src_mac
, &dst_mac
, 1);
833 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
836 /* Expect 2 packets per slave */
837 expected_pkts_cnt
+= 2;
840 retval
= rte_eth_rx_burst(test_params
.bonded_port_id
, 0, pkts
,
843 if (retval
== expected_pkts_cnt
) {
844 int cnt
[2] = { 0, 0 };
846 for (i
= 0; i
< expected_pkts_cnt
; i
++) {
847 hdr
= rte_pktmbuf_mtod(pkts
[i
], struct ether_hdr
*);
848 cnt
[is_same_ether_addr(&hdr
->d_addr
, &bonded_mac
)]++;
851 free_pkts(pkts
, expected_pkts_cnt
);
853 /* For division by 2 expected_pkts_cnt must be even */
854 RTE_VERIFY((expected_pkts_cnt
& 1) == 0);
855 TEST_ASSERT(cnt
[0] == expected_pkts_cnt
/ 2 &&
856 cnt
[1] == expected_pkts_cnt
/ 2,
857 "Expected %u packets with the same MAC and %u with different but "
858 "got %u with the same and %u with different MAC",
859 expected_pkts_cnt
/ 2, expected_pkts_cnt
/ 2, cnt
[1], cnt
[0]);
860 } else if (retval
> 0)
861 free_pkts(pkts
, retval
);
863 TEST_ASSERT_EQUAL(retval
, expected_pkts_cnt
,
864 "Expected %u packets but received only %d", expected_pkts_cnt
, retval
);
866 /* Now, disable promiscuous mode. When promiscuous mode is disabled we
867 * expect to receive only packets that are directed to bonding port. */
868 rte_eth_promiscuous_disable(test_params
.bonded_port_id
);
870 expected_pkts_cnt
= 0;
871 FOR_EACH_SLAVE(i
, slave
) {
872 retval
= generate_and_put_packets(slave
, &src_mac
, &bonded_mac
, 1);
873 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
876 retval
= generate_and_put_packets(slave
, &src_mac
, &dst_mac
, 1);
877 TEST_ASSERT_SUCCESS(retval
, "Failed to enqueue packets to slave %u",
880 /* Expect only one packet per slave */
881 expected_pkts_cnt
+= 1;
884 retval
= rte_eth_rx_burst(test_params
.bonded_port_id
, 0, pkts
,
887 if (retval
== expected_pkts_cnt
) {
890 for (i
= 0; i
< expected_pkts_cnt
; i
++) {
891 hdr
= rte_pktmbuf_mtod(pkts
[i
], struct ether_hdr
*);
892 eq_cnt
+= is_same_ether_addr(&hdr
->d_addr
, &bonded_mac
);
895 free_pkts(pkts
, expected_pkts_cnt
);
896 TEST_ASSERT_EQUAL(eq_cnt
, expected_pkts_cnt
, "Packet address mismatch");
897 } else if (retval
> 0)
898 free_pkts(pkts
, retval
);
900 TEST_ASSERT_EQUAL(retval
, expected_pkts_cnt
,
901 "Expected %u packets but received only %d", expected_pkts_cnt
, retval
);
903 /* Link down test: simulate link down for first slave. */
904 delay
= bond_get_update_timeout_ms();
906 uint8_t slave_down_id
= INVALID_PORT_ID
;
908 /* Find first slave and make link down on it*/
909 FOR_EACH_SLAVE(i
, slave
) {
910 rte_eth_dev_set_link_down(slave
->port_id
);
911 slave_down_id
= slave
->port_id
;
915 RTE_VERIFY(slave_down_id
!= INVALID_PORT_ID
);
917 /* Give some time to rearrange bonding */
918 for (i
= 0; i
< 3; i
++) {
923 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
925 /* Put packet to each slave */
926 FOR_EACH_SLAVE(i
, slave
) {
929 dst_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
930 retval
= generate_and_put_packets(slave
, &src_mac
, &dst_mac
, 1);
931 TEST_ASSERT_SUCCESS(retval
, "Failed to generate test packet burst.");
933 src_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = slave
->port_id
;
934 retval
= generate_and_put_packets(slave
, &src_mac
, &bonded_mac
, 1);
935 TEST_ASSERT_SUCCESS(retval
, "Failed to generate test packet burst.");
937 retval
= bond_rx(pkts
, RTE_DIM(pkts
));
941 free_pkts(pkts
, retval
);
943 while (rte_ring_dequeue(slave
->rx_queue
, (void **)&pkt
) == 0)
944 rte_pktmbuf_free(pkt
);
946 if (slave_down_id
== slave
->port_id
)
947 TEST_ASSERT_EQUAL(retval
, 0, "Packets received unexpectedly.");
949 TEST_ASSERT_NOT_EQUAL(retval
, 0,
950 "Expected to receive some packets on slave %u.",
952 rte_eth_dev_start(slave
->port_id
);
954 for (j
= 0; j
< 5; j
++) {
955 TEST_ASSERT(bond_handshake_reply(slave
) >= 0,
956 "Handshake after link up");
958 if (bond_handshake_done(slave
) == 1)
962 TEST_ASSERT(j
< 5, "Failed to aggregate slave after link up");
965 remove_slaves_and_stop_bonded_device();
970 test_mode4_tx_burst(void)
972 struct slave_conf
*slave
;
975 uint16_t exp_pkts_cnt
, pkts_cnt
= 0;
976 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
980 struct ether_addr dst_mac
= { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
981 struct ether_addr bonded_mac
;
983 retval
= initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT
, 0);
984 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
986 retval
= bond_handshake();
987 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
989 rte_eth_macaddr_get(test_params
.bonded_port_id
, &bonded_mac
);
992 for (pkts_cnt
= 0; pkts_cnt
< RTE_DIM(pkts
); pkts_cnt
++) {
993 dst_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = pkts_cnt
;
994 retval
= generate_packets(&bonded_mac
, &dst_mac
, 1, &pkts
[pkts_cnt
]);
997 free_pkts(pkts
, pkts_cnt
);
999 TEST_ASSERT_EQUAL(retval
, 1, "Failed to generate packet %u", pkts_cnt
);
1001 exp_pkts_cnt
= pkts_cnt
;
1003 /* Transmit packets on bonded device */
1004 retval
= bond_tx(pkts
, pkts_cnt
);
1005 if (retval
> 0 && retval
< pkts_cnt
)
1006 free_pkts(&pkts
[retval
], pkts_cnt
- retval
);
1008 TEST_ASSERT_EQUAL(retval
, pkts_cnt
, "TX on bonded device failed");
1010 /* Check if packets were transmitted properly. Every slave should have
1011 * at least one packet, and sum must match. Under normal operation
1012 * there should be no LACP nor MARKER frames. */
1014 FOR_EACH_SLAVE(i
, slave
) {
1015 uint16_t normal_cnt
, slow_cnt
;
1017 retval
= slave_get_pkts(slave
, pkts
, RTE_DIM(pkts
));
1021 for (j
= 0; j
< retval
; j
++) {
1022 if (make_lacp_reply(slave
, pkts
[j
]) == 1)
1028 free_pkts(pkts
, normal_cnt
+ slow_cnt
);
1029 TEST_ASSERT_EQUAL(slow_cnt
, 0,
1030 "slave %u unexpectedly transmitted %d SLOW packets", slave
->port_id
,
1033 TEST_ASSERT_NOT_EQUAL(normal_cnt
, 0,
1034 "slave %u did not transmitted any packets", slave
->port_id
);
1036 pkts_cnt
+= normal_cnt
;
1039 TEST_ASSERT_EQUAL(exp_pkts_cnt
, pkts_cnt
,
1040 "Expected %u packets but transmitted only %d", exp_pkts_cnt
, pkts_cnt
);
1043 * simulate link down for first slave. */
1044 delay
= bond_get_update_timeout_ms();
1046 uint8_t slave_down_id
= INVALID_PORT_ID
;
1048 FOR_EACH_SLAVE(i
, slave
) {
1049 rte_eth_dev_set_link_down(slave
->port_id
);
1050 slave_down_id
= slave
->port_id
;
1054 RTE_VERIFY(slave_down_id
!= INVALID_PORT_ID
);
1056 /* Give some time to rearrange bonding. */
1057 for (i
= 0; i
< 3; i
++) {
1059 rte_delay_ms(delay
);
1062 TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
1064 /* Prepare burst. */
1065 for (pkts_cnt
= 0; pkts_cnt
< RTE_DIM(pkts
); pkts_cnt
++) {
1066 dst_mac
.addr_bytes
[ETHER_ADDR_LEN
- 1] = pkts_cnt
;
1067 retval
= generate_packets(&bonded_mac
, &dst_mac
, 1, &pkts
[pkts_cnt
]);
1070 free_pkts(pkts
, pkts_cnt
);
1072 TEST_ASSERT_EQUAL(retval
, 1, "Failed to generate test packet %u",
1075 exp_pkts_cnt
= pkts_cnt
;
1077 /* Transmit packets on bonded device. */
1078 retval
= bond_tx(pkts
, pkts_cnt
);
1079 if (retval
> 0 && retval
< pkts_cnt
)
1080 free_pkts(&pkts
[retval
], pkts_cnt
- retval
);
1082 TEST_ASSERT_EQUAL(retval
, pkts_cnt
, "TX on bonded device failed");
1084 /* Check if packets was transmitted properly. Every slave should have
1085 * at least one packet, and sum must match. Under normal operation
1086 * there should be no LACP nor MARKER frames. */
1088 FOR_EACH_SLAVE(i
, slave
) {
1089 uint16_t normal_cnt
, slow_cnt
;
1091 retval
= slave_get_pkts(slave
, pkts
, RTE_DIM(pkts
));
1095 for (j
= 0; j
< retval
; j
++) {
1096 if (make_lacp_reply(slave
, pkts
[j
]) == 1)
1102 free_pkts(pkts
, normal_cnt
+ slow_cnt
);
1104 if (slave_down_id
== slave
->port_id
) {
1105 TEST_ASSERT_EQUAL(normal_cnt
+ slow_cnt
, 0,
1106 "slave %u enexpectedly transmitted %u packets",
1107 normal_cnt
+ slow_cnt
, slave
->port_id
);
1109 TEST_ASSERT_EQUAL(slow_cnt
, 0,
1110 "slave %u unexpectedly transmitted %d SLOW packets",
1111 slave
->port_id
, slow_cnt
);
1113 TEST_ASSERT_NOT_EQUAL(normal_cnt
, 0,
1114 "slave %u did not transmitted any packets", slave
->port_id
);
1117 pkts_cnt
+= normal_cnt
;
1120 TEST_ASSERT_EQUAL(exp_pkts_cnt
, pkts_cnt
,
1121 "Expected %u packets but transmitted only %d", exp_pkts_cnt
, pkts_cnt
);
1123 return remove_slaves_and_stop_bonded_device();
1127 init_marker(struct rte_mbuf
*pkt
, struct slave_conf
*slave
)
1129 struct marker_header
*marker_hdr
= rte_pktmbuf_mtod(pkt
,
1130 struct marker_header
*);
1132 /* Copy multicast destination address */
1133 ether_addr_copy(&slow_protocol_mac_addr
, &marker_hdr
->eth_hdr
.d_addr
);
1135 /* Init source address */
1136 ether_addr_copy(&parnter_mac_default
, &marker_hdr
->eth_hdr
.s_addr
);
1137 marker_hdr
->eth_hdr
.s_addr
.addr_bytes
[ETHER_ADDR_LEN
-1] = slave
->port_id
;
1139 marker_hdr
->eth_hdr
.ether_type
= rte_cpu_to_be_16(ETHER_TYPE_SLOW
);
1141 marker_hdr
->marker
.subtype
= SLOW_SUBTYPE_MARKER
;
1142 marker_hdr
->marker
.version_number
= 1;
1143 marker_hdr
->marker
.tlv_type_marker
= MARKER_TLV_TYPE_INFO
;
1144 marker_hdr
->marker
.info_length
=
1145 offsetof(struct marker
, reserved_90
) -
1146 offsetof(struct marker
, requester_port
);
1147 RTE_VERIFY(marker_hdr
->marker
.info_length
== 16);
1148 marker_hdr
->marker
.requester_port
= slave
->port_id
+ 1;
1149 marker_hdr
->marker
.tlv_type_terminator
= TLV_TYPE_TERMINATOR_INFORMATION
;
1150 marker_hdr
->marker
.terminator_length
= 0;
1154 test_mode4_marker(void)
1156 struct slave_conf
*slave
;
1157 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
1158 struct rte_mbuf
*marker_pkt
;
1159 struct marker_header
*marker_hdr
;
1165 const uint16_t ethtype_slow_be
= rte_be_to_cpu_16(ETHER_TYPE_SLOW
);
1167 retval
= initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT
,
1169 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
1171 /* Test LACP handshake function */
1172 retval
= bond_handshake();
1173 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
1175 delay
= bond_get_update_timeout_ms();
1176 FOR_EACH_SLAVE(i
, slave
) {
1177 marker_pkt
= rte_pktmbuf_alloc(test_params
.mbuf_pool
);
1178 TEST_ASSERT_NOT_NULL(marker_pkt
, "Failed to allocate marker packet");
1179 init_marker(marker_pkt
, slave
);
1181 retval
= slave_put_pkts(slave
, &marker_pkt
, 1);
1183 rte_pktmbuf_free(marker_pkt
);
1185 TEST_ASSERT_EQUAL(retval
, 1,
1186 "Failed to send marker packet to slave %u", slave
->port_id
);
1188 for (j
= 0; j
< 20; ++j
) {
1189 rte_delay_ms(delay
);
1190 retval
= rte_eth_rx_burst(test_params
.bonded_port_id
, 0, pkts
,
1194 free_pkts(pkts
, retval
);
1196 TEST_ASSERT_EQUAL(retval
, 0, "Received packets unexpectedly");
1198 retval
= rte_eth_tx_burst(test_params
.bonded_port_id
, 0, NULL
, 0);
1199 TEST_ASSERT_EQUAL(retval
, 0,
1200 "Requested TX of 0 packets but %d transmitted", retval
);
1202 /* Check if LACP packet was send by state machines
1203 First and only packet must be a maker response */
1204 retval
= slave_get_pkts(slave
, pkts
, MAX_PKT_BURST
);
1208 free_pkts(pkts
, retval
);
1210 TEST_ASSERT_EQUAL(retval
, 1, "failed to get slave packets");
1213 marker_hdr
= rte_pktmbuf_mtod(pkts
[0], struct marker_header
*);
1214 /* Check if it's slow packet*/
1215 if (marker_hdr
->eth_hdr
.ether_type
!= ethtype_slow_be
)
1217 /* Check if it's marker packet */
1218 else if (marker_hdr
->marker
.subtype
!= SLOW_SUBTYPE_MARKER
)
1220 else if (marker_hdr
->marker
.tlv_type_marker
!= MARKER_TLV_TYPE_RESP
)
1223 free_pkts(pkts
, nb_pkts
);
1225 TEST_ASSERT_NOT_EQUAL(retval
, -1, "Unexpected protocol type");
1226 TEST_ASSERT_NOT_EQUAL(retval
, -2, "Unexpected sub protocol type");
1227 TEST_ASSERT_NOT_EQUAL(retval
, -3, "Unexpected marker type");
1231 TEST_ASSERT(j
< 20, "Marker response not found");
1234 retval
= remove_slaves_and_stop_bonded_device();
1235 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
1237 return TEST_SUCCESS
;
1241 test_mode4_expired(void)
1243 struct slave_conf
*slave
, *exp_slave
= NULL
;
1244 struct rte_mbuf
*pkts
[MAX_PKT_BURST
];
1251 struct rte_eth_bond_8023ad_conf conf
;
1253 retval
= initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT
,
1255 /* Set custom timeouts to make test last shorter. */
1256 rte_eth_bond_8023ad_conf_get(test_params
.bonded_port_id
, &conf
);
1257 conf
.fast_periodic_ms
= 100;
1258 conf
.slow_periodic_ms
= 600;
1259 conf
.short_timeout_ms
= 300;
1260 conf
.long_timeout_ms
= 900;
1261 conf
.aggregate_wait_timeout_ms
= 200;
1262 conf
.tx_period_ms
= 100;
1263 old_delay
= conf
.update_timeout_ms
;
1264 conf
.update_timeout_ms
= 10;
1265 rte_eth_bond_8023ad_setup(test_params
.bonded_port_id
, &conf
);
1267 /* Wait for new settings to be applied. */
1268 for (i
= 0; i
< old_delay
/conf
.update_timeout_ms
* 2; i
++) {
1269 FOR_EACH_SLAVE(j
, slave
)
1270 bond_handshake_reply(slave
);
1272 rte_delay_ms(conf
.update_timeout_ms
);
1275 retval
= bond_handshake();
1276 TEST_ASSERT_SUCCESS(retval
, "Initial handshake failed");
1278 /* Find first slave */
1279 FOR_EACH_SLAVE(i
, slave
) {
1284 RTE_VERIFY(exp_slave
!= NULL
);
1286 /* When one of partners do not send or respond to LACP frame in
1287 * conf.long_timeout_ms time, internal state machines should detect this
1288 * and transit to expired state. */
1289 for (j
= 0; j
< conf
.long_timeout_ms
/conf
.update_timeout_ms
+ 2; j
++) {
1290 rte_delay_ms(conf
.update_timeout_ms
);
1292 retval
= bond_tx(NULL
, 0);
1293 TEST_ASSERT_EQUAL(retval
, 0, "Unexpectedly received %d packets",
1296 FOR_EACH_SLAVE(i
, slave
) {
1297 retval
= bond_handshake_reply(slave
);
1298 TEST_ASSERT(retval
>= 0, "Handshake failed");
1300 /* Remove replay for slave that suppose to be expired. */
1301 if (slave
== exp_slave
) {
1302 while (rte_ring_count(slave
->rx_queue
) > 0) {
1305 rte_ring_dequeue(slave
->rx_queue
, &pkt
);
1306 rte_pktmbuf_free(pkt
);
1311 retval
= bond_rx(pkts
, RTE_DIM(pkts
));
1313 free_pkts(pkts
, retval
);
1315 TEST_ASSERT_EQUAL(retval
, 0, "Unexpectedly received %d packets",
1319 /* After test only expected slave should be in EXPIRED state */
1320 FOR_EACH_SLAVE(i
, slave
) {
1321 if (slave
== exp_slave
)
1322 TEST_ASSERT(slave
->lacp_parnter_state
& STATE_EXPIRED
,
1323 "Slave %u should be in expired.", slave
->port_id
);
1325 TEST_ASSERT_EQUAL(bond_handshake_done(slave
), 1,
1326 "Slave %u should be operational.", slave
->port_id
);
1329 retval
= remove_slaves_and_stop_bonded_device();
1330 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
1332 return TEST_SUCCESS
;
1336 test_mode4_ext_ctrl(void)
1339 * configure bonded interface without the external sm enabled
1340 * . try to transmit lacpdu (should fail)
1341 * . try to set collecting and distributing flags (should fail)
1342 * reconfigure w/external sm
1343 * . transmit one lacpdu on each slave using new api
1344 * . make sure each slave receives one lacpdu using the callback api
1345 * . transmit one data pdu on each slave (should fail)
1346 * . enable distribution and collection, send one data pdu each again
1350 struct slave_conf
*slave
= NULL
;
1353 struct rte_mbuf
*lacp_tx_buf
[SLAVE_COUNT
];
1354 struct ether_addr src_mac
, dst_mac
;
1355 struct lacpdu_header lacpdu
= {
1357 .subtype
= SLOW_SUBTYPE_LACP
,
1361 ether_addr_copy(&parnter_system
, &src_mac
);
1362 ether_addr_copy(&slow_protocol_mac_addr
, &dst_mac
);
1364 initialize_eth_header(&lacpdu
.eth_hdr
, &src_mac
, &dst_mac
,
1365 ETHER_TYPE_SLOW
, 0, 0);
1367 for (i
= 0; i
< SLAVE_COUNT
; i
++) {
1368 lacp_tx_buf
[i
] = rte_pktmbuf_alloc(test_params
.mbuf_pool
);
1369 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf
[i
], char *),
1370 &lacpdu
, sizeof(lacpdu
));
1371 rte_pktmbuf_pkt_len(lacp_tx_buf
[i
]) = sizeof(lacpdu
);
1374 retval
= initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT
, 0);
1375 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
1377 FOR_EACH_SLAVE(i
, slave
) {
1378 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_slowtx(
1379 test_params
.bonded_port_id
,
1380 slave
->port_id
, lacp_tx_buf
[i
]),
1381 "Slave should not allow manual LACP xmit");
1382 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_collect(
1383 test_params
.bonded_port_id
,
1385 "Slave should not allow external state controls");
1388 free_pkts(lacp_tx_buf
, RTE_DIM(lacp_tx_buf
));
1390 retval
= remove_slaves_and_stop_bonded_device();
1391 TEST_ASSERT_SUCCESS(retval
, "Bonded device cleanup failed.");
1393 return TEST_SUCCESS
;
1398 test_mode4_ext_lacp(void)
1401 struct slave_conf
*slave
= NULL
;
1402 uint8_t all_slaves_done
= 0, i
;
1404 const unsigned int delay
= bond_get_update_timeout_ms();
1406 struct rte_mbuf
*lacp_tx_buf
[SLAVE_COUNT
];
1407 struct rte_mbuf
*buf
[SLAVE_COUNT
];
1408 struct ether_addr src_mac
, dst_mac
;
1409 struct lacpdu_header lacpdu
= {
1411 .subtype
= SLOW_SUBTYPE_LACP
,
1415 ether_addr_copy(&parnter_system
, &src_mac
);
1416 ether_addr_copy(&slow_protocol_mac_addr
, &dst_mac
);
1418 initialize_eth_header(&lacpdu
.eth_hdr
, &src_mac
, &dst_mac
,
1419 ETHER_TYPE_SLOW
, 0, 0);
1421 for (i
= 0; i
< SLAVE_COUNT
; i
++) {
1422 lacp_tx_buf
[i
] = rte_pktmbuf_alloc(test_params
.mbuf_pool
);
1423 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf
[i
], char *),
1424 &lacpdu
, sizeof(lacpdu
));
1425 rte_pktmbuf_pkt_len(lacp_tx_buf
[i
]) = sizeof(lacpdu
);
1428 retval
= initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT
, 1);
1429 TEST_ASSERT_SUCCESS(retval
, "Failed to initialize bonded device");
1431 memset(lacpdu_rx_count
, 0, sizeof(lacpdu_rx_count
));
1433 /* Wait for new settings to be applied. */
1434 for (i
= 0; i
< 30; ++i
)
1435 rte_delay_ms(delay
);
1437 FOR_EACH_SLAVE(i
, slave
) {
1438 retval
= rte_eth_bond_8023ad_ext_slowtx(
1439 test_params
.bonded_port_id
,
1440 slave
->port_id
, lacp_tx_buf
[i
]);
1441 TEST_ASSERT_SUCCESS(retval
,
1442 "Slave should allow manual LACP xmit");
1445 nb_pkts
= bond_tx(NULL
, 0);
1446 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets transmitted unexpectedly");
1448 FOR_EACH_SLAVE(i
, slave
) {
1449 nb_pkts
= slave_get_pkts(slave
, buf
, RTE_DIM(buf
));
1450 TEST_ASSERT_EQUAL(nb_pkts
, 1, "found %u packets on slave %d\n",
1452 slave_put_pkts(slave
, buf
, nb_pkts
);
1455 nb_pkts
= bond_rx(buf
, RTE_DIM(buf
));
1456 free_pkts(buf
, nb_pkts
);
1457 TEST_ASSERT_EQUAL(nb_pkts
, 0, "Packets received unexpectedly");
1459 /* wait for the periodic callback to run */
1460 for (i
= 0; i
< 30 && all_slaves_done
== 0; ++i
) {
1461 uint8_t s
, total
= 0;
1463 rte_delay_ms(delay
);
1464 FOR_EACH_SLAVE(s
, slave
) {
1465 total
+= lacpdu_rx_count
[slave
->port_id
];
1468 if (total
>= SLAVE_COUNT
)
1469 all_slaves_done
= 1;
1472 FOR_EACH_SLAVE(i
, slave
) {
1473 TEST_ASSERT_EQUAL(lacpdu_rx_count
[slave
->port_id
], 1,
1474 "Slave port %u should have received 1 lacpdu (count=%u)",
1476 lacpdu_rx_count
[slave
->port_id
]);
1479 retval
= remove_slaves_and_stop_bonded_device();
1480 TEST_ASSERT_SUCCESS(retval
, "Test cleanup failed.");
1482 return TEST_SUCCESS
;
1486 check_environment(void)
1488 struct slave_conf
*port
;
1489 uint8_t i
, env_state
;
1490 uint16_t slaves
[RTE_DIM(test_params
.slave_ports
)];
1494 FOR_EACH_PORT(i
, port
) {
1495 if (rte_ring_count(port
->rx_queue
) != 0)
1498 if (rte_ring_count(port
->tx_queue
) != 0)
1501 if (port
->bonded
!= 0)
1504 if (port
->lacp_parnter_state
!= 0)
1511 slaves_count
= rte_eth_bond_slaves_get(test_params
.bonded_port_id
,
1512 slaves
, RTE_DIM(slaves
));
1514 if (slaves_count
!= 0)
1517 TEST_ASSERT_EQUAL(env_state
, 0,
1518 "Environment not clean (port %u):%s%s%s%s%s",
1520 env_state
& 0x01 ? " slave rx queue not clean" : "",
1521 env_state
& 0x02 ? " slave tx queue not clean" : "",
1522 env_state
& 0x04 ? " port marked as enslaved" : "",
1523 env_state
& 0x80 ? " slave state is not reset" : "",
1524 env_state
& 0x10 ? " slave count not equal 0" : ".");
1527 return TEST_SUCCESS
;
1531 test_mode4_executor(int (*test_func
)(void))
1533 struct slave_conf
*port
;
1538 /* Check if environment is clean. Fail to launch a test if there was
1539 * a critical error before that prevented to reset environment. */
1540 TEST_ASSERT_SUCCESS(check_environment(),
1541 "Refusing to launch test in dirty environment.");
1543 RTE_VERIFY(test_func
!= NULL
);
1544 test_result
= (*test_func
)();
1546 /* If test succeed check if environment wast left in good condition. */
1547 if (test_result
== TEST_SUCCESS
)
1548 test_result
= check_environment();
1550 /* Reset environment in case test failed to do that. */
1551 if (test_result
!= TEST_SUCCESS
) {
1552 TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
1553 "Failed to stop bonded device");
1555 FOR_EACH_PORT(i
, port
) {
1556 while (rte_ring_count(port
->rx_queue
) != 0) {
1557 if (rte_ring_dequeue(port
->rx_queue
, &pkt
) == 0)
1558 rte_pktmbuf_free(pkt
);
1561 while (rte_ring_count(port
->tx_queue
) != 0) {
1562 if (rte_ring_dequeue(port
->tx_queue
, &pkt
) == 0)
1563 rte_pktmbuf_free(pkt
);
1572 test_mode4_agg_mode_selection_wrapper(void){
1573 return test_mode4_executor(&test_mode4_agg_mode_selection
);
1577 test_mode4_lacp_wrapper(void)
1579 return test_mode4_executor(&test_mode4_lacp
);
1583 test_mode4_marker_wrapper(void)
1585 return test_mode4_executor(&test_mode4_marker
);
1589 test_mode4_rx_wrapper(void)
1591 return test_mode4_executor(&test_mode4_rx
);
1595 test_mode4_tx_burst_wrapper(void)
1597 return test_mode4_executor(&test_mode4_tx_burst
);
1601 test_mode4_expired_wrapper(void)
1603 return test_mode4_executor(&test_mode4_expired
);
1607 test_mode4_ext_ctrl_wrapper(void)
1609 return test_mode4_executor(&test_mode4_ext_ctrl
);
1613 test_mode4_ext_lacp_wrapper(void)
1615 return test_mode4_executor(&test_mode4_ext_lacp
);
1618 static struct unit_test_suite link_bonding_mode4_test_suite
= {
1619 .suite_name
= "Link Bonding mode 4 Unit Test Suite",
1620 .setup
= test_setup
,
1621 .teardown
= testsuite_teardown
,
1622 .unit_test_cases
= {
1623 TEST_CASE_NAMED("test_mode4_agg_mode_selection",
1624 test_mode4_agg_mode_selection_wrapper
),
1625 TEST_CASE_NAMED("test_mode4_lacp", test_mode4_lacp_wrapper
),
1626 TEST_CASE_NAMED("test_mode4_rx", test_mode4_rx_wrapper
),
1627 TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper
),
1628 TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper
),
1629 TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper
),
1630 TEST_CASE_NAMED("test_mode4_ext_ctrl",
1631 test_mode4_ext_ctrl_wrapper
),
1632 TEST_CASE_NAMED("test_mode4_ext_lacp",
1633 test_mode4_ext_lacp_wrapper
),
1635 TEST_CASES_END() /**< NULL terminate unit test array */
1640 test_link_bonding_mode4(void)
1642 return unit_test_suite_runner(&link_bonding_mode4_test_suite
);
1645 REGISTER_TEST_COMMAND(link_bonding_mode4_autotest
, test_link_bonding_mode4
);