ring: return free space when enqueuing
[dpdk.git] / test / test / test_link_bonding_mode4.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 <rte_cycles.h>
42 #include <sys/queue.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
52 #include <rte_string_fns.h>
53
54 #include <rte_eth_ring.h>
55 #include <rte_errno.h>
56 #include <rte_eth_bond.h>
57 #include <rte_eth_bond_8023ad.h>
58
59 #include "packet_burst_generator.h"
60
61 #include "test.h"
62
63 #define SLAVE_COUNT (4)
64
65 #define RX_RING_SIZE 128
66 #define TX_RING_SIZE 512
67
68 #define MBUF_CACHE_SIZE         (250)
69 #define BURST_SIZE              (32)
70
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)
75
76 #define BONDED_DEV_NAME         ("unit_test_mode4_bond_dev")
77
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")
81
82 #define INVALID_SOCKET_ID       (-1)
83 #define INVALID_PORT_ID         (0xFF)
84 #define INVALID_BONDING_MODE    (-1)
85
86 static const struct ether_addr slave_mac_default = {
87         { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 }
88 };
89
90 static const struct ether_addr parnter_mac_default = {
91         { 0x22, 0xBB, 0xFF, 0xBB, 0x00, 0x00 }
92 };
93
94 static const struct ether_addr parnter_system = {
95         { 0x33, 0xFF, 0xBB, 0xFF, 0x00, 0x00 }
96 };
97
98 static const struct ether_addr slow_protocol_mac_addr = {
99         { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
100 };
101
102 struct slave_conf {
103         struct rte_ring *rx_queue;
104         struct rte_ring *tx_queue;
105         uint8_t port_id;
106         uint8_t bonded : 1;
107
108         uint8_t lacp_parnter_state;
109 };
110
111 struct ether_vlan_hdr {
112         struct ether_hdr pkt_eth_hdr;
113         struct vlan_hdr vlan_hdr;
114 };
115
116 struct link_bonding_unittest_params {
117         uint8_t bonded_port_id;
118         struct slave_conf slave_ports[SLAVE_COUNT];
119
120         struct rte_mempool *mbuf_pool;
121 };
122
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
129
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} },
133
134         .mbuf_pool = NULL,
135 };
136
137 static struct rte_eth_conf default_pmd_conf = {
138         .rxmode = {
139                 .mq_mode = ETH_MQ_RX_NONE,
140                 .max_rx_pkt_len = ETHER_MAX_LEN,
141                 .split_hdr_size = 0,
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   = 0, /**< CRC stripped by hardware */
147         },
148         .txmode = {
149                 .mq_mode = ETH_MQ_TX_NONE,
150         },
151         .lpbk_mode = 0,
152 };
153
154 static uint8_t lacpdu_rx_count[RTE_MAX_ETHPORTS] = {0, };
155
156 #define FOR_EACH(_i, _item, _array, _size) \
157         for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
158
159 /* Macro for iterating over every port that can be used as a slave
160  * in this test.
161  * _i variable used as an index in test_params->slave_ports
162  * _slave pointer to &test_params->slave_ports[_idx]
163  */
164 #define FOR_EACH_PORT(_i, _port) \
165         FOR_EACH(_i, _port, test_params.slave_ports, \
166                 RTE_DIM(test_params.slave_ports))
167
168 /* Macro for iterating over every port that can be used as a slave
169  * in this test and satisfy given condition.
170  *
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
174  */
175 #define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \
176         if (!!(_condition))
177
178 /* Macro for iterating over every port that is currently a slave of a bonded
179  * device.
180  * _i variable used as an index in test_params->slave_ports
181  * _slave pointer to &test_params->slave_ports[_idx]
182  * */
183 #define FOR_EACH_SLAVE(_i, _slave) \
184         FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0)
185
186 /*
187  * Returns packets from slaves TX queue.
188  * slave slave port
189  * buffer for packets
190  * size size of buffer
191  * return number of packets or negative error number
192  */
193 static int
194 slave_get_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size)
195 {
196         return rte_ring_dequeue_burst(slave->tx_queue, (void **)buf, size);
197 }
198
199 /*
200  * Injects given packets into slaves RX queue.
201  * slave slave port
202  * buffer for packets
203  * size number of packets to be injected
204  * return number of queued packets or negative error number
205  */
206 static int
207 slave_put_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size)
208 {
209         return rte_ring_enqueue_burst(slave->rx_queue, (void **)buf,
210                         size, NULL);
211 }
212
213 static uint16_t
214 bond_rx(struct rte_mbuf **buf, uint16_t size)
215 {
216         return rte_eth_rx_burst(test_params.bonded_port_id, 0, buf, size);
217 }
218
219 static uint16_t
220 bond_tx(struct rte_mbuf **buf, uint16_t size)
221 {
222         return rte_eth_tx_burst(test_params.bonded_port_id, 0, buf, size);
223 }
224
225 static void
226 free_pkts(struct rte_mbuf **pkts, uint16_t count)
227 {
228         uint16_t i;
229
230         for (i = 0; i < count; i++) {
231                 if (pkts[i] != NULL)
232                         rte_pktmbuf_free(pkts[i]);
233         }
234 }
235
236 static int
237 configure_ethdev(uint8_t port_id, uint8_t start)
238 {
239         TEST_ASSERT(rte_eth_dev_configure(port_id, 1, 1, &default_pmd_conf) == 0,
240                 "Failed to configure device %u", port_id);
241
242         TEST_ASSERT(rte_eth_rx_queue_setup(port_id, 0, RX_RING_SIZE,
243                 rte_eth_dev_socket_id(port_id), NULL, test_params.mbuf_pool) == 0,
244                 "Failed to setup rx queue.");
245
246         TEST_ASSERT(rte_eth_tx_queue_setup(port_id, 0, TX_RING_SIZE,
247                 rte_eth_dev_socket_id(port_id), NULL) == 0,
248                 "Failed to setup tx queue.");
249
250         if (start) {
251                 TEST_ASSERT(rte_eth_dev_start(port_id) == 0,
252                 "Failed to start device (%d).", port_id);
253         }
254         return 0;
255 }
256
257 static int
258 add_slave(struct slave_conf *slave, uint8_t start)
259 {
260         struct ether_addr addr, addr_check;
261
262         /* Some sanity check */
263         RTE_VERIFY(test_params.slave_ports <= slave &&
264                 slave - test_params.slave_ports < (int)RTE_DIM(test_params.slave_ports));
265         RTE_VERIFY(slave->bonded == 0);
266         RTE_VERIFY(slave->port_id != INVALID_PORT_ID);
267
268         ether_addr_copy(&slave_mac_default, &addr);
269         addr.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id;
270
271         rte_eth_dev_mac_addr_remove(slave->port_id, &addr);
272
273         TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave->port_id, &addr, 0),
274                 "Failed to set slave MAC address");
275
276         TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bonded_port_id,
277                 slave->port_id),
278                         "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)",
279                         (uint8_t)(slave - test_params.slave_ports), slave->port_id,
280                         test_params.bonded_port_id);
281
282         slave->bonded = 1;
283         if (start) {
284                 TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave->port_id),
285                         "Failed to start slave %u", slave->port_id);
286         }
287
288         rte_eth_macaddr_get(slave->port_id, &addr_check);
289         TEST_ASSERT_EQUAL(is_same_ether_addr(&addr, &addr_check), 1,
290                         "Slave MAC address is not as expected");
291
292         RTE_VERIFY(slave->lacp_parnter_state == 0);
293         return 0;
294 }
295
296 static int
297 remove_slave(struct slave_conf *slave)
298 {
299         ptrdiff_t slave_idx = slave - test_params.slave_ports;
300
301         RTE_VERIFY(test_params.slave_ports <= slave &&
302                 slave_idx < (ptrdiff_t)RTE_DIM(test_params.slave_ports));
303
304         RTE_VERIFY(slave->bonded == 1);
305         RTE_VERIFY(slave->port_id != INVALID_PORT_ID);
306
307         TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0,
308                 "Slave %u tx queue not empty while removing from bonding.",
309                 slave->port_id);
310
311         TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0,
312                 "Slave %u tx queue not empty while removing from bonding.",
313                 slave->port_id);
314
315         TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params.bonded_port_id,
316                         slave->port_id), 0,
317                         "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)",
318                         (uint8_t)slave_idx, slave->port_id,
319                         test_params.bonded_port_id);
320
321         slave->bonded = 0;
322         slave->lacp_parnter_state = 0;
323         return 0;
324 }
325
326 static void
327 lacp_recv_cb(uint8_t slave_id, struct rte_mbuf *lacp_pkt)
328 {
329         struct ether_hdr *hdr;
330         struct slow_protocol_frame *slow_hdr;
331
332         RTE_VERIFY(lacp_pkt != NULL);
333
334         hdr = rte_pktmbuf_mtod(lacp_pkt, struct ether_hdr *);
335         RTE_VERIFY(hdr->ether_type == rte_cpu_to_be_16(ETHER_TYPE_SLOW));
336
337         slow_hdr = rte_pktmbuf_mtod(lacp_pkt, struct slow_protocol_frame *);
338         RTE_VERIFY(slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_LACP);
339
340         lacpdu_rx_count[slave_id]++;
341         rte_pktmbuf_free(lacp_pkt);
342 }
343
344 static int
345 initialize_bonded_device_with_slaves(uint8_t slave_count, uint8_t external_sm)
346 {
347         uint8_t i;
348
349         RTE_VERIFY(test_params.bonded_port_id != INVALID_PORT_ID);
350
351         for (i = 0; i < slave_count; i++) {
352                 TEST_ASSERT_SUCCESS(add_slave(&test_params.slave_ports[i], 1),
353                         "Failed to add port %u to bonded device.\n",
354                         test_params.slave_ports[i].port_id);
355         }
356
357         /* Reset mode 4 configuration */
358         rte_eth_bond_8023ad_setup(test_params.bonded_port_id, NULL);
359         rte_eth_promiscuous_disable(test_params.bonded_port_id);
360
361         if (external_sm) {
362                 struct rte_eth_bond_8023ad_conf conf;
363
364                 rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
365                 conf.slowrx_cb = lacp_recv_cb;
366                 rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf);
367
368         }
369
370         TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id),
371                 "Failed to start bonded device");
372
373         return TEST_SUCCESS;
374 }
375
376 static int
377 remove_slaves_and_stop_bonded_device(void)
378 {
379         struct slave_conf *slave;
380         int retval;
381         uint8_t slaves[RTE_MAX_ETHPORTS];
382         uint8_t i;
383
384         rte_eth_dev_stop(test_params.bonded_port_id);
385
386         FOR_EACH_SLAVE(i, slave)
387                 remove_slave(slave);
388
389         retval = rte_eth_bond_slaves_get(test_params.bonded_port_id, slaves,
390                 RTE_DIM(slaves));
391
392         TEST_ASSERT_EQUAL(retval, 0,
393                 "Expected bonded device %u have 0 slaves but returned %d.",
394                         test_params.bonded_port_id, retval);
395
396         FOR_EACH_PORT(i, slave) {
397                 rte_eth_dev_stop(slave->port_id);
398
399                 TEST_ASSERT(slave->bonded == 0,
400                         "Port id=%u is still marked as enslaved.", slave->port_id);
401         }
402
403         return TEST_SUCCESS;
404 }
405
406 static int
407 test_setup(void)
408 {
409         int retval, nb_mbuf_per_pool;
410         char name[RTE_ETH_NAME_MAX_LEN];
411         struct slave_conf *port;
412         const uint8_t socket_id = rte_socket_id();
413         uint8_t i;
414
415         if (test_params.mbuf_pool == NULL) {
416                 nb_mbuf_per_pool = TEST_RX_DESC_MAX + DEF_PKT_BURST +
417                                         TEST_TX_DESC_MAX + MAX_PKT_BURST;
418                 test_params.mbuf_pool = rte_pktmbuf_pool_create("TEST_MODE4",
419                         nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0,
420                         RTE_MBUF_DEFAULT_BUF_SIZE, socket_id);
421
422                 TEST_ASSERT(test_params.mbuf_pool != NULL,
423                         "rte_mempool_create failed\n");
424         }
425
426         /* Create / initialize ring eth devs. */
427         FOR_EACH_PORT(i, port) {
428                 port = &test_params.slave_ports[i];
429
430                 if (port->rx_queue == NULL) {
431                         retval = snprintf(name, RTE_DIM(name), SLAVE_RX_QUEUE_FMT, i);
432                         TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long");
433                         port->rx_queue = rte_ring_create(name, RX_RING_SIZE, socket_id, 0);
434                         TEST_ASSERT(port->rx_queue != NULL,
435                                 "Failed to allocate rx ring '%s': %s", name,
436                                 rte_strerror(rte_errno));
437                 }
438
439                 if (port->tx_queue == NULL) {
440                         retval = snprintf(name, RTE_DIM(name), SLAVE_TX_QUEUE_FMT, i);
441                         TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long");
442                         port->tx_queue = rte_ring_create(name, TX_RING_SIZE, socket_id, 0);
443                         TEST_ASSERT_NOT_NULL(port->tx_queue,
444                                 "Failed to allocate tx ring '%s': %s", name,
445                                 rte_strerror(rte_errno));
446                 }
447
448                 if (port->port_id == INVALID_PORT_ID) {
449                         retval = snprintf(name, RTE_DIM(name), SLAVE_DEV_NAME_FMT, i);
450                         TEST_ASSERT(retval < (int)RTE_DIM(name) - 1, "Name too long");
451                         retval = rte_eth_from_rings(name, &port->rx_queue, 1,
452                                         &port->tx_queue, 1, socket_id);
453                         TEST_ASSERT(retval >= 0,
454                                 "Failed to create ring ethdev '%s'\n", name);
455
456                         port->port_id = rte_eth_dev_count() - 1;
457                 }
458
459                 retval = configure_ethdev(port->port_id, 1);
460                 TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n",
461                         name);
462         }
463
464         if (test_params.bonded_port_id == INVALID_PORT_ID) {
465                 retval = rte_eth_bond_create(BONDED_DEV_NAME, BONDING_MODE_8023AD,
466                                 socket_id);
467
468                 TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s",
469                                 BONDED_DEV_NAME);
470
471                 test_params.bonded_port_id = retval;
472                 TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bonded_port_id, 0),
473                                 "Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
474         } else if (rte_eth_bond_mode_get(test_params.bonded_port_id) !=
475                         BONDING_MODE_8023AD) {
476                 TEST_ASSERT(rte_eth_bond_mode_set(test_params.bonded_port_id,
477                         BONDING_MODE_8023AD) == 0,
478                         "Failed to set ethdev %d to mode %d",
479                         test_params.bonded_port_id, BONDING_MODE_8023AD);
480         }
481
482         return 0;
483 }
484
485 static void
486 testsuite_teardown(void)
487 {
488         struct slave_conf *port;
489         uint8_t i;
490
491         /* Only stop ports.
492          * Any cleanup/reset state is done when particular test is
493          * started. */
494
495         rte_eth_dev_stop(test_params.bonded_port_id);
496
497         FOR_EACH_PORT(i, port)
498                 rte_eth_dev_stop(port->port_id);
499 }
500
501 /*
502  * Check if given LACP packet. If it is, make make replay packet to force
503  * COLLECTING state.
504  * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow
505  * frame but not LACP
506  */
507 static int
508 make_lacp_reply(struct slave_conf *slave, struct rte_mbuf *pkt)
509 {
510         struct ether_hdr *hdr;
511         struct slow_protocol_frame *slow_hdr;
512         struct lacpdu *lacp;
513
514         /* look for LACP */
515         hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
516         if (hdr->ether_type != rte_cpu_to_be_16(ETHER_TYPE_SLOW))
517                 return 1;
518
519         slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *);
520         /* ignore packets of other types */
521         if (slow_hdr->slow_protocol.subtype != SLOW_SUBTYPE_LACP)
522                 return 2;
523
524         slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *);
525
526         /* Change source address to partner address */
527         ether_addr_copy(&parnter_mac_default, &slow_hdr->eth_hdr.s_addr);
528         slow_hdr->eth_hdr.s_addr.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id;
529
530         lacp = (struct lacpdu *) &slow_hdr->slow_protocol;
531         /* Save last received state */
532         slave->lacp_parnter_state = lacp->actor.state;
533         /* Change it into LACP replay by matching parameters. */
534         memcpy(&lacp->partner.port_params, &lacp->actor.port_params,
535                 sizeof(struct port_params));
536
537         lacp->partner.state = lacp->actor.state;
538
539         ether_addr_copy(&parnter_system, &lacp->actor.port_params.system);
540         lacp->actor.state = STATE_LACP_ACTIVE |
541                                                 STATE_SYNCHRONIZATION |
542                                                 STATE_AGGREGATION |
543                                                 STATE_COLLECTING |
544                                                 STATE_DISTRIBUTING;
545
546         return 0;
547 }
548
549 /*
550  * Reads packets from given slave, search for LACP packet and reply them.
551  *
552  * Receives burst of packets from slave. Looks for LACP packet. Drops
553  * all other packets. Prepares response LACP and sends it back.
554  *
555  * return number of LACP received and replied, -1 on error.
556  */
557 static int
558 bond_handshake_reply(struct slave_conf *slave)
559 {
560         int retval;
561         struct rte_mbuf *rx_buf[MAX_PKT_BURST];
562         struct rte_mbuf *lacp_tx_buf[MAX_PKT_BURST];
563         uint16_t lacp_tx_buf_cnt = 0, i;
564
565         retval = slave_get_pkts(slave, rx_buf, RTE_DIM(rx_buf));
566         TEST_ASSERT(retval >= 0, "Getting slave %u packets failed.",
567                         slave->port_id);
568
569         for (i = 0; i < (uint16_t)retval; i++) {
570                 if (make_lacp_reply(slave, rx_buf[i]) == 0) {
571                         /* reply with actor's LACP */
572                         lacp_tx_buf[lacp_tx_buf_cnt++] = rx_buf[i];
573                 } else
574                         rte_pktmbuf_free(rx_buf[i]);
575         }
576
577         if (lacp_tx_buf_cnt == 0)
578                 return 0;
579
580         retval = slave_put_pkts(slave, lacp_tx_buf, lacp_tx_buf_cnt);
581         if (retval <= lacp_tx_buf_cnt) {
582                 /* retval might be negative */
583                 for (i = RTE_MAX(0, retval); retval < lacp_tx_buf_cnt; retval++)
584                         rte_pktmbuf_free(lacp_tx_buf[i]);
585         }
586
587         TEST_ASSERT_EQUAL(retval, lacp_tx_buf_cnt,
588                 "Failed to equeue lacp packets into slave %u tx queue.",
589                 slave->port_id);
590
591         return lacp_tx_buf_cnt;
592 }
593
594 /*
595  * Function check if given slave tx queue contains packets that make mode 4
596  * handshake complete. It will drain slave queue.
597  * return 0 if handshake not completed, 1 if handshake was complete,
598  */
599 static int
600 bond_handshake_done(struct slave_conf *slave)
601 {
602         const uint8_t expected_state = STATE_LACP_ACTIVE | STATE_SYNCHRONIZATION |
603                         STATE_AGGREGATION | STATE_COLLECTING | STATE_DISTRIBUTING;
604
605         return slave->lacp_parnter_state == expected_state;
606 }
607
608 static unsigned
609 bond_get_update_timeout_ms(void)
610 {
611         struct rte_eth_bond_8023ad_conf conf;
612
613         rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
614         return conf.update_timeout_ms;
615 }
616
617 /*
618  * Exchanges LACP packets with partner to achieve dynamic port configuration.
619  * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise.
620  */
621 static int
622 bond_handshake(void)
623 {
624         struct slave_conf *slave;
625         struct rte_mbuf *buf[MAX_PKT_BURST];
626         uint16_t nb_pkts;
627         uint8_t all_slaves_done, i, j;
628         uint8_t status[RTE_DIM(test_params.slave_ports)] = { 0 };
629         const unsigned delay = bond_get_update_timeout_ms();
630
631         /* Exchange LACP frames */
632         all_slaves_done = 0;
633         for (i = 0; i < 30 && all_slaves_done == 0; ++i) {
634                 rte_delay_ms(delay);
635
636                 all_slaves_done = 1;
637                 FOR_EACH_SLAVE(j, slave) {
638                         /* If response already send, skip slave */
639                         if (status[j] != 0)
640                                 continue;
641
642                         if (bond_handshake_reply(slave) < 0) {
643                                 all_slaves_done = 0;
644                                 break;
645                         }
646
647                         status[j] = bond_handshake_done(slave);
648                         if (status[j] == 0)
649                                 all_slaves_done = 0;
650                 }
651
652                 nb_pkts = bond_tx(NULL, 0);
653                 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly");
654
655                 nb_pkts = bond_rx(buf, RTE_DIM(buf));
656                 free_pkts(buf, nb_pkts);
657                 TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly");
658         }
659         /* If response didn't send - report failure */
660         TEST_ASSERT_EQUAL(all_slaves_done, 1, "Bond handshake failed\n");
661
662         /* If flags doesn't match - report failure */
663         return all_slaves_done = 1 ? TEST_SUCCESS : TEST_FAILED;
664 }
665
666 #define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports)
667 static int
668 test_mode4_lacp(void)
669 {
670         int retval;
671
672         retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0);
673         TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
674
675         /* Test LACP handshake function */
676         retval = bond_handshake();
677         TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
678
679         retval = remove_slaves_and_stop_bonded_device();
680         TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
681
682         return TEST_SUCCESS;
683 }
684
685 static int
686 generate_packets(struct ether_addr *src_mac,
687         struct ether_addr *dst_mac, uint16_t count, struct rte_mbuf **buf)
688 {
689         uint16_t pktlen = PACKET_BURST_GEN_PKT_LEN;
690         uint8_t vlan_enable = 0;
691         uint16_t vlan_id = 0;
692         uint8_t ip4_type = 1; /* 0 - ipv6 */
693
694         uint16_t src_port = 10, dst_port = 20;
695
696         uint32_t ip_src[4] = { [0 ... 2] = 0xDEADBEEF, [3] = IPv4(192, 168, 0, 1) };
697         uint32_t ip_dst[4] = { [0 ... 2] = 0xFEEDFACE, [3] = IPv4(192, 168, 0, 2) };
698
699         struct ether_hdr pkt_eth_hdr;
700         struct udp_hdr pkt_udp_hdr;
701         union {
702                 struct ipv4_hdr v4;
703                 struct ipv6_hdr v6;
704         } pkt_ip_hdr;
705
706         int retval;
707
708         initialize_eth_header(&pkt_eth_hdr, src_mac, dst_mac, ip4_type,
709                         vlan_enable, vlan_id);
710
711         if (ip4_type)
712                 initialize_ipv4_header(&pkt_ip_hdr.v4, ip_src[3], ip_dst[3], pktlen);
713         else
714                 initialize_ipv6_header(&pkt_ip_hdr.v6, (uint8_t *)ip_src,
715                         (uint8_t *)&ip_dst, pktlen);
716
717         initialize_udp_header(&pkt_udp_hdr, src_port, dst_port, 16);
718
719         retval = generate_packet_burst(test_params.mbuf_pool, buf,
720                         &pkt_eth_hdr, vlan_enable, &pkt_ip_hdr, 1, &pkt_udp_hdr,
721                         count, pktlen, 1);
722
723         if (retval > 0 && retval != count)
724                 free_pkts(&buf[count - retval], retval);
725
726         TEST_ASSERT_EQUAL(retval, count, "Failed to generate %u packets",
727                 count);
728
729         return count;
730 }
731
732 static int
733 generate_and_put_packets(struct slave_conf *slave, struct ether_addr *src_mac,
734                 struct ether_addr *dst_mac, uint16_t count)
735 {
736         struct rte_mbuf *pkts[MAX_PKT_BURST];
737         int retval;
738
739         retval = generate_packets(src_mac, dst_mac, count, pkts);
740         if (retval != (int)count)
741                 return retval;
742
743         retval = slave_put_pkts(slave, pkts, count);
744         if (retval > 0 && retval != count)
745                 free_pkts(&pkts[retval], count - retval);
746
747         TEST_ASSERT_EQUAL(retval, count,
748                 "Failed to enqueue packets into slave %u RX queue", slave->port_id);
749
750         return TEST_SUCCESS;
751 }
752
753 static int
754 test_mode4_rx(void)
755 {
756         struct slave_conf *slave;
757         uint16_t i, j;
758
759         uint16_t expected_pkts_cnt;
760         struct rte_mbuf *pkts[MAX_PKT_BURST];
761         int retval;
762         unsigned delay;
763
764         struct ether_hdr *hdr;
765
766         struct ether_addr src_mac = { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
767         struct ether_addr dst_mac;
768         struct ether_addr bonded_mac;
769
770         retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT,
771                                                       0);
772         TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
773
774         retval = bond_handshake();
775         TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
776
777         rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac);
778         ether_addr_copy(&bonded_mac, &dst_mac);
779
780         /* Assert that dst address is not bonding address.  Do not set the
781          * least significant bit of the zero byte as this would create a
782          * multicast address.
783          */
784         dst_mac.addr_bytes[0] += 2;
785
786         /* First try with promiscuous mode enabled.
787          * Add 2 packets to each slave. First with bonding MAC address, second with
788          * different. Check if we received all of them. */
789         rte_eth_promiscuous_enable(test_params.bonded_port_id);
790
791         expected_pkts_cnt = 0;
792         FOR_EACH_SLAVE(i, slave) {
793                 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1);
794                 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
795                         slave->port_id);
796
797                 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1);
798                 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
799                         slave->port_id);
800
801                 /* Expect 2 packets per slave */
802                 expected_pkts_cnt += 2;
803         }
804
805         retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts,
806                 RTE_DIM(pkts));
807
808         if (retval == expected_pkts_cnt) {
809                 int cnt[2] = { 0, 0 };
810
811                 for (i = 0; i < expected_pkts_cnt; i++) {
812                         hdr = rte_pktmbuf_mtod(pkts[i], struct ether_hdr *);
813                         cnt[is_same_ether_addr(&hdr->d_addr, &bonded_mac)]++;
814                 }
815
816                 free_pkts(pkts, expected_pkts_cnt);
817
818                 /* For division by 2 expected_pkts_cnt must be even */
819                 RTE_VERIFY((expected_pkts_cnt & 1) == 0);
820                 TEST_ASSERT(cnt[0] == expected_pkts_cnt / 2 &&
821                         cnt[1] == expected_pkts_cnt / 2,
822                         "Expected %u packets with the same MAC and %u with different but "
823                         "got %u with the same and %u with diffrent MAC",
824                         expected_pkts_cnt / 2, expected_pkts_cnt / 2, cnt[1], cnt[0]);
825         } else if (retval > 0)
826                 free_pkts(pkts, retval);
827
828         TEST_ASSERT_EQUAL(retval, expected_pkts_cnt,
829                 "Expected %u packets but received only %d", expected_pkts_cnt, retval);
830
831         /* Now, disable promiscuous mode. When promiscuous mode is disabled we
832          * expect to receive only packets that are directed to bonding port. */
833         rte_eth_promiscuous_disable(test_params.bonded_port_id);
834
835         expected_pkts_cnt = 0;
836         FOR_EACH_SLAVE(i, slave) {
837                 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1);
838                 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
839                         slave->port_id);
840
841                 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1);
842                 TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
843                         slave->port_id);
844
845                 /* Expect only one packet per slave */
846                 expected_pkts_cnt += 1;
847         }
848
849         retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts,
850                 RTE_DIM(pkts));
851
852         if (retval == expected_pkts_cnt) {
853                 int eq_cnt = 0;
854
855                 for (i = 0; i < expected_pkts_cnt; i++) {
856                         hdr = rte_pktmbuf_mtod(pkts[i], struct ether_hdr *);
857                         eq_cnt += is_same_ether_addr(&hdr->d_addr, &bonded_mac);
858                 }
859
860                 free_pkts(pkts, expected_pkts_cnt);
861                 TEST_ASSERT_EQUAL(eq_cnt, expected_pkts_cnt, "Packet address mismatch");
862         } else if (retval > 0)
863                 free_pkts(pkts, retval);
864
865         TEST_ASSERT_EQUAL(retval, expected_pkts_cnt,
866                 "Expected %u packets but received only %d", expected_pkts_cnt, retval);
867
868         /* Link down test: simulate link down for first slave. */
869         delay = bond_get_update_timeout_ms();
870
871         uint8_t slave_down_id = INVALID_PORT_ID;
872
873         /* Find first slave and make link down on it*/
874         FOR_EACH_SLAVE(i, slave) {
875                 rte_eth_dev_set_link_down(slave->port_id);
876                 slave_down_id = slave->port_id;
877                 break;
878         }
879
880         RTE_VERIFY(slave_down_id != INVALID_PORT_ID);
881
882         /* Give some time to rearrange bonding */
883         for (i = 0; i < 3; i++) {
884                 rte_delay_ms(delay);
885                 bond_handshake();
886         }
887
888         TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
889
890         /* Put packet to each slave */
891         FOR_EACH_SLAVE(i, slave) {
892                 void *pkt = NULL;
893
894                 dst_mac.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id;
895                 retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1);
896                 TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst.");
897
898                 src_mac.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id;
899                 retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1);
900                 TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst.");
901
902                 retval = bond_rx(pkts, RTE_DIM(pkts));
903
904                 /* Clean anything */
905                 if (retval > 0)
906                         free_pkts(pkts, retval);
907
908                 while (rte_ring_dequeue(slave->rx_queue, (void **)&pkt) == 0)
909                         rte_pktmbuf_free(pkt);
910
911                 if (slave_down_id == slave->port_id)
912                         TEST_ASSERT_EQUAL(retval, 0, "Packets received unexpectedly.");
913                 else
914                         TEST_ASSERT_NOT_EQUAL(retval, 0,
915                                 "Expected to receive some packets on slave %u.",
916                                 slave->port_id);
917                 rte_eth_dev_start(slave->port_id);
918
919                 for (j = 0; j < 5; j++) {
920                         TEST_ASSERT(bond_handshake_reply(slave) >= 0,
921                                 "Handshake after link up");
922
923                         if (bond_handshake_done(slave) == 1)
924                                 break;
925                 }
926
927                 TEST_ASSERT(j < 5, "Failed to agregate slave after link up");
928         }
929
930         remove_slaves_and_stop_bonded_device();
931         return TEST_SUCCESS;
932 }
933
934 static int
935 test_mode4_tx_burst(void)
936 {
937         struct slave_conf *slave;
938         uint16_t i, j;
939
940         uint16_t exp_pkts_cnt, pkts_cnt = 0;
941         struct rte_mbuf *pkts[MAX_PKT_BURST];
942         int retval;
943         unsigned delay;
944
945         struct ether_addr dst_mac = { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
946         struct ether_addr bonded_mac;
947
948         retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0);
949         TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
950
951         retval = bond_handshake();
952         TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
953
954         rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac);
955
956         /* Prepare burst */
957         for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) {
958                 dst_mac.addr_bytes[ETHER_ADDR_LEN - 1] = pkts_cnt;
959                 retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]);
960
961                 if (retval != 1)
962                         free_pkts(pkts, pkts_cnt);
963
964                 TEST_ASSERT_EQUAL(retval, 1, "Failed to generate packet %u", pkts_cnt);
965         }
966         exp_pkts_cnt = pkts_cnt;
967
968         /* Transmit packets on bonded device */
969         retval = bond_tx(pkts, pkts_cnt);
970         if (retval > 0 && retval < pkts_cnt)
971                 free_pkts(&pkts[retval], pkts_cnt - retval);
972
973         TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed");
974
975         /* Check if packets were transmitted properly. Every slave should have
976          * at least one packet, and sum must match. Under normal operation
977          * there should be no LACP nor MARKER frames. */
978         pkts_cnt = 0;
979         FOR_EACH_SLAVE(i, slave) {
980                 uint16_t normal_cnt, slow_cnt;
981
982                 retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts));
983                 normal_cnt = 0;
984                 slow_cnt = 0;
985
986                 for (j = 0; j < retval; j++) {
987                         if (make_lacp_reply(slave, pkts[j]) == 1)
988                                 normal_cnt++;
989                         else
990                                 slow_cnt++;
991                 }
992
993                 free_pkts(pkts, normal_cnt + slow_cnt);
994                 TEST_ASSERT_EQUAL(slow_cnt, 0,
995                         "slave %u unexpectedly transmitted %d SLOW packets", slave->port_id,
996                         slow_cnt);
997
998                 TEST_ASSERT_NOT_EQUAL(normal_cnt, 0,
999                         "slave %u did not transmitted any packets", slave->port_id);
1000
1001                 pkts_cnt += normal_cnt;
1002         }
1003
1004         TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt,
1005                 "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt);
1006
1007         /* Link down test:
1008          * simulate link down for first slave. */
1009         delay = bond_get_update_timeout_ms();
1010
1011         uint8_t slave_down_id = INVALID_PORT_ID;
1012
1013         FOR_EACH_SLAVE(i, slave) {
1014                 rte_eth_dev_set_link_down(slave->port_id);
1015                 slave_down_id = slave->port_id;
1016                 break;
1017         }
1018
1019         RTE_VERIFY(slave_down_id != INVALID_PORT_ID);
1020
1021         /* Give some time to rearrange bonding. */
1022         for (i = 0; i < 3; i++) {
1023                 bond_handshake();
1024                 rte_delay_ms(delay);
1025         }
1026
1027         TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
1028
1029         /* Prepare burst. */
1030         for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) {
1031                 dst_mac.addr_bytes[ETHER_ADDR_LEN - 1] = pkts_cnt;
1032                 retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]);
1033
1034                 if (retval != 1)
1035                         free_pkts(pkts, pkts_cnt);
1036
1037                 TEST_ASSERT_EQUAL(retval, 1, "Failed to generate test packet %u",
1038                         pkts_cnt);
1039         }
1040         exp_pkts_cnt = pkts_cnt;
1041
1042         /* Transmit packets on bonded device. */
1043         retval = bond_tx(pkts, pkts_cnt);
1044         if (retval > 0 && retval < pkts_cnt)
1045                 free_pkts(&pkts[retval], pkts_cnt - retval);
1046
1047         TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed");
1048
1049         /* Check if packets was transmitted properly. Every slave should have
1050          * at least one packet, and sum must match. Under normal operation
1051          * there should be no LACP nor MARKER frames. */
1052         pkts_cnt = 0;
1053         FOR_EACH_SLAVE(i, slave) {
1054                 uint16_t normal_cnt, slow_cnt;
1055
1056                 retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts));
1057                 normal_cnt = 0;
1058                 slow_cnt = 0;
1059
1060                 for (j = 0; j < retval; j++) {
1061                         if (make_lacp_reply(slave, pkts[j]) == 1)
1062                                 normal_cnt++;
1063                         else
1064                                 slow_cnt++;
1065                 }
1066
1067                 free_pkts(pkts, normal_cnt + slow_cnt);
1068
1069                 if (slave_down_id == slave->port_id) {
1070                         TEST_ASSERT_EQUAL(normal_cnt + slow_cnt, 0,
1071                                 "slave %u enexpectedly transmitted %u packets",
1072                                 normal_cnt + slow_cnt, slave->port_id);
1073                 } else {
1074                         TEST_ASSERT_EQUAL(slow_cnt, 0,
1075                                 "slave %u unexpectedly transmitted %d SLOW packets",
1076                                 slave->port_id, slow_cnt);
1077
1078                         TEST_ASSERT_NOT_EQUAL(normal_cnt, 0,
1079                                 "slave %u did not transmitted any packets", slave->port_id);
1080                 }
1081
1082                 pkts_cnt += normal_cnt;
1083         }
1084
1085         TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt,
1086                 "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt);
1087
1088         return remove_slaves_and_stop_bonded_device();
1089 }
1090
1091 static void
1092 init_marker(struct rte_mbuf *pkt, struct slave_conf *slave)
1093 {
1094         struct marker_header *marker_hdr = rte_pktmbuf_mtod(pkt,
1095                         struct marker_header *);
1096
1097         /* Copy multicast destination address */
1098         ether_addr_copy(&slow_protocol_mac_addr, &marker_hdr->eth_hdr.d_addr);
1099
1100         /* Init source address */
1101         ether_addr_copy(&parnter_mac_default, &marker_hdr->eth_hdr.s_addr);
1102         marker_hdr->eth_hdr.s_addr.addr_bytes[ETHER_ADDR_LEN-1] = slave->port_id;
1103
1104         marker_hdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW);
1105
1106         marker_hdr->marker.subtype = SLOW_SUBTYPE_MARKER;
1107         marker_hdr->marker.version_number = 1;
1108         marker_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_INFO;
1109         marker_hdr->marker.info_length =
1110                         offsetof(struct marker, reserved_90) -
1111                         offsetof(struct marker, requester_port);
1112         RTE_VERIFY(marker_hdr->marker.info_length == 16);
1113         marker_hdr->marker.requester_port = slave->port_id + 1;
1114         marker_hdr->marker.tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION;
1115         marker_hdr->marker.terminator_length = 0;
1116 }
1117
1118 static int
1119 test_mode4_marker(void)
1120 {
1121         struct slave_conf *slave;
1122         struct rte_mbuf *pkts[MAX_PKT_BURST];
1123         struct rte_mbuf *marker_pkt;
1124         struct marker_header *marker_hdr;
1125
1126         unsigned delay;
1127         int retval;
1128         uint16_t nb_pkts;
1129         uint8_t i, j;
1130         const uint16_t ethtype_slow_be = rte_be_to_cpu_16(ETHER_TYPE_SLOW);
1131
1132         retval = initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT,
1133                                                       0);
1134         TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
1135
1136         /* Test LACP handshake function */
1137         retval = bond_handshake();
1138         TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
1139
1140         delay = bond_get_update_timeout_ms();
1141         FOR_EACH_SLAVE(i, slave) {
1142                 marker_pkt = rte_pktmbuf_alloc(test_params.mbuf_pool);
1143                 TEST_ASSERT_NOT_NULL(marker_pkt, "Failed to allocate marker packet");
1144                 init_marker(marker_pkt, slave);
1145
1146                 retval = slave_put_pkts(slave, &marker_pkt, 1);
1147                 if (retval != 1)
1148                         rte_pktmbuf_free(marker_pkt);
1149
1150                 TEST_ASSERT_EQUAL(retval, 1,
1151                         "Failed to send marker packet to slave %u", slave->port_id);
1152
1153                 for (j = 0; j < 20; ++j) {
1154                         rte_delay_ms(delay);
1155                         retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts,
1156                                 RTE_DIM(pkts));
1157
1158                         if (retval > 0)
1159                                 free_pkts(pkts, retval);
1160
1161                         TEST_ASSERT_EQUAL(retval, 0, "Received packets unexpectedly");
1162
1163                         retval = rte_eth_tx_burst(test_params.bonded_port_id, 0, NULL, 0);
1164                         TEST_ASSERT_EQUAL(retval, 0,
1165                                 "Requested TX of 0 packets but %d transmitted", retval);
1166
1167                         /* Check if LACP packet was send by state machines
1168                            First and only packet must be a maker response */
1169                         retval = slave_get_pkts(slave, pkts, MAX_PKT_BURST);
1170                         if (retval == 0)
1171                                 continue;
1172                         if (retval > 1)
1173                                 free_pkts(pkts, retval);
1174
1175                         TEST_ASSERT_EQUAL(retval, 1, "failed to get slave packets");
1176                         nb_pkts = retval;
1177
1178                         marker_hdr = rte_pktmbuf_mtod(pkts[0], struct marker_header *);
1179                         /* Check if it's slow packet*/
1180                         if (marker_hdr->eth_hdr.ether_type != ethtype_slow_be)
1181                                 retval = -1;
1182                         /* Check if it's marker packet */
1183                         else if (marker_hdr->marker.subtype != SLOW_SUBTYPE_MARKER)
1184                                 retval = -2;
1185                         else if (marker_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_RESP)
1186                                 retval = -3;
1187
1188                         free_pkts(pkts, nb_pkts);
1189
1190                         TEST_ASSERT_NOT_EQUAL(retval, -1, "Unexpected protocol type");
1191                         TEST_ASSERT_NOT_EQUAL(retval, -2, "Unexpected sub protocol type");
1192                         TEST_ASSERT_NOT_EQUAL(retval, -3, "Unexpected marker type");
1193                         break;
1194                 }
1195
1196                 TEST_ASSERT(j < 20, "Marker response not found");
1197         }
1198
1199         retval = remove_slaves_and_stop_bonded_device();
1200         TEST_ASSERT_SUCCESS(retval,     "Test cleanup failed.");
1201
1202         return TEST_SUCCESS;
1203 }
1204
1205 static int
1206 test_mode4_expired(void)
1207 {
1208         struct slave_conf *slave, *exp_slave = NULL;
1209         struct rte_mbuf *pkts[MAX_PKT_BURST];
1210         int retval;
1211         uint32_t old_delay;
1212
1213         uint8_t i;
1214         uint16_t j;
1215
1216         struct rte_eth_bond_8023ad_conf conf;
1217
1218         retval = initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT,
1219                                                       0);
1220         /* Set custom timeouts to make test last shorter. */
1221         rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
1222         conf.fast_periodic_ms = 100;
1223         conf.slow_periodic_ms = 600;
1224         conf.short_timeout_ms = 300;
1225         conf.long_timeout_ms = 900;
1226         conf.aggregate_wait_timeout_ms = 200;
1227         conf.tx_period_ms = 100;
1228         old_delay = conf.update_timeout_ms;
1229         conf.update_timeout_ms = 10;
1230         rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf);
1231
1232         /* Wait for new settings to be applied. */
1233         for (i = 0; i < old_delay/conf.update_timeout_ms * 2; i++) {
1234                 FOR_EACH_SLAVE(j, slave)
1235                         bond_handshake_reply(slave);
1236
1237                 rte_delay_ms(conf.update_timeout_ms);
1238         }
1239
1240         retval = bond_handshake();
1241         TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
1242
1243         /* Find first slave */
1244         FOR_EACH_SLAVE(i, slave) {
1245                 exp_slave = slave;
1246                 break;
1247         }
1248
1249         RTE_VERIFY(exp_slave != NULL);
1250
1251         /* When one of partners do not send or respond to LACP frame in
1252          * conf.long_timeout_ms time, internal state machines should detect this
1253          * and transit to expired state. */
1254         for (j = 0; j < conf.long_timeout_ms/conf.update_timeout_ms + 2; j++) {
1255                 rte_delay_ms(conf.update_timeout_ms);
1256
1257                 retval = bond_tx(NULL, 0);
1258                 TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets",
1259                         retval);
1260
1261                 FOR_EACH_SLAVE(i, slave) {
1262                         retval = bond_handshake_reply(slave);
1263                         TEST_ASSERT(retval >= 0, "Handshake failed");
1264
1265                         /* Remove replay for slave that supose to be expired. */
1266                         if (slave == exp_slave) {
1267                                 while (rte_ring_count(slave->rx_queue) > 0) {
1268                                         void *pkt = NULL;
1269
1270                                         rte_ring_dequeue(slave->rx_queue, &pkt);
1271                                         rte_pktmbuf_free(pkt);
1272                                 }
1273                         }
1274                 }
1275
1276                 retval = bond_rx(pkts, RTE_DIM(pkts));
1277                 if (retval > 0)
1278                         free_pkts(pkts, retval);
1279
1280                 TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets",
1281                         retval);
1282         }
1283
1284         /* After test only expected slave should be in EXPIRED state */
1285         FOR_EACH_SLAVE(i, slave) {
1286                 if (slave == exp_slave)
1287                         TEST_ASSERT(slave->lacp_parnter_state & STATE_EXPIRED,
1288                                 "Slave %u should be in expired.", slave->port_id);
1289                 else
1290                         TEST_ASSERT_EQUAL(bond_handshake_done(slave), 1,
1291                                 "Slave %u should be operational.", slave->port_id);
1292         }
1293
1294         retval = remove_slaves_and_stop_bonded_device();
1295         TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
1296
1297         return TEST_SUCCESS;
1298 }
1299
1300 static int
1301 test_mode4_ext_ctrl(void)
1302 {
1303         /*
1304          * configure bonded interface without the external sm enabled
1305          *   . try to transmit lacpdu (should fail)
1306          *   . try to set collecting and distributing flags (should fail)
1307          * reconfigure w/external sm
1308          *   . transmit one lacpdu on each slave using new api
1309          *   . make sure each slave receives one lacpdu using the callback api
1310          *   . transmit one data pdu on each slave (should fail)
1311          *   . enable distribution and collection, send one data pdu each again
1312          */
1313
1314         int retval;
1315         struct slave_conf *slave = NULL;
1316         uint8_t i;
1317
1318         struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT];
1319         struct ether_addr src_mac, dst_mac;
1320         struct lacpdu_header lacpdu = {
1321                 .lacpdu = {
1322                         .subtype = SLOW_SUBTYPE_LACP,
1323                 },
1324         };
1325
1326         ether_addr_copy(&parnter_system, &src_mac);
1327         ether_addr_copy(&slow_protocol_mac_addr, &dst_mac);
1328
1329         initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac,
1330                               ETHER_TYPE_SLOW, 0, 0);
1331
1332         for (i = 0; i < SLAVE_COUNT; i++) {
1333                 lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool);
1334                 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *),
1335                            &lacpdu, sizeof(lacpdu));
1336                 rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu);
1337         }
1338
1339         retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0);
1340         TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
1341
1342         FOR_EACH_SLAVE(i, slave) {
1343                 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_slowtx(
1344                                                 test_params.bonded_port_id,
1345                                                 slave->port_id, lacp_tx_buf[i]),
1346                                  "Slave should not allow manual LACP xmit");
1347                 TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_collect(
1348                                                 test_params.bonded_port_id,
1349                                                 slave->port_id, 1),
1350                                  "Slave should not allow external state controls");
1351         }
1352
1353         free_pkts(lacp_tx_buf, RTE_DIM(lacp_tx_buf));
1354
1355         retval = remove_slaves_and_stop_bonded_device();
1356         TEST_ASSERT_SUCCESS(retval, "Bonded device cleanup failed.");
1357
1358         return TEST_SUCCESS;
1359 }
1360
1361
1362 static int
1363 test_mode4_ext_lacp(void)
1364 {
1365         int retval;
1366         struct slave_conf *slave = NULL;
1367         uint8_t all_slaves_done = 0, i;
1368         uint16_t nb_pkts;
1369         const unsigned int delay = bond_get_update_timeout_ms();
1370
1371         struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT];
1372         struct rte_mbuf *buf[SLAVE_COUNT];
1373         struct ether_addr src_mac, dst_mac;
1374         struct lacpdu_header lacpdu = {
1375                 .lacpdu = {
1376                         .subtype = SLOW_SUBTYPE_LACP,
1377                 },
1378         };
1379
1380         ether_addr_copy(&parnter_system, &src_mac);
1381         ether_addr_copy(&slow_protocol_mac_addr, &dst_mac);
1382
1383         initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac,
1384                               ETHER_TYPE_SLOW, 0, 0);
1385
1386         for (i = 0; i < SLAVE_COUNT; i++) {
1387                 lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool);
1388                 rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *),
1389                            &lacpdu, sizeof(lacpdu));
1390                 rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu);
1391         }
1392
1393         retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 1);
1394         TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
1395
1396         memset(lacpdu_rx_count, 0, sizeof(lacpdu_rx_count));
1397
1398         /* Wait for new settings to be applied. */
1399         for (i = 0; i < 30; ++i)
1400                 rte_delay_ms(delay);
1401
1402         FOR_EACH_SLAVE(i, slave) {
1403                 retval = rte_eth_bond_8023ad_ext_slowtx(
1404                                                 test_params.bonded_port_id,
1405                                                 slave->port_id, lacp_tx_buf[i]);
1406                 TEST_ASSERT_SUCCESS(retval,
1407                                     "Slave should allow manual LACP xmit");
1408         }
1409
1410         nb_pkts = bond_tx(NULL, 0);
1411         TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly");
1412
1413         FOR_EACH_SLAVE(i, slave) {
1414                 nb_pkts = slave_get_pkts(slave, buf, RTE_DIM(buf));
1415                 TEST_ASSERT_EQUAL(nb_pkts, 1, "found %u packets on slave %d\n",
1416                                   nb_pkts, i);
1417                 slave_put_pkts(slave, buf, nb_pkts);
1418         }
1419
1420         nb_pkts = bond_rx(buf, RTE_DIM(buf));
1421         free_pkts(buf, nb_pkts);
1422         TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly");
1423
1424         /* wait for the periodic callback to run */
1425         for (i = 0; i < 30 && all_slaves_done == 0; ++i) {
1426                 uint8_t s, total = 0;
1427
1428                 rte_delay_ms(delay);
1429                 FOR_EACH_SLAVE(s, slave) {
1430                         total += lacpdu_rx_count[slave->port_id];
1431                 }
1432
1433                 if (total >= SLAVE_COUNT)
1434                         all_slaves_done = 1;
1435         }
1436
1437         FOR_EACH_SLAVE(i, slave) {
1438                 TEST_ASSERT_EQUAL(lacpdu_rx_count[slave->port_id], 1,
1439                                   "Slave port %u should have received 1 lacpdu (count=%u)",
1440                                   slave->port_id,
1441                                   lacpdu_rx_count[slave->port_id]);
1442         }
1443
1444         retval = remove_slaves_and_stop_bonded_device();
1445         TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
1446
1447         return TEST_SUCCESS;
1448 }
1449
1450 static int
1451 check_environment(void)
1452 {
1453         struct slave_conf *port;
1454         uint8_t i, env_state;
1455         uint8_t slaves[RTE_DIM(test_params.slave_ports)];
1456         int slaves_count;
1457
1458         env_state = 0;
1459         FOR_EACH_PORT(i, port) {
1460                 if (rte_ring_count(port->rx_queue) != 0)
1461                         env_state |= 0x01;
1462
1463                 if (rte_ring_count(port->tx_queue) != 0)
1464                         env_state |= 0x02;
1465
1466                 if (port->bonded != 0)
1467                         env_state |= 0x04;
1468
1469                 if (port->lacp_parnter_state != 0)
1470                         env_state |= 0x08;
1471
1472                 if (env_state != 0)
1473                         break;
1474         }
1475
1476         slaves_count = rte_eth_bond_slaves_get(test_params.bonded_port_id,
1477                         slaves, RTE_DIM(slaves));
1478
1479         if (slaves_count != 0)
1480                 env_state |= 0x10;
1481
1482         TEST_ASSERT_EQUAL(env_state, 0,
1483                 "Environment not clean (port %u):%s%s%s%s%s",
1484                 port->port_id,
1485                 env_state & 0x01 ? " slave rx queue not clean" : "",
1486                 env_state & 0x02 ? " slave tx queue not clean" : "",
1487                 env_state & 0x04 ? " port marked as enslaved" : "",
1488                 env_state & 0x80 ? " slave state is not reset" : "",
1489                 env_state & 0x10 ? " slave count not equal 0" : ".");
1490
1491
1492         return TEST_SUCCESS;
1493 }
1494
1495 static int
1496 test_mode4_executor(int (*test_func)(void))
1497 {
1498         struct slave_conf *port;
1499         int test_result;
1500         uint8_t i;
1501         void *pkt;
1502
1503         /* Check if environment is clean. Fail to launch a test if there was
1504          * a critical error before that prevented to reset environment. */
1505         TEST_ASSERT_SUCCESS(check_environment(),
1506                 "Refusing to launch test in dirty environment.");
1507
1508         RTE_VERIFY(test_func != NULL);
1509         test_result = (*test_func)();
1510
1511         /* If test succeed check if environment wast left in good condition. */
1512         if (test_result == TEST_SUCCESS)
1513                 test_result = check_environment();
1514
1515         /* Reset environment in case test failed to do that. */
1516         if (test_result != TEST_SUCCESS) {
1517                 TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
1518                         "Failed to stop bonded device");
1519
1520                 FOR_EACH_PORT(i, port) {
1521                         while (rte_ring_count(port->rx_queue) != 0) {
1522                                 if (rte_ring_dequeue(port->rx_queue, &pkt) == 0)
1523                                         rte_pktmbuf_free(pkt);
1524                         }
1525
1526                         while (rte_ring_count(port->tx_queue) != 0) {
1527                                 if (rte_ring_dequeue(port->tx_queue, &pkt) == 0)
1528                                         rte_pktmbuf_free(pkt);
1529                         }
1530                 }
1531         }
1532
1533         return test_result;
1534 }
1535
1536 static int
1537 test_mode4_lacp_wrapper(void)
1538 {
1539         return test_mode4_executor(&test_mode4_lacp);
1540 }
1541
1542 static int
1543 test_mode4_marker_wrapper(void)
1544 {
1545         return test_mode4_executor(&test_mode4_marker);
1546 }
1547
1548 static int
1549 test_mode4_rx_wrapper(void)
1550 {
1551         return test_mode4_executor(&test_mode4_rx);
1552 }
1553
1554 static int
1555 test_mode4_tx_burst_wrapper(void)
1556 {
1557         return test_mode4_executor(&test_mode4_tx_burst);
1558 }
1559
1560 static int
1561 test_mode4_expired_wrapper(void)
1562 {
1563         return test_mode4_executor(&test_mode4_expired);
1564 }
1565
1566 static int
1567 test_mode4_ext_ctrl_wrapper(void)
1568 {
1569         return test_mode4_executor(&test_mode4_ext_ctrl);
1570 }
1571
1572 static int
1573 test_mode4_ext_lacp_wrapper(void)
1574 {
1575         return test_mode4_executor(&test_mode4_ext_lacp);
1576 }
1577
1578 static struct unit_test_suite link_bonding_mode4_test_suite  = {
1579         .suite_name = "Link Bonding mode 4 Unit Test Suite",
1580         .setup = test_setup,
1581         .teardown = testsuite_teardown,
1582         .unit_test_cases = {
1583                 TEST_CASE_NAMED("test_mode4_lacp", test_mode4_lacp_wrapper),
1584                 TEST_CASE_NAMED("test_mode4_rx", test_mode4_rx_wrapper),
1585                 TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper),
1586                 TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper),
1587                 TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper),
1588                 TEST_CASE_NAMED("test_mode4_ext_ctrl",
1589                                 test_mode4_ext_ctrl_wrapper),
1590                 TEST_CASE_NAMED("test_mode4_ext_lacp",
1591                                 test_mode4_ext_lacp_wrapper),
1592
1593                 TEST_CASES_END() /**< NULL terminate unit test array */
1594         }
1595 };
1596
1597 static int
1598 test_link_bonding_mode4(void)
1599 {
1600         return unit_test_suite_runner(&link_bonding_mode4_test_suite);
1601 }
1602
1603 REGISTER_TEST_COMMAND(link_bonding_mode4_autotest, test_link_bonding_mode4);