4 * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <rte_alarm.h>
39 #include <rte_malloc.h>
40 #include <rte_errno.h>
41 #include <rte_cycles.h>
42 #include <rte_compat.h>
44 #include "rte_eth_bond_private.h"
46 static void bond_mode_8023ad_ext_periodic_cb(void *arg);
47 #ifdef RTE_LIBRTE_BOND_DEBUG_8023AD
48 #define MODE4_DEBUG(fmt, ...) RTE_LOG(DEBUG, PMD, "%6u [Port %u: %s] " fmt, \
49 bond_dbg_get_time_diff_ms(), slave_id, \
50 __func__, ##__VA_ARGS__)
52 static uint64_t start_time;
55 bond_dbg_get_time_diff_ms(void)
63 return ((now - start_time) * 1000) / rte_get_tsc_hz();
67 bond_print_lacp(struct lacpdu *l)
71 char a_state[256] = { 0 };
72 char p_state[256] = { 0 };
74 static const char * const state_labels[] = {
75 "ACT", "TIMEOUT", "AGG", "SYNC", "COL", "DIST", "DEF", "EXP"
83 addr = l->actor.port_params.system.addr_bytes;
84 snprintf(a_address, sizeof(a_address), "%02X:%02X:%02X:%02X:%02X:%02X",
85 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
87 addr = l->partner.port_params.system.addr_bytes;
88 snprintf(p_address, sizeof(p_address), "%02X:%02X:%02X:%02X:%02X:%02X",
89 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
91 for (i = 0; i < 8; i++) {
92 if ((l->actor.state >> i) & 1) {
93 a_len += snprintf(&a_state[a_len], RTE_DIM(a_state) - a_len, "%s ",
97 if ((l->partner.state >> i) & 1) {
98 p_len += snprintf(&p_state[p_len], RTE_DIM(p_state) - p_len, "%s ",
103 if (a_len && a_state[a_len-1] == ' ')
104 a_state[a_len-1] = '\0';
106 if (p_len && p_state[p_len-1] == ' ')
107 p_state[p_len-1] = '\0';
109 RTE_LOG(DEBUG, PMD, "LACP: {\n"\
112 " actor={ tlv=%02X, len=%02X\n"\
113 " pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"\
116 " partner={ tlv=%02X, len=%02X\n"\
117 " pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"\
120 " collector={info=%02X, length=%02X, max_delay=%04X\n, " \
121 "type_term=%02X, terminator_length = %02X}\n",\
124 l->actor.tlv_type_info,\
125 l->actor.info_length,\
126 l->actor.port_params.system_priority,\
128 l->actor.port_params.key,\
129 l->actor.port_params.port_priority,\
130 l->actor.port_params.port_number,\
132 l->partner.tlv_type_info,\
133 l->partner.info_length,\
134 l->partner.port_params.system_priority,\
136 l->partner.port_params.key,\
137 l->partner.port_params.port_priority,\
138 l->partner.port_params.port_number,\
140 l->tlv_type_collector_info,\
141 l->collector_info_length,\
142 l->collector_max_delay,\
143 l->tlv_type_terminator,\
144 l->terminator_length);
147 #define BOND_PRINT_LACP(lacpdu) bond_print_lacp(lacpdu)
149 #define BOND_PRINT_LACP(lacpdu) do { } while (0)
150 #define MODE4_DEBUG(fmt, ...) do { } while (0)
153 static const struct ether_addr lacp_mac_addr = {
154 .addr_bytes = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
157 struct port mode_8023ad_ports[RTE_MAX_ETHPORTS];
160 timer_cancel(uint64_t *timer)
166 timer_set(uint64_t *timer, uint64_t timeout)
168 *timer = rte_rdtsc() + timeout;
171 /* Forces given timer to be in expired state. */
173 timer_force_expired(uint64_t *timer)
175 *timer = rte_rdtsc();
179 timer_is_stopped(uint64_t *timer)
185 timer_is_expired(uint64_t *timer)
187 return *timer < rte_rdtsc();
190 /* Timer is in running state if it is not stopped nor expired */
192 timer_is_running(uint64_t *timer)
194 return !timer_is_stopped(timer) && !timer_is_expired(timer);
198 set_warning_flags(struct port *port, uint16_t flags)
202 uint16_t new_flag = 0;
205 old = port->warnings_to_show;
206 new_flag = old | flags;
207 retval = rte_atomic16_cmpset(&port->warnings_to_show, old, new_flag);
208 } while (unlikely(retval == 0));
212 show_warnings(uint16_t slave_id)
214 struct port *port = &mode_8023ad_ports[slave_id];
218 warnings = port->warnings_to_show;
219 } while (rte_atomic16_cmpset(&port->warnings_to_show, warnings, 0) == 0);
224 if (!timer_is_expired(&port->warning_timer))
228 timer_set(&port->warning_timer, BOND_8023AD_WARNINGS_PERIOD_MS *
229 rte_get_tsc_hz() / 1000);
231 if (warnings & WRN_RX_QUEUE_FULL) {
233 "Slave %u: failed to enqueue LACP packet into RX ring.\n"
234 "Receive and transmit functions must be invoked on bonded\n"
235 "interface at least 10 times per second or LACP will not\n"
236 "work correctly\n", slave_id);
239 if (warnings & WRN_TX_QUEUE_FULL) {
241 "Slave %u: failed to enqueue LACP packet into TX ring.\n"
242 "Receive and transmit functions must be invoked on bonded\n"
243 "interface at least 10 times per second or LACP will not\n"
244 "work correctly\n", slave_id);
247 if (warnings & WRN_RX_MARKER_TO_FAST)
248 RTE_LOG(INFO, PMD, "Slave %u: marker to early - ignoring.\n", slave_id);
250 if (warnings & WRN_UNKNOWN_SLOW_TYPE) {
252 "Slave %u: ignoring unknown slow protocol frame type", slave_id);
255 if (warnings & WRN_UNKNOWN_MARKER_TYPE)
256 RTE_LOG(INFO, PMD, "Slave %u: ignoring unknown marker type", slave_id);
258 if (warnings & WRN_NOT_LACP_CAPABLE)
259 MODE4_DEBUG("Port %u is not LACP capable!\n", slave_id);
263 record_default(struct port *port)
265 /* Record default parameters for partner. Partner admin parameters
266 * are not implemented so set them to arbitrary default (last known) and
267 * mark actor that parner is in defaulted state. */
268 port->partner_state = STATE_LACP_ACTIVE;
269 ACTOR_STATE_SET(port, DEFAULTED);
272 /** Function handles rx state machine.
274 * This function implements Receive State Machine from point 5.4.12 in
275 * 802.1AX documentation. It should be called periodically.
277 * @param lacpdu LACPDU received.
278 * @param port Port on which LACPDU was received.
281 rx_machine(struct bond_dev_private *internals, uint16_t slave_id,
284 struct port *agg, *port = &mode_8023ad_ports[slave_id];
287 if (SM_FLAG(port, BEGIN)) {
288 /* Initialize stuff */
289 MODE4_DEBUG("-> INITIALIZE\n");
290 SM_FLAG_CLR(port, MOVED);
291 port->selected = UNSELECTED;
293 record_default(port);
295 ACTOR_STATE_CLR(port, EXPIRED);
296 timer_cancel(&port->current_while_timer);
298 /* DISABLED: On initialization partner is out of sync */
299 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
301 /* LACP DISABLED stuff if LACP not enabled on this port */
302 if (!SM_FLAG(port, LACP_ENABLED))
303 PARTNER_STATE_CLR(port, AGGREGATION);
305 PARTNER_STATE_SET(port, AGGREGATION);
308 if (!SM_FLAG(port, LACP_ENABLED)) {
309 /* Update parameters only if state changed */
310 if (!timer_is_stopped(&port->current_while_timer)) {
311 port->selected = UNSELECTED;
312 record_default(port);
313 PARTNER_STATE_CLR(port, AGGREGATION);
314 ACTOR_STATE_CLR(port, EXPIRED);
315 timer_cancel(&port->current_while_timer);
321 MODE4_DEBUG("LACP -> CURRENT\n");
322 BOND_PRINT_LACP(lacp);
323 /* Update selected flag. If partner parameters are defaulted assume they
324 * are match. If not defaulted compare LACP actor with ports parner
326 if (!ACTOR_STATE(port, DEFAULTED) &&
327 (ACTOR_STATE(port, AGGREGATION) != PARTNER_STATE(port, AGGREGATION)
328 || memcmp(&port->partner, &lacp->actor.port_params,
329 sizeof(port->partner)) != 0)) {
330 MODE4_DEBUG("selected <- UNSELECTED\n");
331 port->selected = UNSELECTED;
334 /* Record this PDU actor params as partner params */
335 memcpy(&port->partner, &lacp->actor.port_params,
336 sizeof(struct port_params));
337 port->partner_state = lacp->actor.state;
339 /* Partner parameters are not defaulted any more */
340 ACTOR_STATE_CLR(port, DEFAULTED);
342 /* If LACP partner params match this port actor params */
343 agg = &mode_8023ad_ports[port->aggregator_port_id];
344 bool match = port->actor.system_priority ==
345 lacp->partner.port_params.system_priority &&
346 is_same_ether_addr(&agg->actor.system,
347 &lacp->partner.port_params.system) &&
348 port->actor.port_priority ==
349 lacp->partner.port_params.port_priority &&
350 port->actor.port_number ==
351 lacp->partner.port_params.port_number;
353 /* Update NTT if partners information are outdated (xored and masked
355 uint8_t state_mask = STATE_LACP_ACTIVE | STATE_LACP_SHORT_TIMEOUT |
356 STATE_SYNCHRONIZATION | STATE_AGGREGATION;
358 if (((port->actor_state ^ lacp->partner.state) & state_mask) ||
360 SM_FLAG_SET(port, NTT);
363 /* If LACP partner params match this port actor params */
364 if (match == true && ACTOR_STATE(port, AGGREGATION) ==
365 PARTNER_STATE(port, AGGREGATION))
366 PARTNER_STATE_SET(port, SYNCHRONIZATION);
367 else if (!PARTNER_STATE(port, AGGREGATION) && ACTOR_STATE(port,
369 PARTNER_STATE_SET(port, SYNCHRONIZATION);
371 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
373 if (ACTOR_STATE(port, LACP_SHORT_TIMEOUT))
374 timeout = internals->mode4.short_timeout;
376 timeout = internals->mode4.long_timeout;
378 timer_set(&port->current_while_timer, timeout);
379 ACTOR_STATE_CLR(port, EXPIRED);
380 return; /* No state change */
383 /* If CURRENT state timer is not running (stopped or expired)
384 * transit to EXPIRED state from DISABLED or CURRENT */
385 if (!timer_is_running(&port->current_while_timer)) {
386 ACTOR_STATE_SET(port, EXPIRED);
387 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
388 PARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT);
389 timer_set(&port->current_while_timer, internals->mode4.short_timeout);
394 * Function handles periodic tx state machine.
396 * Function implements Periodic Transmission state machine from point 5.4.13
397 * in 802.1AX documentation. It should be called periodically.
399 * @param port Port to handle state machine.
402 periodic_machine(struct bond_dev_private *internals, uint16_t slave_id)
404 struct port *port = &mode_8023ad_ports[slave_id];
405 /* Calculate if either site is LACP enabled */
407 uint8_t active = ACTOR_STATE(port, LACP_ACTIVE) ||
408 PARTNER_STATE(port, LACP_ACTIVE);
410 uint8_t is_partner_fast, was_partner_fast;
411 /* No periodic is on BEGIN, LACP DISABLE or when both sides are pasive */
412 if (SM_FLAG(port, BEGIN) || !SM_FLAG(port, LACP_ENABLED) || !active) {
413 timer_cancel(&port->periodic_timer);
414 timer_force_expired(&port->tx_machine_timer);
415 SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);
417 MODE4_DEBUG("-> NO_PERIODIC ( %s%s%s)\n",
418 SM_FLAG(port, BEGIN) ? "begind " : "",
419 SM_FLAG(port, LACP_ENABLED) ? "" : "LACP disabled ",
420 active ? "LACP active " : "LACP pasive ");
424 is_partner_fast = PARTNER_STATE(port, LACP_SHORT_TIMEOUT);
425 was_partner_fast = SM_FLAG(port, PARTNER_SHORT_TIMEOUT);
427 /* If periodic timer is not started, transit from NO PERIODIC to FAST/SLOW.
428 * Other case: check if timer expire or partners settings changed. */
429 if (!timer_is_stopped(&port->periodic_timer)) {
430 if (timer_is_expired(&port->periodic_timer)) {
431 SM_FLAG_SET(port, NTT);
432 } else if (is_partner_fast != was_partner_fast) {
433 /* Partners timeout was slow and now it is fast -> send LACP.
434 * In other case (was fast and now it is slow) just switch
435 * timeout to slow without forcing send of LACP (because standard
438 SM_FLAG_SET(port, NTT);
440 return; /* Nothing changed */
443 /* Handle state transition to FAST/SLOW LACP timeout */
444 if (is_partner_fast) {
445 timeout = internals->mode4.fast_periodic_timeout;
446 SM_FLAG_SET(port, PARTNER_SHORT_TIMEOUT);
448 timeout = internals->mode4.slow_periodic_timeout;
449 SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);
452 timer_set(&port->periodic_timer, timeout);
456 * Function handles mux state machine.
458 * Function implements Mux Machine from point 5.4.15 in 802.1AX documentation.
459 * It should be called periodically.
461 * @param port Port to handle state machine.
464 mux_machine(struct bond_dev_private *internals, uint16_t slave_id)
466 struct port *port = &mode_8023ad_ports[slave_id];
468 /* Save current state for later use */
469 const uint8_t state_mask = STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |
472 /* Enter DETACHED state on BEGIN condition or from any other state if
473 * port was unselected */
474 if (SM_FLAG(port, BEGIN) ||
475 port->selected == UNSELECTED || (port->selected == STANDBY &&
476 (port->actor_state & state_mask) != 0)) {
477 /* detach mux from aggregator */
478 port->actor_state &= ~state_mask;
479 /* Set ntt to true if BEGIN condition or transition from any other state
480 * which is indicated that wait_while_timer was started */
481 if (SM_FLAG(port, BEGIN) ||
482 !timer_is_stopped(&port->wait_while_timer)) {
483 SM_FLAG_SET(port, NTT);
484 MODE4_DEBUG("-> DETACHED\n");
486 timer_cancel(&port->wait_while_timer);
489 if (timer_is_stopped(&port->wait_while_timer)) {
490 if (port->selected == SELECTED || port->selected == STANDBY) {
491 timer_set(&port->wait_while_timer,
492 internals->mode4.aggregate_wait_timeout);
494 MODE4_DEBUG("DETACHED -> WAITING\n");
496 /* Waiting state entered */
500 /* Transit next state if port is ready */
501 if (!timer_is_expired(&port->wait_while_timer))
504 if ((ACTOR_STATE(port, DISTRIBUTING) || ACTOR_STATE(port, COLLECTING)) &&
505 !PARTNER_STATE(port, SYNCHRONIZATION)) {
506 /* If in COLLECTING or DISTRIBUTING state and partner becomes out of
507 * sync transit to ATACHED state. */
508 ACTOR_STATE_CLR(port, DISTRIBUTING);
509 ACTOR_STATE_CLR(port, COLLECTING);
510 /* Clear actor sync to activate transit ATACHED in condition bellow */
511 ACTOR_STATE_CLR(port, SYNCHRONIZATION);
512 MODE4_DEBUG("Out of sync -> ATTACHED\n");
515 if (!ACTOR_STATE(port, SYNCHRONIZATION)) {
516 /* attach mux to aggregator */
517 RTE_ASSERT((port->actor_state & (STATE_COLLECTING |
518 STATE_DISTRIBUTING)) == 0);
520 ACTOR_STATE_SET(port, SYNCHRONIZATION);
521 SM_FLAG_SET(port, NTT);
522 MODE4_DEBUG("ATTACHED Entered\n");
523 } else if (!ACTOR_STATE(port, COLLECTING)) {
524 /* Start collecting if in sync */
525 if (PARTNER_STATE(port, SYNCHRONIZATION)) {
526 MODE4_DEBUG("ATTACHED -> COLLECTING\n");
527 ACTOR_STATE_SET(port, COLLECTING);
528 SM_FLAG_SET(port, NTT);
530 } else if (ACTOR_STATE(port, COLLECTING)) {
531 /* Check if partner is in COLLECTING state. If so this port can
532 * distribute frames to it */
533 if (!ACTOR_STATE(port, DISTRIBUTING)) {
534 if (PARTNER_STATE(port, COLLECTING)) {
535 /* Enable DISTRIBUTING if partner is collecting */
536 ACTOR_STATE_SET(port, DISTRIBUTING);
537 SM_FLAG_SET(port, NTT);
538 MODE4_DEBUG("COLLECTING -> DISTRIBUTING\n");
540 "Bond %u: slave id %u distributing started.\n",
541 internals->port_id, slave_id);
544 if (!PARTNER_STATE(port, COLLECTING)) {
545 /* Disable DISTRIBUTING (enter COLLECTING state) if partner
546 * is not collecting */
547 ACTOR_STATE_CLR(port, DISTRIBUTING);
548 SM_FLAG_SET(port, NTT);
549 MODE4_DEBUG("DISTRIBUTING -> COLLECTING\n");
551 "Bond %u: slave id %u distributing stopped.\n",
552 internals->port_id, slave_id);
559 * Function handles transmit state machine.
561 * Function implements Transmit Machine from point 5.4.16 in 802.1AX
567 tx_machine(struct bond_dev_private *internals, uint16_t slave_id)
569 struct port *agg, *port = &mode_8023ad_ports[slave_id];
571 struct rte_mbuf *lacp_pkt = NULL;
572 struct lacpdu_header *hdr;
573 struct lacpdu *lacpdu;
575 /* If periodic timer is not running periodic machine is in NO PERIODIC and
576 * according to 802.3ax standard tx machine should not transmit any frames
577 * and set ntt to false. */
578 if (timer_is_stopped(&port->periodic_timer))
579 SM_FLAG_CLR(port, NTT);
581 if (!SM_FLAG(port, NTT))
584 if (!timer_is_expired(&port->tx_machine_timer))
587 lacp_pkt = rte_pktmbuf_alloc(port->mbuf_pool);
588 if (lacp_pkt == NULL) {
589 RTE_LOG(ERR, PMD, "Failed to allocate LACP packet from pool\n");
593 lacp_pkt->data_len = sizeof(*hdr);
594 lacp_pkt->pkt_len = sizeof(*hdr);
596 hdr = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
598 /* Source and destination MAC */
599 ether_addr_copy(&lacp_mac_addr, &hdr->eth_hdr.d_addr);
600 rte_eth_macaddr_get(slave_id, &hdr->eth_hdr.s_addr);
601 hdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW);
603 lacpdu = &hdr->lacpdu;
604 memset(lacpdu, 0, sizeof(*lacpdu));
606 /* Initialize LACP part */
607 lacpdu->subtype = SLOW_SUBTYPE_LACP;
608 lacpdu->version_number = 1;
611 lacpdu->actor.tlv_type_info = TLV_TYPE_ACTOR_INFORMATION;
612 lacpdu->actor.info_length = sizeof(struct lacpdu_actor_partner_params);
613 memcpy(&hdr->lacpdu.actor.port_params, &port->actor,
614 sizeof(port->actor));
615 agg = &mode_8023ad_ports[port->aggregator_port_id];
616 ether_addr_copy(&agg->actor.system, &hdr->lacpdu.actor.port_params.system);
617 lacpdu->actor.state = port->actor_state;
620 lacpdu->partner.tlv_type_info = TLV_TYPE_PARTNER_INFORMATION;
621 lacpdu->partner.info_length = sizeof(struct lacpdu_actor_partner_params);
622 memcpy(&lacpdu->partner.port_params, &port->partner,
623 sizeof(struct port_params));
624 lacpdu->partner.state = port->partner_state;
627 lacpdu->tlv_type_collector_info = TLV_TYPE_COLLECTOR_INFORMATION;
628 lacpdu->collector_info_length = 0x10;
629 lacpdu->collector_max_delay = 0;
631 lacpdu->tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION;
632 lacpdu->terminator_length = 0;
634 MODE4_DEBUG("Sending LACP frame\n");
635 BOND_PRINT_LACP(lacpdu);
637 if (internals->mode4.dedicated_queues.enabled == 0) {
638 int retval = rte_ring_enqueue(port->tx_ring, lacp_pkt);
640 /* If TX ring full, drop packet and free message.
641 Retransmission will happen in next function call. */
642 rte_pktmbuf_free(lacp_pkt);
643 set_warning_flags(port, WRN_TX_QUEUE_FULL);
647 uint16_t pkts_sent = rte_eth_tx_burst(slave_id,
648 internals->mode4.dedicated_queues.tx_qid,
650 if (pkts_sent != 1) {
651 rte_pktmbuf_free(lacp_pkt);
652 set_warning_flags(port, WRN_TX_QUEUE_FULL);
658 timer_set(&port->tx_machine_timer, internals->mode4.tx_period_timeout);
659 SM_FLAG_CLR(port, NTT);
663 max_index(uint64_t *a, int n)
671 for (i = 1; i < n; ++i) {
682 * Function assigns port to aggregator.
684 * @param bond_dev_private Pointer to bond_dev_private structure.
685 * @param port_pos Port to assign.
688 selection_logic(struct bond_dev_private *internals, uint8_t slave_id)
690 struct port *agg, *port;
691 uint16_t slaves_count, new_agg_id, i, j = 0;
693 uint64_t agg_bandwidth[8] = {0};
694 uint64_t agg_count[8] = {0};
695 uint16_t default_slave = 0;
696 uint8_t mode_count_id, mode_band_id;
697 struct rte_eth_link link_info;
699 slaves = internals->active_slaves;
700 slaves_count = internals->active_slave_count;
701 port = &mode_8023ad_ports[slave_id];
703 /* Search for aggregator suitable for this port */
704 for (i = 0; i < slaves_count; ++i) {
705 agg = &mode_8023ad_ports[slaves[i]];
706 /* Skip ports that are not aggreagators */
707 if (agg->aggregator_port_id != slaves[i])
710 agg_count[agg->aggregator_port_id] += 1;
711 rte_eth_link_get_nowait(slaves[i], &link_info);
712 agg_bandwidth[agg->aggregator_port_id] += link_info.link_speed;
714 /* Actors system ID is not checked since all slave device have the same
715 * ID (MAC address). */
716 if ((agg->actor.key == port->actor.key &&
717 agg->partner.system_priority == port->partner.system_priority &&
718 is_same_ether_addr(&agg->partner.system, &port->partner.system) == 1
719 && (agg->partner.key == port->partner.key)) &&
720 is_zero_ether_addr(&port->partner.system) != 1 &&
722 rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) != 0) {
730 switch (internals->mode4.agg_selection) {
732 mode_count_id = max_index(
733 (uint64_t *)agg_count, slaves_count);
734 new_agg_id = mode_count_id;
737 mode_band_id = max_index(
738 (uint64_t *)agg_bandwidth, slaves_count);
739 new_agg_id = mode_band_id;
742 if (default_slave == slaves_count)
743 new_agg_id = slave_id;
745 new_agg_id = slaves[default_slave];
748 if (default_slave == slaves_count)
749 new_agg_id = slave_id;
751 new_agg_id = slaves[default_slave];
755 if (new_agg_id != port->aggregator_port_id) {
756 port->aggregator_port_id = new_agg_id;
758 MODE4_DEBUG("-> SELECTED: ID=%3u\n"
759 "\t%s aggregator ID=%3u\n",
760 port->aggregator_port_id,
761 port->aggregator_port_id == slave_id ?
762 "aggregator not found, using default" : "aggregator found",
763 port->aggregator_port_id);
766 port->selected = SELECTED;
769 /* Function maps DPDK speed to bonding speed stored in key field */
771 link_speed_key(uint16_t speed) {
775 case ETH_SPEED_NUM_NONE:
778 case ETH_SPEED_NUM_10M:
779 key_speed = BOND_LINK_SPEED_KEY_10M;
781 case ETH_SPEED_NUM_100M:
782 key_speed = BOND_LINK_SPEED_KEY_100M;
784 case ETH_SPEED_NUM_1G:
785 key_speed = BOND_LINK_SPEED_KEY_1000M;
787 case ETH_SPEED_NUM_10G:
788 key_speed = BOND_LINK_SPEED_KEY_10G;
790 case ETH_SPEED_NUM_20G:
791 key_speed = BOND_LINK_SPEED_KEY_20G;
793 case ETH_SPEED_NUM_40G:
794 key_speed = BOND_LINK_SPEED_KEY_40G;
805 rx_machine_update(struct bond_dev_private *internals, uint8_t slave_id,
806 struct rte_mbuf *lacp_pkt) {
807 struct lacpdu_header *lacp;
809 if (lacp_pkt != NULL) {
810 lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
811 RTE_ASSERT(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
813 /* This is LACP frame so pass it to rx_machine */
814 rx_machine(internals, slave_id, &lacp->lacpdu);
815 rte_pktmbuf_free(lacp_pkt);
817 rx_machine(internals, slave_id, NULL);
821 bond_mode_8023ad_periodic_cb(void *arg)
823 struct rte_eth_dev *bond_dev = arg;
824 struct bond_dev_private *internals = bond_dev->data->dev_private;
826 struct rte_eth_link link_info;
827 struct ether_addr slave_addr;
828 struct rte_mbuf *lacp_pkt = NULL;
833 /* Update link status on each port */
834 for (i = 0; i < internals->active_slave_count; i++) {
837 slave_id = internals->active_slaves[i];
838 rte_eth_link_get_nowait(slave_id, &link_info);
839 rte_eth_macaddr_get(slave_id, &slave_addr);
841 if (link_info.link_status != 0) {
842 key = link_speed_key(link_info.link_speed) << 1;
843 if (link_info.link_duplex == ETH_LINK_FULL_DUPLEX)
844 key |= BOND_LINK_FULL_DUPLEX_KEY;
848 port = &mode_8023ad_ports[slave_id];
850 key = rte_cpu_to_be_16(key);
851 if (key != port->actor.key) {
852 if (!(key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)))
853 set_warning_flags(port, WRN_NOT_LACP_CAPABLE);
855 port->actor.key = key;
856 SM_FLAG_SET(port, NTT);
859 if (!is_same_ether_addr(&port->actor.system, &slave_addr)) {
860 ether_addr_copy(&slave_addr, &port->actor.system);
861 if (port->aggregator_port_id == slave_id)
862 SM_FLAG_SET(port, NTT);
866 for (i = 0; i < internals->active_slave_count; i++) {
867 slave_id = internals->active_slaves[i];
868 port = &mode_8023ad_ports[slave_id];
870 if ((port->actor.key &
871 rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) == 0) {
873 SM_FLAG_SET(port, BEGIN);
875 /* LACP is disabled on half duples or link is down */
876 if (SM_FLAG(port, LACP_ENABLED)) {
877 /* If port was enabled set it to BEGIN state */
878 SM_FLAG_CLR(port, LACP_ENABLED);
879 ACTOR_STATE_CLR(port, DISTRIBUTING);
880 ACTOR_STATE_CLR(port, COLLECTING);
883 /* Skip this port processing */
887 SM_FLAG_SET(port, LACP_ENABLED);
889 if (internals->mode4.dedicated_queues.enabled == 0) {
890 /* Find LACP packet to this port. Do not check subtype,
891 * it is done in function that queued packet
893 int retval = rte_ring_dequeue(port->rx_ring,
899 rx_machine_update(internals, slave_id, lacp_pkt);
901 uint16_t rx_count = rte_eth_rx_burst(slave_id,
902 internals->mode4.dedicated_queues.rx_qid,
906 bond_mode_8023ad_handle_slow_pkt(internals,
909 rx_machine_update(internals, slave_id, NULL);
912 periodic_machine(internals, slave_id);
913 mux_machine(internals, slave_id);
914 tx_machine(internals, slave_id);
915 selection_logic(internals, slave_id);
917 SM_FLAG_CLR(port, BEGIN);
918 show_warnings(slave_id);
921 rte_eal_alarm_set(internals->mode4.update_timeout_us,
922 bond_mode_8023ad_periodic_cb, arg);
926 bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev,
929 struct bond_dev_private *internals = bond_dev->data->dev_private;
931 struct port *port = &mode_8023ad_ports[slave_id];
932 struct port_params initial = {
934 .system_priority = rte_cpu_to_be_16(0xFFFF),
935 .key = rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY),
936 .port_priority = rte_cpu_to_be_16(0x00FF),
940 char mem_name[RTE_ETH_NAME_MAX_LEN];
942 unsigned element_size;
943 uint32_t total_tx_desc;
944 struct bond_tx_queue *bd_tx_q;
947 /* Given slave mus not be in active list */
948 RTE_ASSERT(find_slave_by_id(internals->active_slaves,
949 internals->active_slave_count, slave_id) == internals->active_slave_count);
950 RTE_SET_USED(internals); /* used only for assert when enabled */
952 memcpy(&port->actor, &initial, sizeof(struct port_params));
953 /* Standard requires that port ID must be grater than 0.
954 * Add 1 do get corresponding port_number */
955 port->actor.port_number = rte_cpu_to_be_16(slave_id + 1);
957 memcpy(&port->partner, &initial, sizeof(struct port_params));
960 port->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED;
961 port->partner_state = STATE_LACP_ACTIVE | STATE_AGGREGATION;
962 port->sm_flags = SM_FLAGS_BEGIN;
964 /* use this port as agregator */
965 port->aggregator_port_id = slave_id;
966 rte_eth_promiscuous_enable(slave_id);
968 timer_cancel(&port->warning_timer);
970 if (port->mbuf_pool != NULL)
973 RTE_ASSERT(port->rx_ring == NULL);
974 RTE_ASSERT(port->tx_ring == NULL);
976 socket_id = rte_eth_dev_socket_id(slave_id);
977 if (socket_id == (int)LCORE_ID_ANY)
978 socket_id = rte_socket_id();
980 element_size = sizeof(struct slow_protocol_frame) +
981 RTE_PKTMBUF_HEADROOM;
983 /* The size of the mempool should be at least:
984 * the sum of the TX descriptors + BOND_MODE_8023AX_SLAVE_TX_PKTS */
985 total_tx_desc = BOND_MODE_8023AX_SLAVE_TX_PKTS;
986 for (q_id = 0; q_id < bond_dev->data->nb_tx_queues; q_id++) {
987 bd_tx_q = (struct bond_tx_queue*)bond_dev->data->tx_queues[q_id];
988 total_tx_desc += bd_tx_q->nb_tx_desc;
991 snprintf(mem_name, RTE_DIM(mem_name), "slave_port%u_pool", slave_id);
992 port->mbuf_pool = rte_pktmbuf_pool_create(mem_name, total_tx_desc,
993 RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ?
994 32 : RTE_MEMPOOL_CACHE_MAX_SIZE,
995 0, element_size, socket_id);
997 /* Any memory allocation failure in initialization is critical because
998 * resources can't be free, so reinitialization is impossible. */
999 if (port->mbuf_pool == NULL) {
1000 rte_panic("Slave %u: Failed to create memory pool '%s': %s\n",
1001 slave_id, mem_name, rte_strerror(rte_errno));
1004 snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_rx", slave_id);
1005 port->rx_ring = rte_ring_create(mem_name,
1006 rte_align32pow2(BOND_MODE_8023AX_SLAVE_RX_PKTS), socket_id, 0);
1008 if (port->rx_ring == NULL) {
1009 rte_panic("Slave %u: Failed to create rx ring '%s': %s\n", slave_id,
1010 mem_name, rte_strerror(rte_errno));
1013 /* TX ring is at least one pkt longer to make room for marker packet. */
1014 snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_tx", slave_id);
1015 port->tx_ring = rte_ring_create(mem_name,
1016 rte_align32pow2(BOND_MODE_8023AX_SLAVE_TX_PKTS + 1), socket_id, 0);
1018 if (port->tx_ring == NULL) {
1019 rte_panic("Slave %u: Failed to create tx ring '%s': %s\n", slave_id,
1020 mem_name, rte_strerror(rte_errno));
1025 bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev __rte_unused,
1029 struct port *port = NULL;
1030 uint8_t old_partner_state;
1032 port = &mode_8023ad_ports[slave_id];
1034 ACTOR_STATE_CLR(port, AGGREGATION);
1035 port->selected = UNSELECTED;
1037 old_partner_state = port->partner_state;
1038 record_default(port);
1040 /* If partner timeout state changes then disable timer */
1041 if (!((old_partner_state ^ port->partner_state) &
1042 STATE_LACP_SHORT_TIMEOUT))
1043 timer_cancel(&port->current_while_timer);
1045 PARTNER_STATE_CLR(port, AGGREGATION);
1046 ACTOR_STATE_CLR(port, EXPIRED);
1048 /* flush rx/tx rings */
1049 while (rte_ring_dequeue(port->rx_ring, &pkt) == 0)
1050 rte_pktmbuf_free((struct rte_mbuf *)pkt);
1052 while (rte_ring_dequeue(port->tx_ring, &pkt) == 0)
1053 rte_pktmbuf_free((struct rte_mbuf *)pkt);
1058 bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev)
1060 struct bond_dev_private *internals = bond_dev->data->dev_private;
1061 struct ether_addr slave_addr;
1062 struct port *slave, *agg_slave;
1063 uint16_t slave_id, i, j;
1065 bond_mode_8023ad_stop(bond_dev);
1067 for (i = 0; i < internals->active_slave_count; i++) {
1068 slave_id = internals->active_slaves[i];
1069 slave = &mode_8023ad_ports[slave_id];
1070 rte_eth_macaddr_get(slave_id, &slave_addr);
1072 if (is_same_ether_addr(&slave_addr, &slave->actor.system))
1075 ether_addr_copy(&slave_addr, &slave->actor.system);
1076 /* Do nothing if this port is not an aggregator. In other case
1077 * Set NTT flag on every port that use this aggregator. */
1078 if (slave->aggregator_port_id != slave_id)
1081 for (j = 0; j < internals->active_slave_count; j++) {
1082 agg_slave = &mode_8023ad_ports[internals->active_slaves[j]];
1083 if (agg_slave->aggregator_port_id == slave_id)
1084 SM_FLAG_SET(agg_slave, NTT);
1088 if (bond_dev->data->dev_started)
1089 bond_mode_8023ad_start(bond_dev);
1093 bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
1094 struct rte_eth_bond_8023ad_conf *conf)
1096 struct bond_dev_private *internals = dev->data->dev_private;
1097 struct mode8023ad_private *mode4 = &internals->mode4;
1098 uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
1100 conf->fast_periodic_ms = mode4->fast_periodic_timeout / ms_ticks;
1101 conf->slow_periodic_ms = mode4->slow_periodic_timeout / ms_ticks;
1102 conf->short_timeout_ms = mode4->short_timeout / ms_ticks;
1103 conf->long_timeout_ms = mode4->long_timeout / ms_ticks;
1104 conf->aggregate_wait_timeout_ms = mode4->aggregate_wait_timeout / ms_ticks;
1105 conf->tx_period_ms = mode4->tx_period_timeout / ms_ticks;
1106 conf->update_timeout_ms = mode4->update_timeout_us / 1000;
1107 conf->rx_marker_period_ms = mode4->rx_marker_timeout / ms_ticks;
1108 conf->slowrx_cb = mode4->slowrx_cb;
1109 conf->agg_selection = mode4->agg_selection;
1113 bond_mode_8023ad_conf_get_default(struct rte_eth_bond_8023ad_conf *conf)
1115 conf->fast_periodic_ms = BOND_8023AD_FAST_PERIODIC_MS;
1116 conf->slow_periodic_ms = BOND_8023AD_SLOW_PERIODIC_MS;
1117 conf->short_timeout_ms = BOND_8023AD_SHORT_TIMEOUT_MS;
1118 conf->long_timeout_ms = BOND_8023AD_LONG_TIMEOUT_MS;
1119 conf->aggregate_wait_timeout_ms = BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS;
1120 conf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS;
1121 conf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS;
1122 conf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS;
1123 conf->slowrx_cb = NULL;
1124 conf->agg_selection = AGG_STABLE;
1128 bond_mode_8023ad_conf_assign(struct mode8023ad_private *mode4,
1129 struct rte_eth_bond_8023ad_conf *conf)
1131 uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
1133 mode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks;
1134 mode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks;
1135 mode4->short_timeout = conf->short_timeout_ms * ms_ticks;
1136 mode4->long_timeout = conf->long_timeout_ms * ms_ticks;
1137 mode4->aggregate_wait_timeout = conf->aggregate_wait_timeout_ms * ms_ticks;
1138 mode4->tx_period_timeout = conf->tx_period_ms * ms_ticks;
1139 mode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks;
1140 mode4->update_timeout_us = conf->update_timeout_ms * 1000;
1142 mode4->dedicated_queues.enabled = 0;
1143 mode4->dedicated_queues.rx_qid = UINT16_MAX;
1144 mode4->dedicated_queues.tx_qid = UINT16_MAX;
1148 bond_mode_8023ad_setup(struct rte_eth_dev *dev,
1149 struct rte_eth_bond_8023ad_conf *conf)
1151 struct rte_eth_bond_8023ad_conf def_conf;
1152 struct bond_dev_private *internals = dev->data->dev_private;
1153 struct mode8023ad_private *mode4 = &internals->mode4;
1157 bond_mode_8023ad_conf_get_default(conf);
1160 bond_mode_8023ad_stop(dev);
1161 bond_mode_8023ad_conf_assign(mode4, conf);
1162 mode4->slowrx_cb = conf->slowrx_cb;
1163 mode4->agg_selection = AGG_STABLE;
1165 if (dev->data->dev_started)
1166 bond_mode_8023ad_start(dev);
1170 bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)
1172 struct bond_dev_private *internals = bond_dev->data->dev_private;
1175 for (i = 0; i < internals->active_slave_count; i++)
1176 bond_mode_8023ad_activate_slave(bond_dev, i);
1182 bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)
1184 struct bond_dev_private *internals = bond_dev->data->dev_private;
1185 struct mode8023ad_private *mode4 = &internals->mode4;
1186 static const uint64_t us = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000;
1188 if (mode4->slowrx_cb)
1189 return rte_eal_alarm_set(us, &bond_mode_8023ad_ext_periodic_cb,
1192 return rte_eal_alarm_set(us, &bond_mode_8023ad_periodic_cb, bond_dev);
1196 bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev)
1198 struct bond_dev_private *internals = bond_dev->data->dev_private;
1199 struct mode8023ad_private *mode4 = &internals->mode4;
1201 if (mode4->slowrx_cb) {
1202 rte_eal_alarm_cancel(&bond_mode_8023ad_ext_periodic_cb,
1206 rte_eal_alarm_cancel(&bond_mode_8023ad_periodic_cb, bond_dev);
1210 bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
1211 uint16_t slave_id, struct rte_mbuf *pkt)
1213 struct mode8023ad_private *mode4 = &internals->mode4;
1214 struct port *port = &mode_8023ad_ports[slave_id];
1215 struct marker_header *m_hdr;
1216 uint64_t marker_timer, old_marker_timer;
1218 uint8_t wrn, subtype;
1219 /* If packet is a marker, we send response now by reusing given packet
1220 * and update only source MAC, destination MAC is multicast so don't
1221 * update it. Other frames will be handled later by state machines */
1222 subtype = rte_pktmbuf_mtod(pkt,
1223 struct slow_protocol_frame *)->slow_protocol.subtype;
1225 if (subtype == SLOW_SUBTYPE_MARKER) {
1226 m_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *);
1228 if (likely(m_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_INFO)) {
1229 wrn = WRN_UNKNOWN_MARKER_TYPE;
1233 /* Setup marker timer. Do it in loop in case concurrent access. */
1235 old_marker_timer = port->rx_marker_timer;
1236 if (!timer_is_expired(&old_marker_timer)) {
1237 wrn = WRN_RX_MARKER_TO_FAST;
1241 timer_set(&marker_timer, mode4->rx_marker_timeout);
1242 retval = rte_atomic64_cmpset(&port->rx_marker_timer,
1243 old_marker_timer, marker_timer);
1244 } while (unlikely(retval == 0));
1246 m_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP;
1247 rte_eth_macaddr_get(slave_id, &m_hdr->eth_hdr.s_addr);
1249 if (internals->mode4.dedicated_queues.enabled == 0) {
1250 int retval = rte_ring_enqueue(port->tx_ring, pkt);
1253 port->rx_marker_timer = 0;
1254 wrn = WRN_TX_QUEUE_FULL;
1258 /* Send packet directly to the slow queue */
1259 uint16_t tx_count = rte_eth_tx_burst(slave_id,
1260 internals->mode4.dedicated_queues.tx_qid,
1262 if (tx_count != 1) {
1264 port->rx_marker_timer = 0;
1265 wrn = WRN_TX_QUEUE_FULL;
1269 } else if (likely(subtype == SLOW_SUBTYPE_LACP)) {
1270 if (internals->mode4.dedicated_queues.enabled == 0) {
1271 int retval = rte_ring_enqueue(port->rx_ring, pkt);
1273 /* If RX fing full free lacpdu message and drop packet */
1274 wrn = WRN_RX_QUEUE_FULL;
1278 rx_machine_update(internals, slave_id, pkt);
1280 wrn = WRN_UNKNOWN_SLOW_TYPE;
1287 set_warning_flags(port, wrn);
1288 rte_pktmbuf_free(pkt);
1292 rte_eth_bond_8023ad_conf_get(uint16_t port_id,
1293 struct rte_eth_bond_8023ad_conf *conf)
1295 struct rte_eth_dev *bond_dev;
1297 if (valid_bonded_port_id(port_id) != 0)
1303 bond_dev = &rte_eth_devices[port_id];
1304 bond_mode_8023ad_conf_get(bond_dev, conf);
1309 rte_eth_bond_8023ad_agg_selection_set(uint16_t port_id,
1310 enum rte_bond_8023ad_agg_selection agg_selection)
1312 struct rte_eth_dev *bond_dev;
1313 struct bond_dev_private *internals;
1314 struct mode8023ad_private *mode4;
1316 bond_dev = &rte_eth_devices[port_id];
1317 internals = bond_dev->data->dev_private;
1319 if (valid_bonded_port_id(port_id) != 0)
1321 if (internals->mode != 4)
1324 mode4 = &internals->mode4;
1325 if (agg_selection == AGG_COUNT || agg_selection == AGG_BANDWIDTH
1326 || agg_selection == AGG_STABLE)
1327 mode4->agg_selection = agg_selection;
1331 int rte_eth_bond_8023ad_agg_selection_get(uint16_t port_id)
1333 struct rte_eth_dev *bond_dev;
1334 struct bond_dev_private *internals;
1335 struct mode8023ad_private *mode4;
1337 bond_dev = &rte_eth_devices[port_id];
1338 internals = bond_dev->data->dev_private;
1340 if (valid_bonded_port_id(port_id) != 0)
1342 if (internals->mode != 4)
1344 mode4 = &internals->mode4;
1346 return mode4->agg_selection;
1352 bond_8023ad_setup_validate(uint16_t port_id,
1353 struct rte_eth_bond_8023ad_conf *conf)
1355 if (valid_bonded_port_id(port_id) != 0)
1359 /* Basic sanity check */
1360 if (conf->slow_periodic_ms == 0 ||
1361 conf->fast_periodic_ms >= conf->slow_periodic_ms ||
1362 conf->long_timeout_ms == 0 ||
1363 conf->short_timeout_ms >= conf->long_timeout_ms ||
1364 conf->aggregate_wait_timeout_ms == 0 ||
1365 conf->tx_period_ms == 0 ||
1366 conf->rx_marker_period_ms == 0 ||
1367 conf->update_timeout_ms == 0) {
1368 RTE_LOG(ERR, PMD, "given mode 4 configuration is invalid\n");
1378 rte_eth_bond_8023ad_setup(uint16_t port_id,
1379 struct rte_eth_bond_8023ad_conf *conf)
1381 struct rte_eth_dev *bond_dev;
1384 err = bond_8023ad_setup_validate(port_id, conf);
1388 bond_dev = &rte_eth_devices[port_id];
1389 bond_mode_8023ad_setup(bond_dev, conf);
1399 rte_eth_bond_8023ad_slave_info(uint16_t port_id, uint16_t slave_id,
1400 struct rte_eth_bond_8023ad_slave_info *info)
1402 struct rte_eth_dev *bond_dev;
1403 struct bond_dev_private *internals;
1406 if (info == NULL || valid_bonded_port_id(port_id) != 0 ||
1407 rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
1410 bond_dev = &rte_eth_devices[port_id];
1412 internals = bond_dev->data->dev_private;
1413 if (find_slave_by_id(internals->active_slaves,
1414 internals->active_slave_count, slave_id) ==
1415 internals->active_slave_count)
1418 port = &mode_8023ad_ports[slave_id];
1419 info->selected = port->selected;
1421 info->actor_state = port->actor_state;
1422 rte_memcpy(&info->actor, &port->actor, sizeof(port->actor));
1424 info->partner_state = port->partner_state;
1425 rte_memcpy(&info->partner, &port->partner, sizeof(port->partner));
1427 info->agg_port_id = port->aggregator_port_id;
1432 bond_8023ad_ext_validate(uint16_t port_id, uint16_t slave_id)
1434 struct rte_eth_dev *bond_dev;
1435 struct bond_dev_private *internals;
1436 struct mode8023ad_private *mode4;
1438 if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
1441 bond_dev = &rte_eth_devices[port_id];
1443 if (!bond_dev->data->dev_started)
1446 internals = bond_dev->data->dev_private;
1447 if (find_slave_by_id(internals->active_slaves,
1448 internals->active_slave_count, slave_id) ==
1449 internals->active_slave_count)
1452 mode4 = &internals->mode4;
1453 if (mode4->slowrx_cb == NULL)
1460 rte_eth_bond_8023ad_ext_collect(uint16_t port_id, uint16_t slave_id,
1466 res = bond_8023ad_ext_validate(port_id, slave_id);
1470 port = &mode_8023ad_ports[slave_id];
1473 ACTOR_STATE_SET(port, COLLECTING);
1475 ACTOR_STATE_CLR(port, COLLECTING);
1481 rte_eth_bond_8023ad_ext_distrib(uint16_t port_id, uint16_t slave_id,
1487 res = bond_8023ad_ext_validate(port_id, slave_id);
1491 port = &mode_8023ad_ports[slave_id];
1494 ACTOR_STATE_SET(port, DISTRIBUTING);
1496 ACTOR_STATE_CLR(port, DISTRIBUTING);
1502 rte_eth_bond_8023ad_ext_distrib_get(uint16_t port_id, uint16_t slave_id)
1507 err = bond_8023ad_ext_validate(port_id, slave_id);
1511 port = &mode_8023ad_ports[slave_id];
1512 return ACTOR_STATE(port, DISTRIBUTING);
1516 rte_eth_bond_8023ad_ext_collect_get(uint16_t port_id, uint16_t slave_id)
1521 err = bond_8023ad_ext_validate(port_id, slave_id);
1525 port = &mode_8023ad_ports[slave_id];
1526 return ACTOR_STATE(port, COLLECTING);
1530 rte_eth_bond_8023ad_ext_slowtx(uint16_t port_id, uint16_t slave_id,
1531 struct rte_mbuf *lacp_pkt)
1536 res = bond_8023ad_ext_validate(port_id, slave_id);
1540 port = &mode_8023ad_ports[slave_id];
1542 if (rte_pktmbuf_pkt_len(lacp_pkt) < sizeof(struct lacpdu_header))
1545 struct lacpdu_header *lacp;
1547 /* only enqueue LACPDUs */
1548 lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
1549 if (lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
1552 MODE4_DEBUG("sending LACP frame\n");
1554 return rte_ring_enqueue(port->tx_ring, lacp_pkt);
1558 bond_mode_8023ad_ext_periodic_cb(void *arg)
1560 struct rte_eth_dev *bond_dev = arg;
1561 struct bond_dev_private *internals = bond_dev->data->dev_private;
1562 struct mode8023ad_private *mode4 = &internals->mode4;
1565 uint16_t i, slave_id;
1567 for (i = 0; i < internals->active_slave_count; i++) {
1568 slave_id = internals->active_slaves[i];
1569 port = &mode_8023ad_ports[slave_id];
1571 if (rte_ring_dequeue(port->rx_ring, &pkt) == 0) {
1572 struct rte_mbuf *lacp_pkt = pkt;
1573 struct lacpdu_header *lacp;
1575 lacp = rte_pktmbuf_mtod(lacp_pkt,
1576 struct lacpdu_header *);
1577 RTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
1579 /* This is LACP frame so pass it to rx callback.
1580 * Callback is responsible for freeing mbuf.
1582 mode4->slowrx_cb(slave_id, lacp_pkt);
1586 rte_eal_alarm_set(internals->mode4.update_timeout_us,
1587 bond_mode_8023ad_ext_periodic_cb, arg);
1591 rte_eth_bond_8023ad_dedicated_queues_enable(uint16_t port)
1594 struct rte_eth_dev *dev = &rte_eth_devices[port];
1595 struct bond_dev_private *internals = (struct bond_dev_private *)
1596 dev->data->dev_private;
1598 if (check_for_bonded_ethdev(dev) != 0)
1601 if (bond_8023ad_slow_pkt_hw_filter_supported(port) != 0)
1604 /* Device must be stopped to set up slow queue */
1605 if (dev->data->dev_started)
1608 internals->mode4.dedicated_queues.enabled = 1;
1610 bond_ethdev_mode_set(dev, internals->mode);
1615 rte_eth_bond_8023ad_dedicated_queues_disable(uint16_t port)
1618 struct rte_eth_dev *dev = &rte_eth_devices[port];
1619 struct bond_dev_private *internals = (struct bond_dev_private *)
1620 dev->data->dev_private;
1622 if (check_for_bonded_ethdev(dev) != 0)
1625 /* Device must be stopped to set up slow queue */
1626 if (dev->data->dev_started)
1629 internals->mode4.dedicated_queues.enabled = 0;
1631 bond_ethdev_mode_set(dev, internals->mode);