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(uint8_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, uint8_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, uint8_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, uint8_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, uint8_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 uint8_t slaves_count, new_agg_id, i, j = 0;
693 uint64_t agg_bandwidth[8] = {0};
694 uint64_t agg_count[8] = {0};
695 uint8_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, uint8_t slave_id)
928 struct bond_dev_private *internals = bond_dev->data->dev_private;
930 struct port *port = &mode_8023ad_ports[slave_id];
931 struct port_params initial = {
933 .system_priority = rte_cpu_to_be_16(0xFFFF),
934 .key = rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY),
935 .port_priority = rte_cpu_to_be_16(0x00FF),
939 char mem_name[RTE_ETH_NAME_MAX_LEN];
941 unsigned element_size;
942 uint32_t total_tx_desc;
943 struct bond_tx_queue *bd_tx_q;
946 /* Given slave mus not be in active list */
947 RTE_ASSERT(find_slave_by_id(internals->active_slaves,
948 internals->active_slave_count, slave_id) == internals->active_slave_count);
949 RTE_SET_USED(internals); /* used only for assert when enabled */
951 memcpy(&port->actor, &initial, sizeof(struct port_params));
952 /* Standard requires that port ID must be grater than 0.
953 * Add 1 do get corresponding port_number */
954 port->actor.port_number = rte_cpu_to_be_16((uint16_t)slave_id + 1);
956 memcpy(&port->partner, &initial, sizeof(struct port_params));
959 port->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED;
960 port->partner_state = STATE_LACP_ACTIVE | STATE_AGGREGATION;
961 port->sm_flags = SM_FLAGS_BEGIN;
963 /* use this port as agregator */
964 port->aggregator_port_id = slave_id;
965 rte_eth_promiscuous_enable(slave_id);
967 timer_cancel(&port->warning_timer);
969 if (port->mbuf_pool != NULL)
972 RTE_ASSERT(port->rx_ring == NULL);
973 RTE_ASSERT(port->tx_ring == NULL);
975 socket_id = rte_eth_dev_socket_id(slave_id);
976 if (socket_id == (int)LCORE_ID_ANY)
977 socket_id = rte_socket_id();
979 element_size = sizeof(struct slow_protocol_frame) +
980 RTE_PKTMBUF_HEADROOM;
982 /* The size of the mempool should be at least:
983 * the sum of the TX descriptors + BOND_MODE_8023AX_SLAVE_TX_PKTS */
984 total_tx_desc = BOND_MODE_8023AX_SLAVE_TX_PKTS;
985 for (q_id = 0; q_id < bond_dev->data->nb_tx_queues; q_id++) {
986 bd_tx_q = (struct bond_tx_queue*)bond_dev->data->tx_queues[q_id];
987 total_tx_desc += bd_tx_q->nb_tx_desc;
990 snprintf(mem_name, RTE_DIM(mem_name), "slave_port%u_pool", slave_id);
991 port->mbuf_pool = rte_pktmbuf_pool_create(mem_name, total_tx_desc,
992 RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ?
993 32 : RTE_MEMPOOL_CACHE_MAX_SIZE,
994 0, element_size, socket_id);
996 /* Any memory allocation failure in initialization is critical because
997 * resources can't be free, so reinitialization is impossible. */
998 if (port->mbuf_pool == NULL) {
999 rte_panic("Slave %u: Failed to create memory pool '%s': %s\n",
1000 slave_id, mem_name, rte_strerror(rte_errno));
1003 snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_rx", slave_id);
1004 port->rx_ring = rte_ring_create(mem_name,
1005 rte_align32pow2(BOND_MODE_8023AX_SLAVE_RX_PKTS), socket_id, 0);
1007 if (port->rx_ring == NULL) {
1008 rte_panic("Slave %u: Failed to create rx ring '%s': %s\n", slave_id,
1009 mem_name, rte_strerror(rte_errno));
1012 /* TX ring is at least one pkt longer to make room for marker packet. */
1013 snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_tx", slave_id);
1014 port->tx_ring = rte_ring_create(mem_name,
1015 rte_align32pow2(BOND_MODE_8023AX_SLAVE_TX_PKTS + 1), socket_id, 0);
1017 if (port->tx_ring == NULL) {
1018 rte_panic("Slave %u: Failed to create tx ring '%s': %s\n", slave_id,
1019 mem_name, rte_strerror(rte_errno));
1024 bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev,
1027 struct bond_dev_private *internals = bond_dev->data->dev_private;
1032 /* Given slave must be in active list */
1033 RTE_ASSERT(find_slave_by_id(internals->active_slaves,
1034 internals->active_slave_count, slave_id) < internals->active_slave_count);
1036 /* Exclude slave from transmit policy. If this slave is an aggregator
1037 * make all aggregated slaves unselected to force selection logic
1038 * to select suitable aggregator for this port. */
1039 for (i = 0; i < internals->active_slave_count; i++) {
1040 port = &mode_8023ad_ports[internals->active_slaves[i]];
1041 if (port->aggregator_port_id != slave_id)
1044 port->selected = UNSELECTED;
1046 /* Use default aggregator */
1047 port->aggregator_port_id = internals->active_slaves[i];
1050 port = &mode_8023ad_ports[slave_id];
1051 port->selected = UNSELECTED;
1052 port->actor_state &= ~(STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |
1055 while (rte_ring_dequeue(port->rx_ring, &pkt) == 0)
1056 rte_pktmbuf_free((struct rte_mbuf *)pkt);
1058 while (rte_ring_dequeue(port->tx_ring, &pkt) == 0)
1059 rte_pktmbuf_free((struct rte_mbuf *)pkt);
1064 bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev)
1066 struct bond_dev_private *internals = bond_dev->data->dev_private;
1067 struct ether_addr slave_addr;
1068 struct port *slave, *agg_slave;
1069 uint8_t slave_id, i, j;
1071 bond_mode_8023ad_stop(bond_dev);
1073 for (i = 0; i < internals->active_slave_count; i++) {
1074 slave_id = internals->active_slaves[i];
1075 slave = &mode_8023ad_ports[slave_id];
1076 rte_eth_macaddr_get(slave_id, &slave_addr);
1078 if (is_same_ether_addr(&slave_addr, &slave->actor.system))
1081 ether_addr_copy(&slave_addr, &slave->actor.system);
1082 /* Do nothing if this port is not an aggregator. In other case
1083 * Set NTT flag on every port that use this aggregator. */
1084 if (slave->aggregator_port_id != slave_id)
1087 for (j = 0; j < internals->active_slave_count; j++) {
1088 agg_slave = &mode_8023ad_ports[internals->active_slaves[j]];
1089 if (agg_slave->aggregator_port_id == slave_id)
1090 SM_FLAG_SET(agg_slave, NTT);
1094 if (bond_dev->data->dev_started)
1095 bond_mode_8023ad_start(bond_dev);
1099 bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
1100 struct rte_eth_bond_8023ad_conf *conf)
1102 struct bond_dev_private *internals = dev->data->dev_private;
1103 struct mode8023ad_private *mode4 = &internals->mode4;
1104 uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
1106 conf->fast_periodic_ms = mode4->fast_periodic_timeout / ms_ticks;
1107 conf->slow_periodic_ms = mode4->slow_periodic_timeout / ms_ticks;
1108 conf->short_timeout_ms = mode4->short_timeout / ms_ticks;
1109 conf->long_timeout_ms = mode4->long_timeout / ms_ticks;
1110 conf->aggregate_wait_timeout_ms = mode4->aggregate_wait_timeout / ms_ticks;
1111 conf->tx_period_ms = mode4->tx_period_timeout / ms_ticks;
1112 conf->update_timeout_ms = mode4->update_timeout_us / 1000;
1113 conf->rx_marker_period_ms = mode4->rx_marker_timeout / ms_ticks;
1114 conf->slowrx_cb = mode4->slowrx_cb;
1115 conf->agg_selection = mode4->agg_selection;
1119 bond_mode_8023ad_conf_get_default(struct rte_eth_bond_8023ad_conf *conf)
1121 conf->fast_periodic_ms = BOND_8023AD_FAST_PERIODIC_MS;
1122 conf->slow_periodic_ms = BOND_8023AD_SLOW_PERIODIC_MS;
1123 conf->short_timeout_ms = BOND_8023AD_SHORT_TIMEOUT_MS;
1124 conf->long_timeout_ms = BOND_8023AD_LONG_TIMEOUT_MS;
1125 conf->aggregate_wait_timeout_ms = BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS;
1126 conf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS;
1127 conf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS;
1128 conf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS;
1129 conf->slowrx_cb = NULL;
1130 conf->agg_selection = AGG_STABLE;
1134 bond_mode_8023ad_conf_assign(struct mode8023ad_private *mode4,
1135 struct rte_eth_bond_8023ad_conf *conf)
1137 uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
1139 mode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks;
1140 mode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks;
1141 mode4->short_timeout = conf->short_timeout_ms * ms_ticks;
1142 mode4->long_timeout = conf->long_timeout_ms * ms_ticks;
1143 mode4->aggregate_wait_timeout = conf->aggregate_wait_timeout_ms * ms_ticks;
1144 mode4->tx_period_timeout = conf->tx_period_ms * ms_ticks;
1145 mode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks;
1146 mode4->update_timeout_us = conf->update_timeout_ms * 1000;
1148 mode4->dedicated_queues.enabled = 0;
1149 mode4->dedicated_queues.rx_qid = UINT16_MAX;
1150 mode4->dedicated_queues.tx_qid = UINT16_MAX;
1154 bond_mode_8023ad_setup(struct rte_eth_dev *dev,
1155 struct rte_eth_bond_8023ad_conf *conf)
1157 struct rte_eth_bond_8023ad_conf def_conf;
1158 struct bond_dev_private *internals = dev->data->dev_private;
1159 struct mode8023ad_private *mode4 = &internals->mode4;
1163 bond_mode_8023ad_conf_get_default(conf);
1166 bond_mode_8023ad_stop(dev);
1167 bond_mode_8023ad_conf_assign(mode4, conf);
1168 mode4->slowrx_cb = conf->slowrx_cb;
1169 mode4->agg_selection = AGG_STABLE;
1171 if (dev->data->dev_started)
1172 bond_mode_8023ad_start(dev);
1176 bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)
1178 struct bond_dev_private *internals = bond_dev->data->dev_private;
1181 for (i = 0; i < internals->active_slave_count; i++)
1182 bond_mode_8023ad_activate_slave(bond_dev, i);
1188 bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)
1190 struct bond_dev_private *internals = bond_dev->data->dev_private;
1191 struct mode8023ad_private *mode4 = &internals->mode4;
1192 static const uint64_t us = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000;
1194 if (mode4->slowrx_cb)
1195 return rte_eal_alarm_set(us, &bond_mode_8023ad_ext_periodic_cb,
1198 return rte_eal_alarm_set(us, &bond_mode_8023ad_periodic_cb, bond_dev);
1202 bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev)
1204 struct bond_dev_private *internals = bond_dev->data->dev_private;
1205 struct mode8023ad_private *mode4 = &internals->mode4;
1207 if (mode4->slowrx_cb) {
1208 rte_eal_alarm_cancel(&bond_mode_8023ad_ext_periodic_cb,
1212 rte_eal_alarm_cancel(&bond_mode_8023ad_periodic_cb, bond_dev);
1216 bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
1217 uint8_t slave_id, struct rte_mbuf *pkt)
1219 struct mode8023ad_private *mode4 = &internals->mode4;
1220 struct port *port = &mode_8023ad_ports[slave_id];
1221 struct marker_header *m_hdr;
1222 uint64_t marker_timer, old_marker_timer;
1224 uint8_t wrn, subtype;
1225 /* If packet is a marker, we send response now by reusing given packet
1226 * and update only source MAC, destination MAC is multicast so don't
1227 * update it. Other frames will be handled later by state machines */
1228 subtype = rte_pktmbuf_mtod(pkt,
1229 struct slow_protocol_frame *)->slow_protocol.subtype;
1231 if (subtype == SLOW_SUBTYPE_MARKER) {
1232 m_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *);
1234 if (likely(m_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_INFO)) {
1235 wrn = WRN_UNKNOWN_MARKER_TYPE;
1239 /* Setup marker timer. Do it in loop in case concurrent access. */
1241 old_marker_timer = port->rx_marker_timer;
1242 if (!timer_is_expired(&old_marker_timer)) {
1243 wrn = WRN_RX_MARKER_TO_FAST;
1247 timer_set(&marker_timer, mode4->rx_marker_timeout);
1248 retval = rte_atomic64_cmpset(&port->rx_marker_timer,
1249 old_marker_timer, marker_timer);
1250 } while (unlikely(retval == 0));
1252 m_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP;
1253 rte_eth_macaddr_get(slave_id, &m_hdr->eth_hdr.s_addr);
1255 if (internals->mode4.dedicated_queues.enabled == 0) {
1256 int retval = rte_ring_enqueue(port->tx_ring, pkt);
1259 port->rx_marker_timer = 0;
1260 wrn = WRN_TX_QUEUE_FULL;
1264 /* Send packet directly to the slow queue */
1265 uint16_t tx_count = rte_eth_tx_burst(slave_id,
1266 internals->mode4.dedicated_queues.tx_qid,
1268 if (tx_count != 1) {
1270 port->rx_marker_timer = 0;
1271 wrn = WRN_TX_QUEUE_FULL;
1275 } else if (likely(subtype == SLOW_SUBTYPE_LACP)) {
1276 if (internals->mode4.dedicated_queues.enabled == 0) {
1277 int retval = rte_ring_enqueue(port->rx_ring, pkt);
1279 /* If RX fing full free lacpdu message and drop packet */
1280 wrn = WRN_RX_QUEUE_FULL;
1284 rx_machine_update(internals, slave_id, pkt);
1286 wrn = WRN_UNKNOWN_SLOW_TYPE;
1293 set_warning_flags(port, wrn);
1294 rte_pktmbuf_free(pkt);
1298 rte_eth_bond_8023ad_conf_get(uint8_t port_id,
1299 struct rte_eth_bond_8023ad_conf *conf)
1301 struct rte_eth_dev *bond_dev;
1303 if (valid_bonded_port_id(port_id) != 0)
1309 bond_dev = &rte_eth_devices[port_id];
1310 bond_mode_8023ad_conf_get(bond_dev, conf);
1315 rte_eth_bond_8023ad_agg_selection_set(uint8_t port_id,
1316 enum rte_bond_8023ad_agg_selection agg_selection)
1318 struct rte_eth_dev *bond_dev;
1319 struct bond_dev_private *internals;
1320 struct mode8023ad_private *mode4;
1322 bond_dev = &rte_eth_devices[port_id];
1323 internals = bond_dev->data->dev_private;
1325 if (valid_bonded_port_id(port_id) != 0)
1327 if (internals->mode != 4)
1330 mode4 = &internals->mode4;
1331 if (agg_selection == AGG_COUNT || agg_selection == AGG_BANDWIDTH
1332 || agg_selection == AGG_STABLE)
1333 mode4->agg_selection = agg_selection;
1337 int rte_eth_bond_8023ad_agg_selection_get(uint8_t port_id)
1339 struct rte_eth_dev *bond_dev;
1340 struct bond_dev_private *internals;
1341 struct mode8023ad_private *mode4;
1343 bond_dev = &rte_eth_devices[port_id];
1344 internals = bond_dev->data->dev_private;
1346 if (valid_bonded_port_id(port_id) != 0)
1348 if (internals->mode != 4)
1350 mode4 = &internals->mode4;
1352 return mode4->agg_selection;
1358 bond_8023ad_setup_validate(uint8_t port_id,
1359 struct rte_eth_bond_8023ad_conf *conf)
1361 if (valid_bonded_port_id(port_id) != 0)
1365 /* Basic sanity check */
1366 if (conf->slow_periodic_ms == 0 ||
1367 conf->fast_periodic_ms >= conf->slow_periodic_ms ||
1368 conf->long_timeout_ms == 0 ||
1369 conf->short_timeout_ms >= conf->long_timeout_ms ||
1370 conf->aggregate_wait_timeout_ms == 0 ||
1371 conf->tx_period_ms == 0 ||
1372 conf->rx_marker_period_ms == 0 ||
1373 conf->update_timeout_ms == 0) {
1374 RTE_LOG(ERR, PMD, "given mode 4 configuration is invalid\n");
1383 rte_eth_bond_8023ad_setup(uint8_t port_id,
1384 struct rte_eth_bond_8023ad_conf *conf)
1386 struct rte_eth_dev *bond_dev;
1389 err = bond_8023ad_setup_validate(port_id, conf);
1393 bond_dev = &rte_eth_devices[port_id];
1394 bond_mode_8023ad_setup(bond_dev, conf);
1404 rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id,
1405 struct rte_eth_bond_8023ad_slave_info *info)
1407 struct rte_eth_dev *bond_dev;
1408 struct bond_dev_private *internals;
1411 if (info == NULL || valid_bonded_port_id(port_id) != 0 ||
1412 rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
1415 bond_dev = &rte_eth_devices[port_id];
1417 internals = bond_dev->data->dev_private;
1418 if (find_slave_by_id(internals->active_slaves,
1419 internals->active_slave_count, slave_id) ==
1420 internals->active_slave_count)
1423 port = &mode_8023ad_ports[slave_id];
1424 info->selected = port->selected;
1426 info->actor_state = port->actor_state;
1427 rte_memcpy(&info->actor, &port->actor, sizeof(port->actor));
1429 info->partner_state = port->partner_state;
1430 rte_memcpy(&info->partner, &port->partner, sizeof(port->partner));
1432 info->agg_port_id = port->aggregator_port_id;
1437 bond_8023ad_ext_validate(uint8_t port_id, uint8_t slave_id)
1439 struct rte_eth_dev *bond_dev;
1440 struct bond_dev_private *internals;
1441 struct mode8023ad_private *mode4;
1443 if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
1446 bond_dev = &rte_eth_devices[port_id];
1448 if (!bond_dev->data->dev_started)
1451 internals = bond_dev->data->dev_private;
1452 if (find_slave_by_id(internals->active_slaves,
1453 internals->active_slave_count, slave_id) ==
1454 internals->active_slave_count)
1457 mode4 = &internals->mode4;
1458 if (mode4->slowrx_cb == NULL)
1465 rte_eth_bond_8023ad_ext_collect(uint8_t port_id, uint8_t slave_id, int enabled)
1470 res = bond_8023ad_ext_validate(port_id, slave_id);
1474 port = &mode_8023ad_ports[slave_id];
1477 ACTOR_STATE_SET(port, COLLECTING);
1479 ACTOR_STATE_CLR(port, COLLECTING);
1485 rte_eth_bond_8023ad_ext_distrib(uint8_t port_id, uint8_t slave_id, int enabled)
1490 res = bond_8023ad_ext_validate(port_id, slave_id);
1494 port = &mode_8023ad_ports[slave_id];
1497 ACTOR_STATE_SET(port, DISTRIBUTING);
1499 ACTOR_STATE_CLR(port, DISTRIBUTING);
1505 rte_eth_bond_8023ad_ext_distrib_get(uint8_t port_id, uint8_t slave_id)
1510 err = bond_8023ad_ext_validate(port_id, slave_id);
1514 port = &mode_8023ad_ports[slave_id];
1515 return ACTOR_STATE(port, DISTRIBUTING);
1519 rte_eth_bond_8023ad_ext_collect_get(uint8_t port_id, uint8_t slave_id)
1524 err = bond_8023ad_ext_validate(port_id, slave_id);
1528 port = &mode_8023ad_ports[slave_id];
1529 return ACTOR_STATE(port, COLLECTING);
1533 rte_eth_bond_8023ad_ext_slowtx(uint8_t port_id, uint8_t slave_id,
1534 struct rte_mbuf *lacp_pkt)
1539 res = bond_8023ad_ext_validate(port_id, slave_id);
1543 port = &mode_8023ad_ports[slave_id];
1545 if (rte_pktmbuf_pkt_len(lacp_pkt) < sizeof(struct lacpdu_header))
1548 struct lacpdu_header *lacp;
1550 /* only enqueue LACPDUs */
1551 lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
1552 if (lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
1555 MODE4_DEBUG("sending LACP frame\n");
1557 return rte_ring_enqueue(port->tx_ring, lacp_pkt);
1561 bond_mode_8023ad_ext_periodic_cb(void *arg)
1563 struct rte_eth_dev *bond_dev = arg;
1564 struct bond_dev_private *internals = bond_dev->data->dev_private;
1565 struct mode8023ad_private *mode4 = &internals->mode4;
1568 uint16_t i, slave_id;
1570 for (i = 0; i < internals->active_slave_count; i++) {
1571 slave_id = internals->active_slaves[i];
1572 port = &mode_8023ad_ports[slave_id];
1574 if (rte_ring_dequeue(port->rx_ring, &pkt) == 0) {
1575 struct rte_mbuf *lacp_pkt = pkt;
1576 struct lacpdu_header *lacp;
1578 lacp = rte_pktmbuf_mtod(lacp_pkt,
1579 struct lacpdu_header *);
1580 RTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
1582 /* This is LACP frame so pass it to rx callback.
1583 * Callback is responsible for freeing mbuf.
1585 mode4->slowrx_cb(slave_id, lacp_pkt);
1589 rte_eal_alarm_set(internals->mode4.update_timeout_us,
1590 bond_mode_8023ad_ext_periodic_cb, arg);
1594 rte_eth_bond_8023ad_dedicated_queues_enable(uint8_t port)
1597 struct rte_eth_dev *dev = &rte_eth_devices[port];
1598 struct bond_dev_private *internals = (struct bond_dev_private *)
1599 dev->data->dev_private;
1601 if (check_for_bonded_ethdev(dev) != 0)
1604 if (bond_8023ad_slow_pkt_hw_filter_supported(port) != 0)
1607 /* Device must be stopped to set up slow queue */
1608 if (dev->data->dev_started)
1611 internals->mode4.dedicated_queues.enabled = 1;
1613 bond_ethdev_mode_set(dev, internals->mode);
1618 rte_eth_bond_8023ad_dedicated_queues_disable(uint8_t port)
1621 struct rte_eth_dev *dev = &rte_eth_devices[port];
1622 struct bond_dev_private *internals = (struct bond_dev_private *)
1623 dev->data->dev_private;
1625 if (check_for_bonded_ethdev(dev) != 0)
1628 /* Device must be stopped to set up slow queue */
1629 if (dev->data->dev_started)
1632 internals->mode4.dedicated_queues.enabled = 0;
1634 bond_ethdev_mode_set(dev, internals->mode);