LCOV - code coverage report
Current view: top level - drivers/net/bonding - rte_eth_bond_8023ad.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 617 0.0 %
Date: 2024-01-22 16:26:08 Functions: 0 36 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 439 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2015 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stddef.h>
       6                 :            : #include <string.h>
       7                 :            : #include <stdbool.h>
       8                 :            : 
       9                 :            : #include <rte_alarm.h>
      10                 :            : #include <rte_malloc.h>
      11                 :            : #include <rte_errno.h>
      12                 :            : #include <rte_cycles.h>
      13                 :            : 
      14                 :            : #include "eth_bond_private.h"
      15                 :            : 
      16                 :            : static void bond_mode_8023ad_ext_periodic_cb(void *arg);
      17                 :            : #ifdef RTE_LIBRTE_BOND_DEBUG_8023AD
      18                 :            : 
      19                 :            : #define MODE4_DEBUG(fmt, ...)                           \
      20                 :            :         rte_log(RTE_LOG_DEBUG, bond_logtype,            \
      21                 :            :                 "%6u [Port %u: %s] " fmt,             \
      22                 :            :                 bond_dbg_get_time_diff_ms(), member_id, \
      23                 :            :                 __func__, ##__VA_ARGS__)
      24                 :            : 
      25                 :            : static uint64_t start_time;
      26                 :            : 
      27                 :            : static unsigned
      28                 :            : bond_dbg_get_time_diff_ms(void)
      29                 :            : {
      30                 :            :         uint64_t now;
      31                 :            : 
      32                 :            :         now = rte_rdtsc();
      33                 :            :         if (start_time == 0)
      34                 :            :                 start_time = now;
      35                 :            : 
      36                 :            :         return ((now - start_time) * 1000) / rte_get_tsc_hz();
      37                 :            : }
      38                 :            : 
      39                 :            : static void
      40                 :            : bond_print_lacp(struct lacpdu *l)
      41                 :            : {
      42                 :            :         char a_address[18];
      43                 :            :         char p_address[18];
      44                 :            :         char a_state[256] = { 0 };
      45                 :            :         char p_state[256] = { 0 };
      46                 :            : 
      47                 :            :         static const char * const state_labels[] = {
      48                 :            :                 "ACT", "TIMEOUT", "AGG", "SYNC", "COL", "DIST", "DEF", "EXP"
      49                 :            :         };
      50                 :            : 
      51                 :            :         int a_len = 0;
      52                 :            :         int p_len = 0;
      53                 :            :         uint8_t i;
      54                 :            :         uint8_t *addr;
      55                 :            : 
      56                 :            :         addr = l->actor.port_params.system.addr_bytes;
      57                 :            :         snprintf(a_address, sizeof(a_address), RTE_ETHER_ADDR_PRT_FMT,
      58                 :            :                 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
      59                 :            : 
      60                 :            :         addr = l->partner.port_params.system.addr_bytes;
      61                 :            :         snprintf(p_address, sizeof(p_address), RTE_ETHER_ADDR_PRT_FMT,
      62                 :            :                 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
      63                 :            : 
      64                 :            :         for (i = 0; i < 8; i++) {
      65                 :            :                 if ((l->actor.state >> i) & 1) {
      66                 :            :                         a_len += snprintf(&a_state[a_len], RTE_DIM(a_state) - a_len, "%s ",
      67                 :            :                                 state_labels[i]);
      68                 :            :                 }
      69                 :            : 
      70                 :            :                 if ((l->partner.state >> i) & 1) {
      71                 :            :                         p_len += snprintf(&p_state[p_len], RTE_DIM(p_state) - p_len, "%s ",
      72                 :            :                                 state_labels[i]);
      73                 :            :                 }
      74                 :            :         }
      75                 :            : 
      76                 :            :         if (a_len && a_state[a_len-1] == ' ')
      77                 :            :                 a_state[a_len-1] = '\0';
      78                 :            : 
      79                 :            :         if (p_len && p_state[p_len-1] == ' ')
      80                 :            :                 p_state[p_len-1] = '\0';
      81                 :            : 
      82                 :            :         RTE_BOND_LOG(DEBUG,
      83                 :            :                      "LACP: {\n"
      84                 :            :                      "  subtype= %02X\n"
      85                 :            :                      "  ver_num=%02X\n"
      86                 :            :                      "  actor={ tlv=%02X, len=%02X\n"
      87                 :            :                      "    pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"
      88                 :            :                      "       state={ %s }\n"
      89                 :            :                      "  }\n"
      90                 :            :                      "  partner={ tlv=%02X, len=%02X\n"
      91                 :            :                      "    pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"
      92                 :            :                      "       state={ %s }\n"
      93                 :            :                      "  }\n"
      94                 :            :                      "  collector={info=%02X, length=%02X, max_delay=%04X\n, "
      95                 :            :                      "type_term=%02X, terminator_length = %02X }",
      96                 :            :                      l->subtype,
      97                 :            :                      l->version_number,
      98                 :            :                      l->actor.tlv_type_info,
      99                 :            :                      l->actor.info_length,
     100                 :            :                      l->actor.port_params.system_priority,
     101                 :            :                      a_address,
     102                 :            :                      l->actor.port_params.key,
     103                 :            :                      l->actor.port_params.port_priority,
     104                 :            :                      l->actor.port_params.port_number,
     105                 :            :                      a_state,
     106                 :            :                      l->partner.tlv_type_info,
     107                 :            :                      l->partner.info_length,
     108                 :            :                      l->partner.port_params.system_priority,
     109                 :            :                      p_address,
     110                 :            :                      l->partner.port_params.key,
     111                 :            :                      l->partner.port_params.port_priority,
     112                 :            :                      l->partner.port_params.port_number,
     113                 :            :                      p_state,
     114                 :            :                      l->tlv_type_collector_info,
     115                 :            :                      l->collector_info_length,
     116                 :            :                      l->collector_max_delay,
     117                 :            :                      l->tlv_type_terminator,
     118                 :            :                      l->terminator_length);
     119                 :            : 
     120                 :            : }
     121                 :            : 
     122                 :            : #define BOND_PRINT_LACP(lacpdu) bond_print_lacp(lacpdu)
     123                 :            : #else
     124                 :            : #define BOND_PRINT_LACP(lacpdu) do { } while (0)
     125                 :            : #define MODE4_DEBUG(fmt, ...) do { } while (0)
     126                 :            : #endif
     127                 :            : 
     128                 :            : static const struct rte_ether_addr lacp_mac_addr = {
     129                 :            :         .addr_bytes = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
     130                 :            : };
     131                 :            : 
     132                 :            : struct port bond_mode_8023ad_ports[RTE_MAX_ETHPORTS];
     133                 :            : 
     134                 :            : static void
     135                 :            : timer_cancel(uint64_t *timer)
     136                 :            : {
     137                 :          0 :         *timer = 0;
     138                 :          0 : }
     139                 :            : 
     140                 :            : static void
     141                 :            : timer_set(uint64_t *timer, uint64_t timeout)
     142                 :            : {
     143                 :          0 :         *timer = rte_rdtsc() + timeout;
     144                 :          0 : }
     145                 :            : 
     146                 :            : /* Forces given timer to be in expired state. */
     147                 :            : static void
     148                 :            : timer_force_expired(uint64_t *timer)
     149                 :            : {
     150                 :          0 :         *timer = rte_rdtsc();
     151                 :            : }
     152                 :            : 
     153                 :            : static bool
     154                 :            : timer_is_stopped(uint64_t *timer)
     155                 :            : {
     156                 :          0 :         return *timer == 0;
     157                 :            : }
     158                 :            : 
     159                 :            : static bool
     160                 :            : timer_is_expired(uint64_t *timer)
     161                 :            : {
     162                 :          0 :         return *timer < rte_rdtsc();
     163                 :            : }
     164                 :            : 
     165                 :            : /* Timer is in running state if it is not stopped nor expired */
     166                 :            : static bool
     167                 :            : timer_is_running(uint64_t *timer)
     168                 :            : {
     169   [ #  #  #  # ]:          0 :         return !timer_is_stopped(timer) && !timer_is_expired(timer);
     170                 :            : }
     171                 :            : 
     172                 :            : static void
     173                 :            : set_warning_flags(struct port *port, uint16_t flags)
     174                 :            : {
     175                 :            :         int retval;
     176                 :            :         uint16_t old;
     177                 :            :         uint16_t new_flag = 0;
     178                 :            : 
     179                 :            :         do {
     180                 :          0 :                 old = port->warnings_to_show;
     181                 :          0 :                 new_flag = old | flags;
     182                 :          0 :                 retval = rte_atomic16_cmpset(&port->warnings_to_show, old, new_flag);
     183   [ #  #  #  #  :          0 :         } while (unlikely(retval == 0));
             #  #  #  # ]
     184                 :            : }
     185                 :            : 
     186                 :            : static void
     187                 :          0 : show_warnings(uint16_t member_id)
     188                 :            : {
     189                 :          0 :         struct port *port = &bond_mode_8023ad_ports[member_id];
     190                 :            :         uint8_t warnings;
     191                 :            : 
     192                 :            :         do {
     193                 :          0 :                 warnings = port->warnings_to_show;
     194         [ #  # ]:          0 :         } while (rte_atomic16_cmpset(&port->warnings_to_show, warnings, 0) == 0);
     195                 :            : 
     196         [ #  # ]:          0 :         if (!warnings)
     197                 :            :                 return;
     198                 :            : 
     199         [ #  # ]:          0 :         if (!timer_is_expired(&port->warning_timer))
     200                 :            :                 return;
     201                 :            : 
     202                 :            : 
     203                 :          0 :         timer_set(&port->warning_timer, BOND_8023AD_WARNINGS_PERIOD_MS *
     204                 :          0 :                         rte_get_tsc_hz() / 1000);
     205                 :            : 
     206         [ #  # ]:          0 :         if (warnings & WRN_RX_QUEUE_FULL) {
     207                 :          0 :                 RTE_BOND_LOG(DEBUG,
     208                 :            :                              "Member %u: failed to enqueue LACP packet into RX ring.\n"
     209                 :            :                              "Receive and transmit functions must be invoked on bonding"
     210                 :            :                              "interface at least 10 times per second or LACP will notwork correctly",
     211                 :            :                              member_id);
     212                 :            :         }
     213                 :            : 
     214         [ #  # ]:          0 :         if (warnings & WRN_TX_QUEUE_FULL) {
     215                 :          0 :                 RTE_BOND_LOG(DEBUG,
     216                 :            :                              "Member %u: failed to enqueue LACP packet into TX ring.\n"
     217                 :            :                              "Receive and transmit functions must be invoked on bonding"
     218                 :            :                              "interface at least 10 times per second or LACP will not work correctly",
     219                 :            :                              member_id);
     220                 :            :         }
     221                 :            : 
     222         [ #  # ]:          0 :         if (warnings & WRN_RX_MARKER_TO_FAST)
     223                 :          0 :                 RTE_BOND_LOG(INFO, "Member %u: marker to early - ignoring.",
     224                 :            :                              member_id);
     225                 :            : 
     226         [ #  # ]:          0 :         if (warnings & WRN_UNKNOWN_SLOW_TYPE) {
     227                 :          0 :                 RTE_BOND_LOG(INFO,
     228                 :            :                         "Member %u: ignoring unknown slow protocol frame type",
     229                 :            :                              member_id);
     230                 :            :         }
     231                 :            : 
     232         [ #  # ]:          0 :         if (warnings & WRN_UNKNOWN_MARKER_TYPE)
     233                 :          0 :                 RTE_BOND_LOG(INFO, "Member %u: ignoring unknown marker type",
     234                 :            :                              member_id);
     235                 :            : 
     236                 :            :         if (warnings & WRN_NOT_LACP_CAPABLE)
     237                 :            :                 MODE4_DEBUG("Port %u is not LACP capable!\n", member_id);
     238                 :            : }
     239                 :            : 
     240                 :            : static void
     241                 :            : record_default(struct port *port)
     242                 :            : {
     243                 :            :         /* Record default parameters for partner. Partner admin parameters
     244                 :            :          * are not implemented so set them to arbitrary default (last known) and
     245                 :            :          * mark actor that partner is in defaulted state. */
     246                 :          0 :         port->partner_state = STATE_LACP_ACTIVE;
     247                 :          0 :         ACTOR_STATE_SET(port, DEFAULTED);
     248                 :            : }
     249                 :            : 
     250                 :            : /** Function handles rx state machine.
     251                 :            :  *
     252                 :            :  * This function implements Receive State Machine from point 5.4.12 in
     253                 :            :  * 802.1AX documentation. It should be called periodically.
     254                 :            :  *
     255                 :            :  * @param lacpdu                LACPDU received.
     256                 :            :  * @param port                  Port on which LACPDU was received.
     257                 :            :  */
     258                 :            : static void
     259                 :          0 : rx_machine(struct bond_dev_private *internals, uint16_t member_id,
     260                 :            :                 struct lacpdu *lacp)
     261                 :            : {
     262                 :          0 :         struct port *agg, *port = &bond_mode_8023ad_ports[member_id];
     263                 :            :         uint64_t timeout;
     264                 :            : 
     265         [ #  # ]:          0 :         if (SM_FLAG(port, BEGIN)) {
     266                 :            :                 /* Initialize stuff */
     267                 :            :                 MODE4_DEBUG("-> INITIALIZE\n");
     268                 :          0 :                 SM_FLAG_CLR(port, MOVED);
     269                 :          0 :                 port->selected = UNSELECTED;
     270                 :            : 
     271                 :            :                 record_default(port);
     272                 :            : 
     273                 :          0 :                 ACTOR_STATE_CLR(port, EXPIRED);
     274                 :            :                 timer_cancel(&port->current_while_timer);
     275                 :            : 
     276                 :            :                 /* DISABLED: On initialization partner is out of sync */
     277                 :            :                 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
     278                 :            : 
     279                 :            :                 /* LACP DISABLED stuff if LACP not enabled on this port */
     280         [ #  # ]:          0 :                 if (!SM_FLAG(port, LACP_ENABLED))
     281                 :            :                         PARTNER_STATE_CLR(port, AGGREGATION);
     282                 :            :                 else
     283                 :          0 :                         PARTNER_STATE_SET(port, AGGREGATION);
     284                 :            :         }
     285                 :            : 
     286         [ #  # ]:          0 :         if (!SM_FLAG(port, LACP_ENABLED)) {
     287                 :            :                 /* Update parameters only if state changed */
     288         [ #  # ]:          0 :                 if (!timer_is_stopped(&port->current_while_timer)) {
     289                 :          0 :                         port->selected = UNSELECTED;
     290                 :            :                         record_default(port);
     291                 :            :                         PARTNER_STATE_CLR(port, AGGREGATION);
     292                 :          0 :                         ACTOR_STATE_CLR(port, EXPIRED);
     293                 :            :                         timer_cancel(&port->current_while_timer);
     294                 :            :                 }
     295                 :          0 :                 return;
     296                 :            :         }
     297                 :            : 
     298         [ #  # ]:          0 :         if (lacp) {
     299                 :            :                 MODE4_DEBUG("LACP -> CURRENT\n");
     300                 :            :                 BOND_PRINT_LACP(lacp);
     301                 :            :                 /* Update selected flag. If partner parameters are defaulted assume they
     302                 :            :                  * are match. If not defaulted  compare LACP actor with ports partner
     303                 :            :                  * params. */
     304         [ #  # ]:          0 :                 if (!ACTOR_STATE(port, DEFAULTED) &&
     305         [ #  # ]:          0 :                         (ACTOR_STATE(port, AGGREGATION) != PARTNER_STATE(port, AGGREGATION)
     306         [ #  # ]:          0 :                         || memcmp(&port->partner, &lacp->actor.port_params,
     307                 :            :                                 sizeof(port->partner)) != 0)) {
     308                 :            :                         MODE4_DEBUG("selected <- UNSELECTED\n");
     309                 :          0 :                         port->selected = UNSELECTED;
     310                 :            :                 }
     311                 :            : 
     312                 :            :                 /* Record this PDU actor params as partner params */
     313         [ #  # ]:          0 :                 memcpy(&port->partner, &lacp->actor.port_params,
     314                 :            :                         sizeof(struct port_params));
     315                 :          0 :                 port->partner_state = lacp->actor.state;
     316                 :            : 
     317                 :            :                 /* Partner parameters are not defaulted any more */
     318                 :          0 :                 ACTOR_STATE_CLR(port, DEFAULTED);
     319                 :            : 
     320                 :            :                 /* If LACP partner params match this port actor params */
     321                 :          0 :                 agg = &bond_mode_8023ad_ports[port->aggregator_port_id];
     322                 :          0 :                 bool match = port->actor.system_priority ==
     323         [ #  # ]:          0 :                         lacp->partner.port_params.system_priority &&
     324         [ #  # ]:          0 :                         rte_is_same_ether_addr(&agg->actor.system,
     325                 :          0 :                         &lacp->partner.port_params.system) &&
     326                 :          0 :                         port->actor.port_priority ==
     327   [ #  #  #  # ]:          0 :                         lacp->partner.port_params.port_priority &&
     328                 :          0 :                         port->actor.port_number ==
     329         [ #  # ]:          0 :                         lacp->partner.port_params.port_number;
     330                 :            : 
     331                 :            :                 /* Update NTT if partners information are outdated (xored and masked
     332                 :            :                  * bits are set)*/
     333                 :            :                 uint8_t state_mask = STATE_LACP_ACTIVE | STATE_LACP_SHORT_TIMEOUT |
     334                 :            :                         STATE_SYNCHRONIZATION | STATE_AGGREGATION;
     335                 :            : 
     336   [ #  #  #  # ]:          0 :                 if (((port->actor_state ^ lacp->partner.state) & state_mask) ||
     337                 :            :                                 match == false) {
     338                 :          0 :                         SM_FLAG_SET(port, NTT);
     339                 :            :                 }
     340                 :            : 
     341                 :            :                 /* If LACP partner params match this port actor params */
     342   [ #  #  #  # ]:          0 :                 if (match == true && ACTOR_STATE(port, AGGREGATION) ==
     343                 :            :                                 PARTNER_STATE(port,     AGGREGATION))
     344                 :          0 :                         PARTNER_STATE_SET(port, SYNCHRONIZATION);
     345   [ #  #  #  # ]:          0 :                 else if (!PARTNER_STATE(port, AGGREGATION) && ACTOR_STATE(port,
     346                 :            :                                 AGGREGATION))
     347                 :          0 :                         PARTNER_STATE_SET(port, SYNCHRONIZATION);
     348                 :            :                 else
     349                 :          0 :                         PARTNER_STATE_CLR(port, SYNCHRONIZATION);
     350                 :            : 
     351         [ #  # ]:          0 :                 if (ACTOR_STATE(port, LACP_SHORT_TIMEOUT))
     352                 :          0 :                         timeout = internals->mode4.short_timeout;
     353                 :            :                 else
     354                 :          0 :                         timeout = internals->mode4.long_timeout;
     355                 :            : 
     356                 :            :                 timer_set(&port->current_while_timer, timeout);
     357                 :          0 :                 ACTOR_STATE_CLR(port, EXPIRED);
     358                 :          0 :                 SM_FLAG_CLR(port, EXPIRED);
     359                 :          0 :                 return; /* No state change */
     360                 :            :         }
     361                 :            : 
     362                 :            :         /* If CURRENT state timer is not running (stopped or expired)
     363                 :            :          * transit to EXPIRED state from DISABLED or CURRENT */
     364         [ #  # ]:          0 :         if (!timer_is_running(&port->current_while_timer)) {
     365         [ #  # ]:          0 :                 if (SM_FLAG(port, EXPIRED)) {
     366                 :          0 :                         port->selected = UNSELECTED;
     367                 :          0 :                         memcpy(&port->partner, &port->partner_admin,
     368                 :            :                                 sizeof(struct port_params));
     369                 :            :                         record_default(port);
     370                 :          0 :                         ACTOR_STATE_CLR(port, EXPIRED);
     371                 :            :                         timer_cancel(&port->current_while_timer);
     372                 :            :                 } else {
     373                 :          0 :                         SM_FLAG_SET(port, EXPIRED);
     374                 :          0 :                         ACTOR_STATE_SET(port, EXPIRED);
     375                 :          0 :                         PARTNER_STATE_CLR(port, SYNCHRONIZATION);
     376                 :          0 :                         PARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT);
     377                 :          0 :                         timer_set(&port->current_while_timer,
     378                 :            :                                 internals->mode4.short_timeout);
     379                 :            :                 }
     380                 :            :         }
     381                 :            : }
     382                 :            : 
     383                 :            : /**
     384                 :            :  * Function handles periodic tx state machine.
     385                 :            :  *
     386                 :            :  * Function implements Periodic Transmission state machine from point 5.4.13
     387                 :            :  * in 802.1AX documentation. It should be called periodically.
     388                 :            :  *
     389                 :            :  * @param port                  Port to handle state machine.
     390                 :            :  */
     391                 :            : static void
     392                 :          0 : periodic_machine(struct bond_dev_private *internals, uint16_t member_id)
     393                 :            : {
     394                 :          0 :         struct port *port = &bond_mode_8023ad_ports[member_id];
     395                 :            :         /* Calculate if either site is LACP enabled */
     396                 :            :         uint64_t timeout;
     397         [ #  # ]:          0 :         uint8_t active = ACTOR_STATE(port, LACP_ACTIVE) ||
     398         [ #  # ]:          0 :                 PARTNER_STATE(port, LACP_ACTIVE);
     399                 :            : 
     400                 :            :         uint8_t is_partner_fast, was_partner_fast;
     401                 :            :         /* No periodic is on BEGIN, LACP DISABLE or when both sides are passive */
     402   [ #  #  #  # ]:          0 :         if (SM_FLAG(port, BEGIN) || !SM_FLAG(port, LACP_ENABLED) || !active) {
     403                 :            :                 timer_cancel(&port->periodic_timer);
     404                 :            :                 timer_force_expired(&port->tx_machine_timer);
     405                 :          0 :                 SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);
     406                 :            : 
     407                 :            :                 MODE4_DEBUG("-> NO_PERIODIC ( %s%s%s)\n",
     408                 :            :                         SM_FLAG(port, BEGIN) ? "begin " : "",
     409                 :            :                         SM_FLAG(port, LACP_ENABLED) ? "" : "LACP disabled ",
     410                 :            :                         active ? "LACP active " : "LACP passive ");
     411                 :          0 :                 return;
     412                 :            :         }
     413                 :            : 
     414                 :          0 :         is_partner_fast = PARTNER_STATE(port, LACP_SHORT_TIMEOUT);
     415                 :          0 :         was_partner_fast = SM_FLAG(port, PARTNER_SHORT_TIMEOUT);
     416                 :            : 
     417                 :            :         /* If periodic timer is not started, transit from NO PERIODIC to FAST/SLOW.
     418                 :            :          * Other case: check if timer expire or partners settings changed. */
     419         [ #  # ]:          0 :         if (!timer_is_stopped(&port->periodic_timer)) {
     420         [ #  # ]:          0 :                 if (timer_is_expired(&port->periodic_timer)) {
     421                 :          0 :                         SM_FLAG_SET(port, NTT);
     422         [ #  # ]:          0 :                 } else if (is_partner_fast != was_partner_fast) {
     423                 :            :                         /* Partners timeout  was slow and now it is fast -> send LACP.
     424                 :            :                          * In other case (was fast and now it is slow) just switch
     425                 :            :                          * timeout to slow without forcing send of LACP (because standard
     426                 :            :                          * say so)*/
     427         [ #  # ]:          0 :                         if (is_partner_fast)
     428                 :          0 :                                 SM_FLAG_SET(port, NTT);
     429                 :            :                 } else
     430                 :            :                         return; /* Nothing changed */
     431                 :            :         }
     432                 :            : 
     433                 :            :         /* Handle state transition to FAST/SLOW LACP timeout */
     434         [ #  # ]:          0 :         if (is_partner_fast) {
     435                 :          0 :                 timeout = internals->mode4.fast_periodic_timeout;
     436                 :          0 :                 SM_FLAG_SET(port, PARTNER_SHORT_TIMEOUT);
     437                 :            :         } else {
     438                 :          0 :                 timeout = internals->mode4.slow_periodic_timeout;
     439                 :          0 :                 SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);
     440                 :            :         }
     441                 :            : 
     442                 :            :         timer_set(&port->periodic_timer, timeout);
     443                 :            : }
     444                 :            : 
     445                 :            : /**
     446                 :            :  * Function handles mux state machine.
     447                 :            :  *
     448                 :            :  * Function implements Mux Machine from point 5.4.15 in 802.1AX documentation.
     449                 :            :  * It should be called periodically.
     450                 :            :  *
     451                 :            :  * @param port                  Port to handle state machine.
     452                 :            :  */
     453                 :            : static void
     454                 :          0 : mux_machine(struct bond_dev_private *internals, uint16_t member_id)
     455                 :            : {
     456                 :          0 :         struct port *port = &bond_mode_8023ad_ports[member_id];
     457                 :            : 
     458                 :            :         /* Save current state for later use */
     459                 :            :         const uint8_t state_mask = STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |
     460                 :            :                 STATE_COLLECTING;
     461                 :            : 
     462                 :            :         /* Enter DETACHED state on BEGIN condition or from any other state if
     463                 :            :          * port was unselected */
     464         [ #  # ]:          0 :         if (SM_FLAG(port, BEGIN) ||
     465   [ #  #  #  # ]:          0 :                         port->selected == UNSELECTED || (port->selected == STANDBY &&
     466         [ #  # ]:          0 :                                 (port->actor_state & state_mask) != 0)) {
     467                 :            :                 /* detach mux from aggregator */
     468                 :          0 :                 port->actor_state &= ~state_mask;
     469                 :            :                 /* Set ntt to true if BEGIN condition or transition from any other state
     470                 :            :                  * which is indicated that wait_while_timer was started */
     471   [ #  #  #  # ]:          0 :                 if (SM_FLAG(port, BEGIN) ||
     472                 :            :                                 !timer_is_stopped(&port->wait_while_timer)) {
     473                 :          0 :                         SM_FLAG_SET(port, NTT);
     474                 :            :                         MODE4_DEBUG("-> DETACHED\n");
     475                 :            :                 }
     476                 :            :                 timer_cancel(&port->wait_while_timer);
     477                 :            :         }
     478                 :            : 
     479         [ #  # ]:          0 :         if (timer_is_stopped(&port->wait_while_timer)) {
     480         [ #  # ]:          0 :                 if (port->selected == SELECTED || port->selected == STANDBY) {
     481                 :          0 :                         timer_set(&port->wait_while_timer,
     482                 :            :                                 internals->mode4.aggregate_wait_timeout);
     483                 :            : 
     484                 :            :                         MODE4_DEBUG("DETACHED -> WAITING\n");
     485                 :            :                 }
     486                 :            :                 /* Waiting state entered */
     487                 :          0 :                 return;
     488                 :            :         }
     489                 :            : 
     490                 :            :         /* Transit next state if port is ready */
     491         [ #  # ]:          0 :         if (!timer_is_expired(&port->wait_while_timer))
     492                 :            :                 return;
     493                 :            : 
     494         [ #  # ]:          0 :         if ((ACTOR_STATE(port, DISTRIBUTING) || ACTOR_STATE(port, COLLECTING)) &&
     495         [ #  # ]:          0 :                 !PARTNER_STATE(port, SYNCHRONIZATION)) {
     496                 :            :                 /* If in COLLECTING or DISTRIBUTING state and partner becomes out of
     497                 :            :                  * sync transit to ATTACHED state.  */
     498                 :          0 :                 ACTOR_STATE_CLR(port, DISTRIBUTING);
     499                 :          0 :                 ACTOR_STATE_CLR(port, COLLECTING);
     500                 :            :                 /* Clear actor sync to activate transit ATTACHED in condition bellow */
     501                 :          0 :                 ACTOR_STATE_CLR(port, SYNCHRONIZATION);
     502                 :            :                 MODE4_DEBUG("Out of sync -> ATTACHED\n");
     503                 :            :         }
     504                 :            : 
     505         [ #  # ]:          0 :         if (!ACTOR_STATE(port, SYNCHRONIZATION)) {
     506                 :            :                 /* attach mux to aggregator */
     507                 :            :                 RTE_ASSERT((port->actor_state & (STATE_COLLECTING |
     508                 :            :                         STATE_DISTRIBUTING)) == 0);
     509                 :            : 
     510                 :          0 :                 ACTOR_STATE_SET(port, SYNCHRONIZATION);
     511                 :          0 :                 SM_FLAG_SET(port, NTT);
     512                 :            :                 MODE4_DEBUG("ATTACHED Entered\n");
     513         [ #  # ]:          0 :         } else if (!ACTOR_STATE(port, COLLECTING)) {
     514                 :            :                 /* Start collecting if in sync */
     515         [ #  # ]:          0 :                 if (PARTNER_STATE(port, SYNCHRONIZATION)) {
     516                 :            :                         MODE4_DEBUG("ATTACHED -> COLLECTING\n");
     517                 :          0 :                         ACTOR_STATE_SET(port, COLLECTING);
     518                 :          0 :                         SM_FLAG_SET(port, NTT);
     519                 :            :                 }
     520                 :            :         } else if (ACTOR_STATE(port, COLLECTING)) {
     521                 :            :                 /* Check if partner is in COLLECTING state. If so this port can
     522                 :            :                  * distribute frames to it */
     523         [ #  # ]:          0 :                 if (!ACTOR_STATE(port, DISTRIBUTING)) {
     524         [ #  # ]:          0 :                         if (PARTNER_STATE(port, COLLECTING)) {
     525                 :            :                                 /* Enable  DISTRIBUTING if partner is collecting */
     526                 :          0 :                                 ACTOR_STATE_SET(port, DISTRIBUTING);
     527                 :          0 :                                 SM_FLAG_SET(port, NTT);
     528                 :            :                                 MODE4_DEBUG("COLLECTING -> DISTRIBUTING\n");
     529                 :          0 :                                 RTE_BOND_LOG(INFO,
     530                 :            :                                         "Bond %u: member id %u distributing started.",
     531                 :            :                                         internals->port_id, member_id);
     532                 :            :                         }
     533                 :            :                 } else {
     534         [ #  # ]:          0 :                         if (!PARTNER_STATE(port, COLLECTING)) {
     535                 :            :                                 /* Disable DISTRIBUTING (enter COLLECTING state) if partner
     536                 :            :                                  * is not collecting */
     537                 :          0 :                                 ACTOR_STATE_CLR(port, DISTRIBUTING);
     538                 :          0 :                                 SM_FLAG_SET(port, NTT);
     539                 :            :                                 MODE4_DEBUG("DISTRIBUTING -> COLLECTING\n");
     540                 :          0 :                                 RTE_BOND_LOG(INFO,
     541                 :            :                                         "Bond %u: member id %u distributing stopped.",
     542                 :            :                                         internals->port_id, member_id);
     543                 :            :                         }
     544                 :            :                 }
     545                 :            :         }
     546                 :            : }
     547                 :            : 
     548                 :            : /**
     549                 :            :  * Function handles transmit state machine.
     550                 :            :  *
     551                 :            :  * Function implements Transmit Machine from point 5.4.16 in 802.1AX
     552                 :            :  * documentation.
     553                 :            :  *
     554                 :            :  * @param port
     555                 :            :  */
     556                 :            : static void
     557                 :          0 : tx_machine(struct bond_dev_private *internals, uint16_t member_id)
     558                 :            : {
     559                 :          0 :         struct port *agg, *port = &bond_mode_8023ad_ports[member_id];
     560                 :            : 
     561                 :          0 :         struct rte_mbuf *lacp_pkt = NULL;
     562                 :            :         struct lacpdu_header *hdr;
     563                 :            :         struct lacpdu *lacpdu;
     564                 :            : 
     565                 :            :         /* If periodic timer is not running periodic machine is in NO PERIODIC and
     566                 :            :          * according to 802.3ax standard tx machine should not transmit any frames
     567                 :            :          * and set ntt to false. */
     568         [ #  # ]:          0 :         if (timer_is_stopped(&port->periodic_timer))
     569                 :          0 :                 SM_FLAG_CLR(port, NTT);
     570                 :            : 
     571         [ #  # ]:          0 :         if (!SM_FLAG(port, NTT))
     572                 :          0 :                 return;
     573                 :            : 
     574         [ #  # ]:          0 :         if (!timer_is_expired(&port->tx_machine_timer))
     575                 :            :                 return;
     576                 :            : 
     577                 :          0 :         lacp_pkt = rte_pktmbuf_alloc(port->mbuf_pool);
     578         [ #  # ]:          0 :         if (lacp_pkt == NULL) {
     579                 :          0 :                 RTE_BOND_LOG(ERR, "Failed to allocate LACP packet from pool");
     580                 :          0 :                 return;
     581                 :            :         }
     582                 :            : 
     583                 :          0 :         lacp_pkt->data_len = sizeof(*hdr);
     584                 :          0 :         lacp_pkt->pkt_len = sizeof(*hdr);
     585                 :            : 
     586                 :          0 :         hdr = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
     587                 :            : 
     588                 :            :         /* Source and destination MAC */
     589                 :            :         rte_ether_addr_copy(&lacp_mac_addr, &hdr->eth_hdr.dst_addr);
     590                 :          0 :         rte_eth_macaddr_get(member_id, &hdr->eth_hdr.src_addr);
     591                 :          0 :         hdr->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW);
     592                 :            : 
     593         [ #  # ]:          0 :         lacpdu = &hdr->lacpdu;
     594                 :            :         memset(lacpdu, 0, sizeof(*lacpdu));
     595                 :            : 
     596                 :            :         /* Initialize LACP part */
     597                 :          0 :         lacpdu->subtype = SLOW_SUBTYPE_LACP;
     598                 :          0 :         lacpdu->version_number = 1;
     599                 :            : 
     600                 :            :         /* ACTOR */
     601                 :          0 :         lacpdu->actor.tlv_type_info = TLV_TYPE_ACTOR_INFORMATION;
     602                 :          0 :         lacpdu->actor.info_length = sizeof(struct lacpdu_actor_partner_params);
     603         [ #  # ]:          0 :         memcpy(&hdr->lacpdu.actor.port_params, &port->actor,
     604                 :            :                         sizeof(port->actor));
     605         [ #  # ]:          0 :         agg = &bond_mode_8023ad_ports[port->aggregator_port_id];
     606                 :            :         rte_ether_addr_copy(&agg->actor.system,
     607                 :            :                         &hdr->lacpdu.actor.port_params.system);
     608                 :          0 :         lacpdu->actor.state = port->actor_state;
     609                 :            : 
     610                 :            :         /* PARTNER */
     611                 :          0 :         lacpdu->partner.tlv_type_info = TLV_TYPE_PARTNER_INFORMATION;
     612                 :          0 :         lacpdu->partner.info_length = sizeof(struct lacpdu_actor_partner_params);
     613                 :          0 :         memcpy(&lacpdu->partner.port_params, &port->partner,
     614                 :            :                         sizeof(struct port_params));
     615                 :          0 :         lacpdu->partner.state = port->partner_state;
     616                 :            : 
     617                 :            :         /* Other fields */
     618                 :          0 :         lacpdu->tlv_type_collector_info = TLV_TYPE_COLLECTOR_INFORMATION;
     619                 :          0 :         lacpdu->collector_info_length = 0x10;
     620                 :          0 :         lacpdu->collector_max_delay = 0;
     621                 :            : 
     622                 :          0 :         lacpdu->tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION;
     623                 :          0 :         lacpdu->terminator_length = 0;
     624                 :            : 
     625                 :            :         MODE4_DEBUG("Sending LACP frame\n");
     626                 :            :         BOND_PRINT_LACP(lacpdu);
     627                 :            : 
     628         [ #  # ]:          0 :         if (internals->mode4.dedicated_queues.enabled == 0) {
     629   [ #  #  #  #  :          0 :                 int retval = rte_ring_enqueue(port->tx_ring, lacp_pkt);
                      # ]
     630                 :            :                 if (retval != 0) {
     631                 :            :                         /* If TX ring full, drop packet and free message.
     632                 :            :                            Retransmission will happen in next function call. */
     633                 :          0 :                         rte_pktmbuf_free(lacp_pkt);
     634                 :            :                         set_warning_flags(port, WRN_TX_QUEUE_FULL);
     635                 :            :                         return;
     636                 :            :                 }
     637                 :            :         } else {
     638                 :            :                 uint16_t pkts_sent = rte_eth_tx_prepare(member_id,
     639         [ #  # ]:          0 :                                 internals->mode4.dedicated_queues.tx_qid,
     640                 :            :                                 &lacp_pkt, 1);
     641                 :          0 :                 pkts_sent = rte_eth_tx_burst(member_id,
     642                 :          0 :                                 internals->mode4.dedicated_queues.tx_qid,
     643                 :            :                                 &lacp_pkt, pkts_sent);
     644         [ #  # ]:          0 :                 if (pkts_sent != 1) {
     645                 :          0 :                         rte_pktmbuf_free(lacp_pkt);
     646                 :            :                         set_warning_flags(port, WRN_TX_QUEUE_FULL);
     647                 :            :                         return;
     648                 :            :                 }
     649                 :            :         }
     650                 :            : 
     651                 :            : 
     652                 :          0 :         timer_set(&port->tx_machine_timer, internals->mode4.tx_period_timeout);
     653                 :          0 :         SM_FLAG_CLR(port, NTT);
     654                 :            : }
     655                 :            : 
     656                 :            : static uint16_t
     657                 :            : max_index(uint64_t *a, uint16_t n)
     658                 :            : {
     659                 :            :         uint16_t i, max_i = 0;
     660                 :          0 :         uint64_t max = a[0];
     661                 :            : 
     662   [ #  #  #  # ]:          0 :         for (i = 1; i < n; ++i) {
     663   [ #  #  #  # ]:          0 :                 if (a[i] > max) {
     664                 :            :                         max = a[i];
     665                 :            :                         max_i = i;
     666                 :            :                 }
     667                 :            :         }
     668                 :            : 
     669                 :            :         return max_i;
     670                 :            : }
     671                 :            : 
     672                 :            : /**
     673                 :            :  * Function assigns port to aggregator.
     674                 :            :  *
     675                 :            :  * @param bond_dev_private      Pointer to bond_dev_private structure.
     676                 :            :  * @param port_pos                      Port to assign.
     677                 :            :  */
     678                 :            : static void
     679                 :          0 : selection_logic(struct bond_dev_private *internals, uint16_t member_id)
     680                 :            : {
     681                 :            :         struct port *agg, *port;
     682                 :            :         uint16_t members_count, new_agg_id, i, j = 0;
     683                 :            :         uint16_t *members;
     684                 :          0 :         uint64_t agg_bandwidth[RTE_MAX_ETHPORTS] = {0};
     685                 :          0 :         uint64_t agg_count[RTE_MAX_ETHPORTS] = {0};
     686                 :            :         uint16_t default_member = 0;
     687                 :            :         struct rte_eth_link link_info;
     688                 :            :         uint16_t agg_new_idx = 0;
     689                 :            :         int ret;
     690                 :            : 
     691                 :          0 :         members = internals->active_members;
     692                 :          0 :         members_count = internals->active_member_count;
     693                 :          0 :         port = &bond_mode_8023ad_ports[member_id];
     694                 :            : 
     695                 :            :         /* Search for aggregator suitable for this port */
     696         [ #  # ]:          0 :         for (i = 0; i < members_count; ++i) {
     697                 :          0 :                 agg = &bond_mode_8023ad_ports[members[i]];
     698                 :            :                 /* Skip ports that are not aggregators */
     699         [ #  # ]:          0 :                 if (agg->aggregator_port_id != members[i])
     700                 :          0 :                         continue;
     701                 :            : 
     702                 :          0 :                 ret = rte_eth_link_get_nowait(members[i], &link_info);
     703         [ #  # ]:          0 :                 if (ret < 0) {
     704                 :          0 :                         RTE_BOND_LOG(ERR,
     705                 :            :                                 "Member (port %u) link get failed: %s\n",
     706                 :            :                                 members[i], rte_strerror(-ret));
     707                 :          0 :                         continue;
     708                 :            :                 }
     709                 :          0 :                 agg_count[i] += 1;
     710                 :          0 :                 agg_bandwidth[i] += link_info.link_speed;
     711                 :            : 
     712                 :            :                 /* Actors system ID is not checked since all member device have the same
     713                 :            :                  * ID (MAC address). */
     714         [ #  # ]:          0 :                 if ((agg->actor.key == port->actor.key &&
     715   [ #  #  #  # ]:          0 :                         agg->partner.system_priority == port->partner.system_priority &&
     716                 :          0 :                         rte_is_same_ether_addr(&agg->partner.system,
     717         [ #  # ]:          0 :                                         &port->partner.system) == 1
     718   [ #  #  #  # ]:          0 :                         && (agg->partner.key == port->partner.key)) &&
     719                 :          0 :                         rte_is_zero_ether_addr(&port->partner.system) != 1 &&
     720                 :            :                         (agg->actor.key &
     721         [ #  # ]:          0 :                                 rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) != 0) {
     722                 :            : 
     723         [ #  # ]:          0 :                         if (j == 0)
     724                 :            :                                 default_member = i;
     725                 :          0 :                         j++;
     726                 :            :                 }
     727                 :            :         }
     728                 :            : 
     729   [ #  #  #  # ]:          0 :         switch (internals->mode4.agg_selection) {
     730                 :          0 :         case AGG_COUNT:
     731                 :            :                 agg_new_idx = max_index(agg_count, members_count);
     732                 :          0 :                 new_agg_id = members[agg_new_idx];
     733                 :          0 :                 break;
     734                 :          0 :         case AGG_BANDWIDTH:
     735                 :            :                 agg_new_idx = max_index(agg_bandwidth, members_count);
     736                 :          0 :                 new_agg_id = members[agg_new_idx];
     737                 :          0 :                 break;
     738                 :          0 :         case AGG_STABLE:
     739         [ #  # ]:          0 :                 if (default_member == members_count)
     740                 :          0 :                         new_agg_id = members[member_id];
     741                 :            :                 else
     742                 :          0 :                         new_agg_id = members[default_member];
     743                 :            :                 break;
     744                 :          0 :         default:
     745         [ #  # ]:          0 :                 if (default_member == members_count)
     746                 :          0 :                         new_agg_id = members[member_id];
     747                 :            :                 else
     748                 :          0 :                         new_agg_id = members[default_member];
     749                 :            :                 break;
     750                 :            :         }
     751                 :            : 
     752         [ #  # ]:          0 :         if (new_agg_id != port->aggregator_port_id) {
     753                 :          0 :                 port->aggregator_port_id = new_agg_id;
     754                 :            : 
     755                 :            :                 MODE4_DEBUG("-> SELECTED: ID=%3u\n"
     756                 :            :                         "\t%s aggregator ID=%3u\n",
     757                 :            :                         port->aggregator_port_id,
     758                 :            :                         port->aggregator_port_id == member_id ?
     759                 :            :                                 "aggregator not found, using default" : "aggregator found",
     760                 :            :                         port->aggregator_port_id);
     761                 :            :         }
     762                 :            : 
     763                 :          0 :         port->selected = SELECTED;
     764                 :          0 : }
     765                 :            : 
     766                 :            : /* Function maps DPDK speed to bonding speed stored in key field */
     767                 :            : static uint16_t
     768                 :            : link_speed_key(uint16_t speed) {
     769                 :            :         uint16_t key_speed;
     770                 :            : 
     771                 :          0 :         switch (speed) {
     772                 :            :         case RTE_ETH_SPEED_NUM_NONE:
     773                 :            :                 key_speed = 0x00;
     774                 :            :                 break;
     775                 :          0 :         case RTE_ETH_SPEED_NUM_10M:
     776                 :            :                 key_speed = BOND_LINK_SPEED_KEY_10M;
     777                 :          0 :                 break;
     778                 :          0 :         case RTE_ETH_SPEED_NUM_100M:
     779                 :            :                 key_speed = BOND_LINK_SPEED_KEY_100M;
     780                 :          0 :                 break;
     781                 :          0 :         case RTE_ETH_SPEED_NUM_1G:
     782                 :            :                 key_speed = BOND_LINK_SPEED_KEY_1000M;
     783                 :          0 :                 break;
     784                 :          0 :         case RTE_ETH_SPEED_NUM_10G:
     785                 :            :                 key_speed = BOND_LINK_SPEED_KEY_10G;
     786                 :          0 :                 break;
     787                 :          0 :         case RTE_ETH_SPEED_NUM_20G:
     788                 :            :                 key_speed = BOND_LINK_SPEED_KEY_20G;
     789                 :          0 :                 break;
     790                 :          0 :         case RTE_ETH_SPEED_NUM_40G:
     791                 :            :                 key_speed = BOND_LINK_SPEED_KEY_40G;
     792                 :          0 :                 break;
     793                 :          0 :         default:
     794                 :            :                 /* Unknown speed*/
     795                 :            :                 key_speed = 0xFFFF;
     796                 :            :         }
     797                 :            : 
     798                 :            :         return key_speed;
     799                 :            : }
     800                 :            : 
     801                 :            : static void
     802                 :          0 : rx_machine_update(struct bond_dev_private *internals, uint16_t member_id,
     803                 :            :                 struct rte_mbuf *lacp_pkt) {
     804                 :            :         struct lacpdu_header *lacp;
     805                 :            :         struct lacpdu_actor_partner_params *partner;
     806                 :            :         struct port *port, *agg;
     807                 :            : 
     808         [ #  # ]:          0 :         if (lacp_pkt != NULL) {
     809                 :          0 :                 lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
     810                 :            :                 RTE_ASSERT(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
     811                 :            : 
     812                 :            :                 partner = &lacp->lacpdu.partner;
     813                 :          0 :                 port = &bond_mode_8023ad_ports[member_id];
     814         [ #  # ]:          0 :                 agg = &bond_mode_8023ad_ports[port->aggregator_port_id];
     815                 :            : 
     816   [ #  #  #  # ]:          0 :                 if (rte_is_zero_ether_addr(&partner->port_params.system) ||
     817                 :            :                         rte_is_same_ether_addr(&partner->port_params.system,
     818         [ #  # ]:          0 :                                 &agg->actor.system)) {
     819                 :            :                         /* This LACP frame is sending to the bonding port
     820                 :            :                          * so pass it to rx_machine.
     821                 :            :                          */
     822                 :          0 :                         rx_machine(internals, member_id, &lacp->lacpdu);
     823                 :            :                 } else {
     824                 :            :                         char preferred_system_name[RTE_ETHER_ADDR_FMT_SIZE];
     825                 :            :                         char self_system_name[RTE_ETHER_ADDR_FMT_SIZE];
     826                 :            : 
     827                 :          0 :                         rte_ether_format_addr(preferred_system_name,
     828                 :          0 :                                 RTE_ETHER_ADDR_FMT_SIZE, &partner->port_params.system);
     829                 :          0 :                         rte_ether_format_addr(self_system_name,
     830                 :            :                                 RTE_ETHER_ADDR_FMT_SIZE, &agg->actor.system);
     831                 :            :                         MODE4_DEBUG("preferred partner system %s "
     832                 :            :                                 "is not equal with self system: %s\n",
     833                 :            :                                 preferred_system_name, self_system_name);
     834                 :            :                 }
     835                 :          0 :                 rte_pktmbuf_free(lacp_pkt);
     836                 :            :         } else
     837                 :          0 :                 rx_machine(internals, member_id, NULL);
     838                 :          0 : }
     839                 :            : 
     840                 :            : static void
     841                 :          0 : bond_mode_8023ad_dedicated_rxq_process(struct bond_dev_private *internals,
     842                 :            :                         uint16_t member_id)
     843                 :            : {
     844                 :            : #define DEDICATED_QUEUE_BURST_SIZE 32
     845                 :            :         struct rte_mbuf *lacp_pkt[DEDICATED_QUEUE_BURST_SIZE];
     846                 :          0 :         uint16_t rx_count = rte_eth_rx_burst(member_id,
     847                 :          0 :                                 internals->mode4.dedicated_queues.rx_qid,
     848                 :            :                                 lacp_pkt, DEDICATED_QUEUE_BURST_SIZE);
     849                 :            : 
     850         [ #  # ]:          0 :         if (rx_count) {
     851                 :            :                 uint16_t i;
     852                 :            : 
     853         [ #  # ]:          0 :                 for (i = 0; i < rx_count; i++)
     854                 :          0 :                         bond_mode_8023ad_handle_slow_pkt(internals, member_id,
     855                 :            :                                         lacp_pkt[i]);
     856                 :            :         } else {
     857                 :            :                 rx_machine_update(internals, member_id, NULL);
     858                 :            :         }
     859                 :          0 : }
     860                 :            : 
     861                 :            : static void
     862                 :          0 : bond_mode_8023ad_periodic_cb(void *arg)
     863                 :            : {
     864                 :            :         struct rte_eth_dev *bond_dev = arg;
     865                 :          0 :         struct bond_dev_private *internals = bond_dev->data->dev_private;
     866                 :            :         struct port *port;
     867                 :            :         struct rte_eth_link link_info;
     868                 :            :         struct rte_ether_addr member_addr;
     869                 :          0 :         struct rte_mbuf *lacp_pkt = NULL;
     870                 :            :         uint16_t member_id;
     871                 :            :         uint16_t i;
     872                 :            : 
     873                 :            : 
     874                 :            :         /* Update link status on each port */
     875         [ #  # ]:          0 :         for (i = 0; i < internals->active_member_count; i++) {
     876                 :            :                 uint16_t key;
     877                 :            :                 int ret;
     878                 :            : 
     879                 :          0 :                 member_id = internals->active_members[i];
     880                 :          0 :                 ret = rte_eth_link_get_nowait(member_id, &link_info);
     881         [ #  # ]:          0 :                 if (ret < 0) {
     882                 :          0 :                         RTE_BOND_LOG(ERR,
     883                 :            :                                 "Member (port %u) link get failed: %s\n",
     884                 :            :                                 member_id, rte_strerror(-ret));
     885                 :            :                 }
     886                 :            : 
     887   [ #  #  #  # ]:          0 :                 if (ret >= 0 && link_info.link_status != 0) {
     888   [ #  #  #  #  :          0 :                         key = link_speed_key(link_info.link_speed) << 1;
             #  #  #  # ]
     889         [ #  # ]:          0 :                         if (link_info.link_duplex == RTE_ETH_LINK_FULL_DUPLEX)
     890                 :          0 :                                 key |= BOND_LINK_FULL_DUPLEX_KEY;
     891                 :            :                 } else {
     892                 :            :                         key = 0;
     893                 :            :                 }
     894                 :            : 
     895                 :          0 :                 rte_eth_macaddr_get(member_id, &member_addr);
     896                 :            :                 port = &bond_mode_8023ad_ports[member_id];
     897                 :            : 
     898         [ #  # ]:          0 :                 key = rte_cpu_to_be_16(key);
     899         [ #  # ]:          0 :                 if (key != port->actor.key) {
     900         [ #  # ]:          0 :                         if (!(key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)))
     901                 :            :                                 set_warning_flags(port, WRN_NOT_LACP_CAPABLE);
     902                 :            : 
     903                 :          0 :                         port->actor.key = key;
     904                 :          0 :                         SM_FLAG_SET(port, NTT);
     905                 :            :                 }
     906                 :            : 
     907         [ #  # ]:          0 :                 if (!rte_is_same_ether_addr(&port->actor.system, &member_addr)) {
     908                 :            :                         rte_ether_addr_copy(&member_addr, &port->actor.system);
     909         [ #  # ]:          0 :                         if (port->aggregator_port_id == member_id)
     910                 :          0 :                                 SM_FLAG_SET(port, NTT);
     911                 :            :                 }
     912                 :            :         }
     913                 :            : 
     914         [ #  # ]:          0 :         for (i = 0; i < internals->active_member_count; i++) {
     915                 :          0 :                 member_id = internals->active_members[i];
     916                 :          0 :                 port = &bond_mode_8023ad_ports[member_id];
     917                 :            : 
     918                 :          0 :                 if ((port->actor.key &
     919         [ #  # ]:          0 :                                 rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) == 0) {
     920                 :            : 
     921                 :          0 :                         SM_FLAG_SET(port, BEGIN);
     922                 :            : 
     923                 :            :                         /* LACP is disabled on half duplex or link is down */
     924         [ #  # ]:          0 :                         if (SM_FLAG(port, LACP_ENABLED)) {
     925                 :            :                                 /* If port was enabled set it to BEGIN state */
     926                 :          0 :                                 SM_FLAG_CLR(port, LACP_ENABLED);
     927                 :          0 :                                 ACTOR_STATE_CLR(port, DISTRIBUTING);
     928                 :          0 :                                 ACTOR_STATE_CLR(port, COLLECTING);
     929                 :            :                         }
     930                 :            : 
     931                 :            :                         /* Skip this port processing */
     932                 :          0 :                         continue;
     933                 :            :                 }
     934                 :            : 
     935                 :          0 :                 SM_FLAG_SET(port, LACP_ENABLED);
     936                 :            : 
     937         [ #  # ]:          0 :                 if (internals->mode4.dedicated_queues.enabled == 0) {
     938                 :            :                         /* Find LACP packet to this port. Do not check subtype,
     939                 :            :                          * it is done in function that queued packet
     940                 :            :                          */
     941   [ #  #  #  #  :          0 :                         int retval = rte_ring_dequeue(port->rx_ring,
                      # ]
     942                 :            :                                         (void **)&lacp_pkt);
     943                 :            : 
     944                 :            :                         if (retval != 0)
     945                 :          0 :                                 lacp_pkt = NULL;
     946                 :            : 
     947                 :          0 :                         rx_machine_update(internals, member_id, lacp_pkt);
     948                 :            :                 } else {
     949                 :          0 :                         bond_mode_8023ad_dedicated_rxq_process(internals,
     950                 :            :                                         member_id);
     951                 :            :                 }
     952                 :            : 
     953                 :          0 :                 periodic_machine(internals, member_id);
     954                 :          0 :                 mux_machine(internals, member_id);
     955                 :          0 :                 tx_machine(internals, member_id);
     956                 :          0 :                 selection_logic(internals, member_id);
     957                 :            : 
     958                 :          0 :                 SM_FLAG_CLR(port, BEGIN);
     959                 :          0 :                 show_warnings(member_id);
     960                 :            :         }
     961                 :            : 
     962                 :          0 :         rte_eal_alarm_set(internals->mode4.update_timeout_us,
     963                 :            :                         bond_mode_8023ad_periodic_cb, arg);
     964                 :          0 : }
     965                 :            : 
     966                 :            : static int
     967                 :          0 : bond_mode_8023ad_register_lacp_mac(uint16_t member_id)
     968                 :            : {
     969                 :            :         int ret;
     970                 :            : 
     971                 :          0 :         ret = rte_eth_allmulticast_enable(member_id);
     972         [ #  # ]:          0 :         if (ret != 0) {
     973                 :          0 :                 RTE_BOND_LOG(ERR,
     974                 :            :                         "failed to enable allmulti mode for port %u: %s",
     975                 :            :                         member_id, rte_strerror(-ret));
     976                 :            :         }
     977         [ #  # ]:          0 :         if (rte_eth_allmulticast_get(member_id)) {
     978                 :          0 :                 RTE_BOND_LOG(DEBUG, "forced allmulti for port %u",
     979                 :            :                              member_id);
     980                 :          0 :                 bond_mode_8023ad_ports[member_id].forced_rx_flags =
     981                 :            :                                 BOND_8023AD_FORCED_ALLMULTI;
     982                 :          0 :                 return 0;
     983                 :            :         }
     984                 :            : 
     985                 :          0 :         ret = rte_eth_promiscuous_enable(member_id);
     986         [ #  # ]:          0 :         if (ret != 0) {
     987                 :          0 :                 RTE_BOND_LOG(ERR,
     988                 :            :                         "failed to enable promiscuous mode for port %u: %s",
     989                 :            :                         member_id, rte_strerror(-ret));
     990                 :            :         }
     991         [ #  # ]:          0 :         if (rte_eth_promiscuous_get(member_id)) {
     992                 :          0 :                 RTE_BOND_LOG(DEBUG, "forced promiscuous for port %u",
     993                 :            :                              member_id);
     994                 :          0 :                 bond_mode_8023ad_ports[member_id].forced_rx_flags =
     995                 :            :                                 BOND_8023AD_FORCED_PROMISC;
     996                 :          0 :                 return 0;
     997                 :            :         }
     998                 :            : 
     999                 :            :         return -1;
    1000                 :            : }
    1001                 :            : 
    1002                 :            : static void
    1003                 :          0 : bond_mode_8023ad_unregister_lacp_mac(uint16_t member_id)
    1004                 :            : {
    1005                 :            :         int ret;
    1006                 :            : 
    1007      [ #  #  # ]:          0 :         switch (bond_mode_8023ad_ports[member_id].forced_rx_flags) {
    1008                 :          0 :         case BOND_8023AD_FORCED_ALLMULTI:
    1009                 :          0 :                 RTE_BOND_LOG(DEBUG, "unset allmulti for port %u", member_id);
    1010                 :          0 :                 ret = rte_eth_allmulticast_disable(member_id);
    1011         [ #  # ]:          0 :                 if (ret != 0)
    1012                 :          0 :                         RTE_BOND_LOG(ERR,
    1013                 :            :                                 "failed to disable allmulti mode for port %u: %s",
    1014                 :            :                                 member_id, rte_strerror(-ret));
    1015                 :            :                 break;
    1016                 :            : 
    1017                 :          0 :         case BOND_8023AD_FORCED_PROMISC:
    1018                 :          0 :                 RTE_BOND_LOG(DEBUG, "unset promisc for port %u", member_id);
    1019                 :          0 :                 ret = rte_eth_promiscuous_disable(member_id);
    1020         [ #  # ]:          0 :                 if (ret != 0)
    1021                 :          0 :                         RTE_BOND_LOG(ERR,
    1022                 :            :                                 "failed to disable promiscuous mode for port %u: %s",
    1023                 :            :                                 member_id, rte_strerror(-ret));
    1024                 :            :                 break;
    1025                 :            : 
    1026                 :            :         default:
    1027                 :            :                 break;
    1028                 :            :         }
    1029                 :          0 : }
    1030                 :            : 
    1031                 :            : void
    1032                 :          0 : bond_mode_8023ad_activate_member(struct rte_eth_dev *bond_dev,
    1033                 :            :                                 uint16_t member_id)
    1034                 :            : {
    1035                 :            :         struct bond_dev_private *internals = bond_dev->data->dev_private;
    1036                 :            : 
    1037                 :          0 :         struct port *port = &bond_mode_8023ad_ports[member_id];
    1038                 :          0 :         struct port_params initial = {
    1039                 :            :                         .system = { { 0 } },
    1040                 :            :                         .system_priority = rte_cpu_to_be_16(0xFFFF),
    1041                 :            :                         .key = rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY),
    1042                 :            :                         .port_priority = rte_cpu_to_be_16(0x00FF),
    1043                 :            :                         .port_number = 0,
    1044                 :            :         };
    1045                 :            : 
    1046                 :            :         char mem_name[RTE_ETH_NAME_MAX_LEN];
    1047                 :            :         int socket_id;
    1048                 :            :         unsigned element_size;
    1049                 :            :         uint32_t total_tx_desc;
    1050                 :            :         struct bond_tx_queue *bd_tx_q;
    1051                 :            :         uint16_t q_id;
    1052                 :            : 
    1053                 :            :         /* Given member mus not be in active list */
    1054                 :            :         RTE_ASSERT(find_member_by_id(internals->active_members,
    1055                 :            :         internals->active_member_count, member_id) == internals->active_member_count);
    1056                 :            :         RTE_SET_USED(internals); /* used only for assert when enabled */
    1057                 :            : 
    1058         [ #  # ]:          0 :         memcpy(&port->actor, &initial, sizeof(struct port_params));
    1059                 :            :         /* Standard requires that port ID must be grater than 0.
    1060                 :            :          * Add 1 do get corresponding port_number */
    1061         [ #  # ]:          0 :         port->actor.port_number = rte_cpu_to_be_16(member_id + 1);
    1062                 :            : 
    1063                 :          0 :         memcpy(&port->partner, &initial, sizeof(struct port_params));
    1064                 :          0 :         memcpy(&port->partner_admin, &initial, sizeof(struct port_params));
    1065                 :            : 
    1066                 :            :         /* default states */
    1067                 :          0 :         port->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED;
    1068                 :          0 :         port->partner_state = STATE_LACP_ACTIVE | STATE_AGGREGATION;
    1069                 :          0 :         port->sm_flags = SM_FLAGS_BEGIN;
    1070                 :            : 
    1071                 :            :         /* use this port as aggregator */
    1072                 :          0 :         port->aggregator_port_id = member_id;
    1073                 :            : 
    1074         [ #  # ]:          0 :         if (bond_mode_8023ad_register_lacp_mac(member_id) < 0) {
    1075                 :          0 :                 RTE_BOND_LOG(WARNING, "member %u is most likely broken and won't receive LACP packets",
    1076                 :            :                              member_id);
    1077                 :            :         }
    1078                 :            : 
    1079                 :            :         timer_cancel(&port->warning_timer);
    1080                 :            : 
    1081         [ #  # ]:          0 :         if (port->mbuf_pool != NULL)
    1082                 :          0 :                 return;
    1083                 :            : 
    1084                 :            :         RTE_ASSERT(port->rx_ring == NULL);
    1085                 :            :         RTE_ASSERT(port->tx_ring == NULL);
    1086                 :            : 
    1087                 :          0 :         socket_id = rte_eth_dev_socket_id(member_id);
    1088         [ #  # ]:          0 :         if (socket_id == -1)
    1089                 :          0 :                 socket_id = rte_socket_id();
    1090                 :            : 
    1091                 :            :         element_size = sizeof(struct slow_protocol_frame) +
    1092                 :            :                                 RTE_PKTMBUF_HEADROOM;
    1093                 :            : 
    1094                 :            :         /*
    1095                 :            :          * The size of the mempool should be at least:
    1096                 :            :          * the sum of the TX descriptors + BOND_MODE_8023AX_MEMBER_TX_PKTS.
    1097                 :            :          */
    1098                 :            :         total_tx_desc = BOND_MODE_8023AX_MEMBER_TX_PKTS;
    1099         [ #  # ]:          0 :         for (q_id = 0; q_id < bond_dev->data->nb_tx_queues; q_id++) {
    1100                 :          0 :                 bd_tx_q = (struct bond_tx_queue*)bond_dev->data->tx_queues[q_id];
    1101                 :          0 :                 total_tx_desc += bd_tx_q->nb_tx_desc;
    1102                 :            :         }
    1103                 :            : 
    1104                 :            :         snprintf(mem_name, RTE_DIM(mem_name), "member_port%u_pool", member_id);
    1105                 :          0 :         port->mbuf_pool = rte_pktmbuf_pool_create(mem_name, total_tx_desc,
    1106                 :            :                 RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ?
    1107                 :            :                         32 : RTE_MEMPOOL_CACHE_MAX_SIZE,
    1108                 :            :                 0, element_size, socket_id);
    1109                 :            : 
    1110                 :            :         /* Any memory allocation failure in initialization is critical because
    1111                 :            :          * resources can't be free, so reinitialization is impossible. */
    1112         [ #  # ]:          0 :         if (port->mbuf_pool == NULL) {
    1113                 :          0 :                 rte_panic("Member %u: Failed to create memory pool '%s': %s\n",
    1114                 :            :                         member_id, mem_name, rte_strerror(rte_errno));
    1115                 :            :         }
    1116                 :            : 
    1117                 :            :         snprintf(mem_name, RTE_DIM(mem_name), "member_%u_rx", member_id);
    1118                 :          0 :         port->rx_ring = rte_ring_create(mem_name,
    1119                 :            :                         rte_align32pow2(BOND_MODE_8023AX_MEMBER_RX_PKTS), socket_id, 0);
    1120                 :            : 
    1121         [ #  # ]:          0 :         if (port->rx_ring == NULL) {
    1122                 :          0 :                 rte_panic("Member %u: Failed to create rx ring '%s': %s\n", member_id,
    1123                 :            :                         mem_name, rte_strerror(rte_errno));
    1124                 :            :         }
    1125                 :            : 
    1126                 :            :         /* TX ring is at least one pkt longer to make room for marker packet. */
    1127                 :            :         snprintf(mem_name, RTE_DIM(mem_name), "member_%u_tx", member_id);
    1128                 :          0 :         port->tx_ring = rte_ring_create(mem_name,
    1129                 :            :                         rte_align32pow2(BOND_MODE_8023AX_MEMBER_TX_PKTS + 1), socket_id, 0);
    1130                 :            : 
    1131         [ #  # ]:          0 :         if (port->tx_ring == NULL) {
    1132                 :          0 :                 rte_panic("Member %u: Failed to create tx ring '%s': %s\n", member_id,
    1133                 :            :                         mem_name, rte_strerror(rte_errno));
    1134                 :            :         }
    1135                 :            : }
    1136                 :            : 
    1137                 :            : int
    1138                 :          0 : bond_mode_8023ad_deactivate_member(struct rte_eth_dev *bond_dev __rte_unused,
    1139                 :            :                 uint16_t member_id)
    1140                 :            : {
    1141                 :          0 :         void *pkt = NULL;
    1142                 :            :         struct port *port = NULL;
    1143                 :            :         uint8_t old_partner_state;
    1144                 :            : 
    1145                 :          0 :         port = &bond_mode_8023ad_ports[member_id];
    1146                 :            : 
    1147                 :          0 :         ACTOR_STATE_CLR(port, AGGREGATION);
    1148                 :          0 :         port->selected = UNSELECTED;
    1149                 :            : 
    1150                 :          0 :         old_partner_state = port->partner_state;
    1151                 :            :         record_default(port);
    1152                 :            : 
    1153                 :          0 :         bond_mode_8023ad_unregister_lacp_mac(member_id);
    1154                 :            : 
    1155                 :            :         /* If partner timeout state changes then disable timer */
    1156         [ #  # ]:          0 :         if (!((old_partner_state ^ port->partner_state) &
    1157                 :            :                         STATE_LACP_SHORT_TIMEOUT))
    1158                 :            :                 timer_cancel(&port->current_while_timer);
    1159                 :            : 
    1160                 :          0 :         PARTNER_STATE_CLR(port, AGGREGATION);
    1161                 :          0 :         ACTOR_STATE_CLR(port, EXPIRED);
    1162                 :            : 
    1163                 :            :         /* flush rx/tx rings */
    1164   [ #  #  #  #  :          0 :         while (rte_ring_dequeue(port->rx_ring, &pkt) == 0)
                      # ]
    1165                 :          0 :                 rte_pktmbuf_free((struct rte_mbuf *)pkt);
    1166                 :            : 
    1167   [ #  #  #  #  :          0 :         while (rte_ring_dequeue(port->tx_ring, &pkt) == 0)
                      # ]
    1168                 :          0 :                         rte_pktmbuf_free((struct rte_mbuf *)pkt);
    1169                 :          0 :         return 0;
    1170                 :            : }
    1171                 :            : 
    1172                 :            : void
    1173                 :          0 : bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev)
    1174                 :            : {
    1175                 :          0 :         struct bond_dev_private *internals = bond_dev->data->dev_private;
    1176                 :            :         struct rte_ether_addr member_addr;
    1177                 :            :         struct port *member, *agg_member;
    1178                 :            :         uint16_t member_id, i, j;
    1179                 :            : 
    1180                 :          0 :         bond_mode_8023ad_stop(bond_dev);
    1181                 :            : 
    1182         [ #  # ]:          0 :         for (i = 0; i < internals->active_member_count; i++) {
    1183                 :          0 :                 member_id = internals->active_members[i];
    1184                 :          0 :                 member = &bond_mode_8023ad_ports[member_id];
    1185                 :          0 :                 rte_eth_macaddr_get(member_id, &member_addr);
    1186                 :            : 
    1187         [ #  # ]:          0 :                 if (rte_is_same_ether_addr(&member_addr, &member->actor.system))
    1188                 :          0 :                         continue;
    1189                 :            : 
    1190                 :            :                 rte_ether_addr_copy(&member_addr, &member->actor.system);
    1191                 :            :                 /* Do nothing if this port is not an aggregator. In other case
    1192                 :            :                  * Set NTT flag on every port that use this aggregator. */
    1193         [ #  # ]:          0 :                 if (member->aggregator_port_id != member_id)
    1194                 :          0 :                         continue;
    1195                 :            : 
    1196         [ #  # ]:          0 :                 for (j = 0; j < internals->active_member_count; j++) {
    1197                 :          0 :                         agg_member = &bond_mode_8023ad_ports[internals->active_members[j]];
    1198         [ #  # ]:          0 :                         if (agg_member->aggregator_port_id == member_id)
    1199                 :          0 :                                 SM_FLAG_SET(agg_member, NTT);
    1200                 :            :                 }
    1201                 :            :         }
    1202                 :            : 
    1203         [ #  # ]:          0 :         if (bond_dev->data->dev_started)
    1204                 :          0 :                 bond_mode_8023ad_start(bond_dev);
    1205                 :          0 : }
    1206                 :            : 
    1207                 :            : static void
    1208                 :          0 : bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
    1209                 :            :                 struct rte_eth_bond_8023ad_conf *conf)
    1210                 :            : {
    1211                 :          0 :         struct bond_dev_private *internals = dev->data->dev_private;
    1212                 :            :         struct mode8023ad_private *mode4 = &internals->mode4;
    1213                 :          0 :         uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
    1214                 :            : 
    1215                 :          0 :         conf->fast_periodic_ms = mode4->fast_periodic_timeout / ms_ticks;
    1216                 :          0 :         conf->slow_periodic_ms = mode4->slow_periodic_timeout / ms_ticks;
    1217                 :          0 :         conf->short_timeout_ms = mode4->short_timeout / ms_ticks;
    1218                 :          0 :         conf->long_timeout_ms = mode4->long_timeout / ms_ticks;
    1219                 :          0 :         conf->aggregate_wait_timeout_ms = mode4->aggregate_wait_timeout / ms_ticks;
    1220                 :          0 :         conf->tx_period_ms = mode4->tx_period_timeout / ms_ticks;
    1221                 :          0 :         conf->update_timeout_ms = mode4->update_timeout_us / 1000;
    1222                 :          0 :         conf->rx_marker_period_ms = mode4->rx_marker_timeout / ms_ticks;
    1223                 :          0 :         conf->slowrx_cb = mode4->slowrx_cb;
    1224                 :          0 :         conf->agg_selection = mode4->agg_selection;
    1225                 :          0 : }
    1226                 :            : 
    1227                 :            : static void
    1228                 :            : bond_mode_8023ad_conf_get_default(struct rte_eth_bond_8023ad_conf *conf)
    1229                 :            : {
    1230                 :          0 :         conf->fast_periodic_ms = BOND_8023AD_FAST_PERIODIC_MS;
    1231                 :          0 :         conf->slow_periodic_ms = BOND_8023AD_SLOW_PERIODIC_MS;
    1232                 :          0 :         conf->short_timeout_ms = BOND_8023AD_SHORT_TIMEOUT_MS;
    1233                 :          0 :         conf->long_timeout_ms = BOND_8023AD_LONG_TIMEOUT_MS;
    1234                 :          0 :         conf->aggregate_wait_timeout_ms = BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS;
    1235                 :          0 :         conf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS;
    1236                 :          0 :         conf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS;
    1237                 :          0 :         conf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS;
    1238                 :          0 :         conf->slowrx_cb = NULL;
    1239                 :          0 :         conf->agg_selection = AGG_STABLE;
    1240                 :          0 : }
    1241                 :            : 
    1242                 :            : static void
    1243                 :          0 : bond_mode_8023ad_conf_assign(struct mode8023ad_private *mode4,
    1244                 :            :                 struct rte_eth_bond_8023ad_conf *conf)
    1245                 :            : {
    1246                 :          0 :         uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
    1247                 :            : 
    1248                 :          0 :         mode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks;
    1249                 :          0 :         mode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks;
    1250                 :          0 :         mode4->short_timeout = conf->short_timeout_ms * ms_ticks;
    1251                 :          0 :         mode4->long_timeout = conf->long_timeout_ms * ms_ticks;
    1252                 :          0 :         mode4->aggregate_wait_timeout = conf->aggregate_wait_timeout_ms * ms_ticks;
    1253                 :          0 :         mode4->tx_period_timeout = conf->tx_period_ms * ms_ticks;
    1254                 :          0 :         mode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks;
    1255                 :          0 :         mode4->update_timeout_us = conf->update_timeout_ms * 1000;
    1256                 :            : 
    1257                 :          0 :         mode4->dedicated_queues.enabled = 0;
    1258                 :          0 :         mode4->dedicated_queues.rx_qid = UINT16_MAX;
    1259                 :          0 :         mode4->dedicated_queues.tx_qid = UINT16_MAX;
    1260                 :          0 : }
    1261                 :            : 
    1262                 :            : void
    1263                 :          0 : bond_mode_8023ad_setup(struct rte_eth_dev *dev,
    1264                 :            :                 struct rte_eth_bond_8023ad_conf *conf)
    1265                 :            : {
    1266                 :            :         struct rte_eth_bond_8023ad_conf def_conf;
    1267                 :          0 :         struct bond_dev_private *internals = dev->data->dev_private;
    1268                 :          0 :         struct mode8023ad_private *mode4 = &internals->mode4;
    1269                 :            : 
    1270         [ #  # ]:          0 :         if (conf == NULL) {
    1271                 :            :                 conf = &def_conf;
    1272                 :            :                 bond_mode_8023ad_conf_get_default(conf);
    1273                 :            :         }
    1274                 :            : 
    1275                 :          0 :         bond_mode_8023ad_stop(dev);
    1276                 :          0 :         bond_mode_8023ad_conf_assign(mode4, conf);
    1277                 :          0 :         mode4->slowrx_cb = conf->slowrx_cb;
    1278                 :          0 :         mode4->agg_selection = AGG_STABLE;
    1279                 :            : 
    1280         [ #  # ]:          0 :         if (dev->data->dev_started)
    1281                 :          0 :                 bond_mode_8023ad_start(dev);
    1282                 :          0 : }
    1283                 :            : 
    1284                 :            : int
    1285                 :          0 : bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)
    1286                 :            : {
    1287                 :          0 :         struct bond_dev_private *internals = bond_dev->data->dev_private;
    1288                 :            :         uint16_t i;
    1289                 :            : 
    1290         [ #  # ]:          0 :         for (i = 0; i < internals->active_member_count; i++)
    1291                 :          0 :                 bond_mode_8023ad_activate_member(bond_dev,
    1292                 :          0 :                                 internals->active_members[i]);
    1293                 :            : 
    1294                 :          0 :         return 0;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : int
    1298                 :          0 : bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)
    1299                 :            : {
    1300                 :          0 :         struct bond_dev_private *internals = bond_dev->data->dev_private;
    1301                 :            :         struct mode8023ad_private *mode4 = &internals->mode4;
    1302                 :            :         static const uint64_t us = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000;
    1303                 :            : 
    1304                 :          0 :         rte_eth_macaddr_get(internals->port_id, &mode4->mac_addr);
    1305         [ #  # ]:          0 :         if (mode4->slowrx_cb)
    1306                 :          0 :                 return rte_eal_alarm_set(us, &bond_mode_8023ad_ext_periodic_cb,
    1307                 :            :                                          bond_dev);
    1308                 :            : 
    1309                 :          0 :         return rte_eal_alarm_set(us, &bond_mode_8023ad_periodic_cb, bond_dev);
    1310                 :            : }
    1311                 :            : 
    1312                 :            : void
    1313                 :          0 : bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev)
    1314                 :            : {
    1315                 :          0 :         struct bond_dev_private *internals = bond_dev->data->dev_private;
    1316                 :            :         struct mode8023ad_private *mode4 = &internals->mode4;
    1317                 :            : 
    1318         [ #  # ]:          0 :         if (mode4->slowrx_cb) {
    1319                 :          0 :                 rte_eal_alarm_cancel(&bond_mode_8023ad_ext_periodic_cb,
    1320                 :            :                                      bond_dev);
    1321                 :          0 :                 return;
    1322                 :            :         }
    1323                 :          0 :         rte_eal_alarm_cancel(&bond_mode_8023ad_periodic_cb, bond_dev);
    1324                 :            : }
    1325                 :            : 
    1326                 :            : void
    1327                 :          0 : bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
    1328                 :            :                                   uint16_t member_id, struct rte_mbuf *pkt)
    1329                 :            : {
    1330                 :            :         struct mode8023ad_private *mode4 = &internals->mode4;
    1331                 :          0 :         struct port *port = &bond_mode_8023ad_ports[member_id];
    1332                 :            :         struct marker_header *m_hdr;
    1333                 :            :         uint64_t marker_timer, old_marker_timer;
    1334                 :            :         int retval;
    1335                 :            :         uint8_t wrn, subtype;
    1336                 :            :         /* If packet is a marker, we send response now by reusing given packet
    1337                 :            :          * and update only source MAC, destination MAC is multicast so don't
    1338                 :            :          * update it. Other frames will be handled later by state machines */
    1339                 :          0 :         subtype = rte_pktmbuf_mtod(pkt,
    1340                 :            :                         struct slow_protocol_frame *)->slow_protocol.subtype;
    1341                 :            : 
    1342         [ #  # ]:          0 :         if (subtype == SLOW_SUBTYPE_MARKER) {
    1343                 :            :                 m_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *);
    1344                 :            : 
    1345         [ #  # ]:          0 :                 if (likely(m_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_INFO)) {
    1346                 :            :                         wrn = WRN_UNKNOWN_MARKER_TYPE;
    1347                 :          0 :                         goto free_out;
    1348                 :            :                 }
    1349                 :            : 
    1350                 :            :                 /* Setup marker timer. Do it in loop in case concurrent access. */
    1351                 :            :                 do {
    1352                 :          0 :                         old_marker_timer = port->rx_marker_timer;
    1353         [ #  # ]:          0 :                         if (!timer_is_expired(&old_marker_timer)) {
    1354                 :            :                                 wrn = WRN_RX_MARKER_TO_FAST;
    1355                 :          0 :                                 goto free_out;
    1356                 :            :                         }
    1357                 :            : 
    1358                 :          0 :                         timer_set(&marker_timer, mode4->rx_marker_timeout);
    1359                 :          0 :                         retval = rte_atomic64_cmpset(&port->rx_marker_timer,
    1360                 :            :                                 old_marker_timer, marker_timer);
    1361         [ #  # ]:          0 :                 } while (unlikely(retval == 0));
    1362                 :            : 
    1363                 :          0 :                 m_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP;
    1364                 :          0 :                 rte_eth_macaddr_get(member_id, &m_hdr->eth_hdr.src_addr);
    1365                 :            : 
    1366         [ #  # ]:          0 :                 if (internals->mode4.dedicated_queues.enabled == 0) {
    1367   [ #  #  #  #  :          0 :                         if (rte_ring_enqueue(port->tx_ring, pkt) != 0) {
                      # ]
    1368                 :            :                                 /* reset timer */
    1369                 :          0 :                                 port->rx_marker_timer = 0;
    1370                 :            :                                 wrn = WRN_TX_QUEUE_FULL;
    1371                 :          0 :                                 goto free_out;
    1372                 :            :                         }
    1373                 :            :                 } else {
    1374                 :            :                         /* Send packet directly to the slow queue */
    1375                 :            :                         uint16_t tx_count = rte_eth_tx_prepare(member_id,
    1376         [ #  # ]:          0 :                                         internals->mode4.dedicated_queues.tx_qid,
    1377                 :            :                                         &pkt, 1);
    1378                 :          0 :                         tx_count = rte_eth_tx_burst(member_id,
    1379                 :          0 :                                         internals->mode4.dedicated_queues.tx_qid,
    1380                 :            :                                         &pkt, tx_count);
    1381         [ #  # ]:          0 :                         if (tx_count != 1) {
    1382                 :            :                                 /* reset timer */
    1383                 :          0 :                                 port->rx_marker_timer = 0;
    1384                 :            :                                 wrn = WRN_TX_QUEUE_FULL;
    1385                 :          0 :                                 goto free_out;
    1386                 :            :                         }
    1387                 :            :                 }
    1388         [ #  # ]:          0 :         } else if (likely(subtype == SLOW_SUBTYPE_LACP)) {
    1389         [ #  # ]:          0 :                 if (internals->mode4.dedicated_queues.enabled == 0) {
    1390   [ #  #  #  #  :          0 :                         if (rte_ring_enqueue(port->rx_ring, pkt) != 0) {
                      # ]
    1391                 :            :                                 /* If RX fing full free lacpdu message and drop packet */
    1392                 :            :                                 wrn = WRN_RX_QUEUE_FULL;
    1393                 :          0 :                                 goto free_out;
    1394                 :            :                         }
    1395                 :            :                 } else
    1396                 :          0 :                         rx_machine_update(internals, member_id, pkt);
    1397                 :            :         } else {
    1398                 :            :                 wrn = WRN_UNKNOWN_SLOW_TYPE;
    1399                 :          0 :                 goto free_out;
    1400                 :            :         }
    1401                 :            : 
    1402                 :            :         return;
    1403                 :            : 
    1404                 :          0 : free_out:
    1405                 :            :         set_warning_flags(port, wrn);
    1406                 :          0 :         rte_pktmbuf_free(pkt);
    1407                 :            : }
    1408                 :            : 
    1409                 :            : int
    1410                 :          0 : rte_eth_bond_8023ad_conf_get(uint16_t port_id,
    1411                 :            :                 struct rte_eth_bond_8023ad_conf *conf)
    1412                 :            : {
    1413                 :            :         struct rte_eth_dev *bond_dev;
    1414                 :            : 
    1415         [ #  # ]:          0 :         if (valid_bonding_port_id(port_id) != 0)
    1416                 :            :                 return -EINVAL;
    1417                 :            : 
    1418         [ #  # ]:          0 :         if (conf == NULL)
    1419                 :            :                 return -EINVAL;
    1420                 :            : 
    1421                 :          0 :         bond_dev = &rte_eth_devices[port_id];
    1422                 :          0 :         bond_mode_8023ad_conf_get(bond_dev, conf);
    1423                 :          0 :         return 0;
    1424                 :            : }
    1425                 :            : 
    1426                 :            : int
    1427                 :          0 : rte_eth_bond_8023ad_agg_selection_set(uint16_t port_id,
    1428                 :            :                 enum rte_bond_8023ad_agg_selection agg_selection)
    1429                 :            : {
    1430                 :            :         struct rte_eth_dev *bond_dev;
    1431                 :            :         struct bond_dev_private *internals;
    1432                 :            :         struct mode8023ad_private *mode4;
    1433                 :            : 
    1434         [ #  # ]:          0 :         if (valid_bonding_port_id(port_id) != 0)
    1435                 :            :                 return -EINVAL;
    1436                 :            : 
    1437                 :            :         bond_dev = &rte_eth_devices[port_id];
    1438                 :          0 :         internals = bond_dev->data->dev_private;
    1439                 :            : 
    1440         [ #  # ]:          0 :         if (internals->mode != 4)
    1441                 :            :                 return -EINVAL;
    1442                 :            : 
    1443                 :            :         mode4 = &internals->mode4;
    1444         [ #  # ]:          0 :         if (agg_selection == AGG_COUNT || agg_selection == AGG_BANDWIDTH
    1445                 :            :                         || agg_selection == AGG_STABLE)
    1446                 :          0 :                 mode4->agg_selection = agg_selection;
    1447                 :            :         return 0;
    1448                 :            : }
    1449                 :            : 
    1450                 :          0 : int rte_eth_bond_8023ad_agg_selection_get(uint16_t port_id)
    1451                 :            : {
    1452                 :            :         struct rte_eth_dev *bond_dev;
    1453                 :            :         struct bond_dev_private *internals;
    1454                 :            :         struct mode8023ad_private *mode4;
    1455                 :            : 
    1456         [ #  # ]:          0 :         if (valid_bonding_port_id(port_id) != 0)
    1457                 :            :                 return -EINVAL;
    1458                 :            : 
    1459                 :            :         bond_dev = &rte_eth_devices[port_id];
    1460                 :          0 :         internals = bond_dev->data->dev_private;
    1461                 :            : 
    1462         [ #  # ]:          0 :         if (internals->mode != 4)
    1463                 :            :                 return -EINVAL;
    1464                 :            :         mode4 = &internals->mode4;
    1465                 :            : 
    1466                 :          0 :         return mode4->agg_selection;
    1467                 :            : }
    1468                 :            : 
    1469                 :            : 
    1470                 :            : 
    1471                 :            : static int
    1472                 :          0 : bond_8023ad_setup_validate(uint16_t port_id,
    1473                 :            :                 struct rte_eth_bond_8023ad_conf *conf)
    1474                 :            : {
    1475         [ #  # ]:          0 :         if (valid_bonding_port_id(port_id) != 0)
    1476                 :            :                 return -EINVAL;
    1477                 :            : 
    1478         [ #  # ]:          0 :         if (conf != NULL) {
    1479                 :            :                 /* Basic sanity check */
    1480         [ #  # ]:          0 :                 if (conf->slow_periodic_ms == 0 ||
    1481         [ #  # ]:          0 :                                 conf->fast_periodic_ms >= conf->slow_periodic_ms ||
    1482         [ #  # ]:          0 :                                 conf->long_timeout_ms == 0 ||
    1483         [ #  # ]:          0 :                                 conf->short_timeout_ms >= conf->long_timeout_ms ||
    1484         [ #  # ]:          0 :                                 conf->aggregate_wait_timeout_ms == 0 ||
    1485         [ #  # ]:          0 :                                 conf->tx_period_ms == 0 ||
    1486         [ #  # ]:          0 :                                 conf->rx_marker_period_ms == 0 ||
    1487         [ #  # ]:          0 :                                 conf->update_timeout_ms == 0) {
    1488                 :          0 :                         RTE_BOND_LOG(ERR, "given mode 4 configuration is invalid");
    1489                 :          0 :                         return -EINVAL;
    1490                 :            :                 }
    1491                 :            :         }
    1492                 :            : 
    1493                 :            :         return 0;
    1494                 :            : }
    1495                 :            : 
    1496                 :            : 
    1497                 :            : int
    1498                 :          0 : rte_eth_bond_8023ad_setup(uint16_t port_id,
    1499                 :            :                 struct rte_eth_bond_8023ad_conf *conf)
    1500                 :            : {
    1501                 :            :         struct rte_eth_dev *bond_dev;
    1502                 :            :         int err;
    1503                 :            : 
    1504                 :          0 :         err = bond_8023ad_setup_validate(port_id, conf);
    1505         [ #  # ]:          0 :         if (err != 0)
    1506                 :            :                 return err;
    1507                 :            : 
    1508                 :          0 :         bond_dev = &rte_eth_devices[port_id];
    1509                 :          0 :         bond_mode_8023ad_setup(bond_dev, conf);
    1510                 :            : 
    1511                 :          0 :         return 0;
    1512                 :            : }
    1513                 :            : 
    1514                 :            : 
    1515                 :            : 
    1516                 :            : 
    1517                 :            : 
    1518                 :            : int
    1519                 :          0 : rte_eth_bond_8023ad_member_info(uint16_t port_id, uint16_t member_id,
    1520                 :            :                 struct rte_eth_bond_8023ad_member_info *info)
    1521                 :            : {
    1522                 :            :         struct rte_eth_dev *bond_dev;
    1523                 :            :         struct bond_dev_private *internals;
    1524                 :            :         struct port *port;
    1525                 :            : 
    1526   [ #  #  #  #  :          0 :         if (info == NULL || valid_bonding_port_id(port_id) != 0 ||
                   #  # ]
    1527                 :          0 :                         rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
    1528                 :          0 :                 return -EINVAL;
    1529                 :            : 
    1530                 :            :         bond_dev = &rte_eth_devices[port_id];
    1531                 :            : 
    1532                 :          0 :         internals = bond_dev->data->dev_private;
    1533         [ #  # ]:          0 :         if (find_member_by_id(internals->active_members,
    1534                 :          0 :                         internals->active_member_count, member_id) ==
    1535                 :            :                                 internals->active_member_count)
    1536                 :            :                 return -EINVAL;
    1537                 :            : 
    1538                 :            :         port = &bond_mode_8023ad_ports[member_id];
    1539                 :          0 :         info->selected = port->selected;
    1540                 :            : 
    1541                 :          0 :         info->actor_state = port->actor_state;
    1542         [ #  # ]:          0 :         rte_memcpy(&info->actor, &port->actor, sizeof(port->actor));
    1543                 :            : 
    1544                 :          0 :         info->partner_state = port->partner_state;
    1545         [ #  # ]:          0 :         rte_memcpy(&info->partner, &port->partner, sizeof(port->partner));
    1546                 :            : 
    1547                 :          0 :         info->agg_port_id = port->aggregator_port_id;
    1548                 :          0 :         return 0;
    1549                 :            : }
    1550                 :            : 
    1551                 :            : static int
    1552                 :          0 : bond_8023ad_ext_validate(uint16_t port_id, uint16_t member_id)
    1553                 :            : {
    1554                 :            :         struct rte_eth_dev *bond_dev;
    1555                 :            :         struct bond_dev_private *internals;
    1556                 :            :         struct mode8023ad_private *mode4;
    1557                 :            : 
    1558         [ #  # ]:          0 :         if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
    1559                 :            :                 return -EINVAL;
    1560                 :            : 
    1561                 :            :         bond_dev = &rte_eth_devices[port_id];
    1562                 :            : 
    1563         [ #  # ]:          0 :         if (!bond_dev->data->dev_started)
    1564                 :            :                 return -EINVAL;
    1565                 :            : 
    1566                 :          0 :         internals = bond_dev->data->dev_private;
    1567         [ #  # ]:          0 :         if (find_member_by_id(internals->active_members,
    1568                 :          0 :                         internals->active_member_count, member_id) ==
    1569                 :            :                                 internals->active_member_count)
    1570                 :            :                 return -EINVAL;
    1571                 :            : 
    1572                 :            :         mode4 = &internals->mode4;
    1573         [ #  # ]:          0 :         if (mode4->slowrx_cb == NULL)
    1574                 :          0 :                 return -EINVAL;
    1575                 :            : 
    1576                 :            :         return 0;
    1577                 :            : }
    1578                 :            : 
    1579                 :            : int
    1580                 :          0 : rte_eth_bond_8023ad_ext_collect(uint16_t port_id, uint16_t member_id,
    1581                 :            :                                 int enabled)
    1582                 :            : {
    1583                 :            :         struct port *port;
    1584                 :            :         int res;
    1585                 :            : 
    1586                 :          0 :         res = bond_8023ad_ext_validate(port_id, member_id);
    1587         [ #  # ]:          0 :         if (res != 0)
    1588                 :            :                 return res;
    1589                 :            : 
    1590                 :            :         port = &bond_mode_8023ad_ports[member_id];
    1591                 :            : 
    1592         [ #  # ]:          0 :         if (enabled)
    1593                 :          0 :                 ACTOR_STATE_SET(port, COLLECTING);
    1594                 :            :         else
    1595                 :          0 :                 ACTOR_STATE_CLR(port, COLLECTING);
    1596                 :            : 
    1597                 :            :         return 0;
    1598                 :            : }
    1599                 :            : 
    1600                 :            : int
    1601                 :          0 : rte_eth_bond_8023ad_ext_distrib(uint16_t port_id, uint16_t member_id,
    1602                 :            :                                 int enabled)
    1603                 :            : {
    1604                 :            :         struct port *port;
    1605                 :            :         int res;
    1606                 :            : 
    1607                 :          0 :         res = bond_8023ad_ext_validate(port_id, member_id);
    1608         [ #  # ]:          0 :         if (res != 0)
    1609                 :            :                 return res;
    1610                 :            : 
    1611                 :            :         port = &bond_mode_8023ad_ports[member_id];
    1612                 :            : 
    1613         [ #  # ]:          0 :         if (enabled)
    1614                 :          0 :                 ACTOR_STATE_SET(port, DISTRIBUTING);
    1615                 :            :         else
    1616                 :          0 :                 ACTOR_STATE_CLR(port, DISTRIBUTING);
    1617                 :            : 
    1618                 :            :         return 0;
    1619                 :            : }
    1620                 :            : 
    1621                 :            : int
    1622                 :          0 : rte_eth_bond_8023ad_ext_distrib_get(uint16_t port_id, uint16_t member_id)
    1623                 :            : {
    1624                 :            :         struct port *port;
    1625                 :            :         int err;
    1626                 :            : 
    1627                 :          0 :         err = bond_8023ad_ext_validate(port_id, member_id);
    1628         [ #  # ]:          0 :         if (err != 0)
    1629                 :            :                 return err;
    1630                 :            : 
    1631                 :            :         port = &bond_mode_8023ad_ports[member_id];
    1632                 :          0 :         return ACTOR_STATE(port, DISTRIBUTING);
    1633                 :            : }
    1634                 :            : 
    1635                 :            : int
    1636                 :          0 : rte_eth_bond_8023ad_ext_collect_get(uint16_t port_id, uint16_t member_id)
    1637                 :            : {
    1638                 :            :         struct port *port;
    1639                 :            :         int err;
    1640                 :            : 
    1641                 :          0 :         err = bond_8023ad_ext_validate(port_id, member_id);
    1642         [ #  # ]:          0 :         if (err != 0)
    1643                 :            :                 return err;
    1644                 :            : 
    1645                 :            :         port = &bond_mode_8023ad_ports[member_id];
    1646                 :          0 :         return ACTOR_STATE(port, COLLECTING);
    1647                 :            : }
    1648                 :            : 
    1649                 :            : int
    1650                 :          0 : rte_eth_bond_8023ad_ext_slowtx(uint16_t port_id, uint16_t member_id,
    1651                 :            :                 struct rte_mbuf *lacp_pkt)
    1652                 :            : {
    1653                 :            :         struct port *port;
    1654                 :            :         int res;
    1655                 :            : 
    1656                 :          0 :         res = bond_8023ad_ext_validate(port_id, member_id);
    1657         [ #  # ]:          0 :         if (res != 0)
    1658                 :            :                 return res;
    1659                 :            : 
    1660                 :            :         port = &bond_mode_8023ad_ports[member_id];
    1661                 :            : 
    1662         [ #  # ]:          0 :         if (rte_pktmbuf_pkt_len(lacp_pkt) < sizeof(struct lacpdu_header))
    1663                 :            :                 return -EINVAL;
    1664                 :            : 
    1665                 :            :         struct lacpdu_header *lacp;
    1666                 :            : 
    1667                 :            :         /* only enqueue LACPDUs */
    1668                 :          0 :         lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
    1669         [ #  # ]:          0 :         if (lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
    1670                 :            :                 return -EINVAL;
    1671                 :            : 
    1672                 :            :         MODE4_DEBUG("sending LACP frame\n");
    1673                 :            : 
    1674   [ #  #  #  #  :          0 :         return rte_ring_enqueue(port->tx_ring, lacp_pkt);
                      # ]
    1675                 :            : }
    1676                 :            : 
    1677                 :            : static void
    1678                 :          0 : bond_mode_8023ad_ext_periodic_cb(void *arg)
    1679                 :            : {
    1680                 :            :         struct rte_eth_dev *bond_dev = arg;
    1681                 :          0 :         struct bond_dev_private *internals = bond_dev->data->dev_private;
    1682                 :            :         struct mode8023ad_private *mode4 = &internals->mode4;
    1683                 :            :         struct port *port;
    1684                 :          0 :         void *pkt = NULL;
    1685                 :            :         uint16_t i, member_id;
    1686                 :            : 
    1687         [ #  # ]:          0 :         for (i = 0; i < internals->active_member_count; i++) {
    1688                 :          0 :                 member_id = internals->active_members[i];
    1689                 :          0 :                 port = &bond_mode_8023ad_ports[member_id];
    1690                 :            : 
    1691   [ #  #  #  #  :          0 :                 if (rte_ring_dequeue(port->rx_ring, &pkt) == 0) {
                      # ]
    1692                 :          0 :                         struct rte_mbuf *lacp_pkt = pkt;
    1693                 :            :                         struct lacpdu_header *lacp;
    1694                 :            : 
    1695                 :          0 :                         lacp = rte_pktmbuf_mtod(lacp_pkt,
    1696                 :            :                                                 struct lacpdu_header *);
    1697         [ #  # ]:          0 :                         RTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
    1698                 :            : 
    1699                 :            :                         /* This is LACP frame so pass it to rx callback.
    1700                 :            :                          * Callback is responsible for freeing mbuf.
    1701                 :            :                          */
    1702                 :          0 :                         mode4->slowrx_cb(member_id, lacp_pkt);
    1703                 :            :                 }
    1704                 :            :         }
    1705                 :            : 
    1706                 :          0 :         rte_eal_alarm_set(internals->mode4.update_timeout_us,
    1707                 :            :                         bond_mode_8023ad_ext_periodic_cb, arg);
    1708                 :          0 : }
    1709                 :            : 
    1710                 :            : int
    1711                 :          0 : rte_eth_bond_8023ad_dedicated_queues_enable(uint16_t port)
    1712                 :            : {
    1713                 :            :         int retval = 0;
    1714                 :            :         struct rte_eth_dev *dev;
    1715                 :            :         struct bond_dev_private *internals;
    1716                 :            : 
    1717         [ #  # ]:          0 :         if (valid_bonding_port_id(port) != 0)
    1718                 :            :                 return -EINVAL;
    1719                 :            : 
    1720                 :          0 :         dev = &rte_eth_devices[port];
    1721                 :          0 :         internals = dev->data->dev_private;
    1722                 :            : 
    1723         [ #  # ]:          0 :         if (bond_8023ad_slow_pkt_hw_filter_supported(port) != 0)
    1724                 :            :                 return -1;
    1725                 :            : 
    1726                 :            :         /* Device must be stopped to set up slow queue */
    1727         [ #  # ]:          0 :         if (dev->data->dev_started)
    1728                 :            :                 return -1;
    1729                 :            : 
    1730                 :          0 :         internals->mode4.dedicated_queues.enabled = 1;
    1731                 :            : 
    1732                 :          0 :         bond_ethdev_mode_set(dev, internals->mode);
    1733                 :          0 :         return retval;
    1734                 :            : }
    1735                 :            : 
    1736                 :            : int
    1737                 :          0 : rte_eth_bond_8023ad_dedicated_queues_disable(uint16_t port)
    1738                 :            : {
    1739                 :            :         int retval = 0;
    1740                 :            :         struct rte_eth_dev *dev;
    1741                 :            :         struct bond_dev_private *internals;
    1742                 :            : 
    1743         [ #  # ]:          0 :         if (valid_bonding_port_id(port) != 0)
    1744                 :            :                 return -EINVAL;
    1745                 :            : 
    1746                 :          0 :         dev = &rte_eth_devices[port];
    1747                 :          0 :         internals = dev->data->dev_private;
    1748                 :            : 
    1749                 :            :         /* Device must be stopped to set up slow queue */
    1750         [ #  # ]:          0 :         if (dev->data->dev_started)
    1751                 :            :                 return -1;
    1752                 :            : 
    1753                 :          0 :         internals->mode4.dedicated_queues.enabled = 0;
    1754                 :            : 
    1755                 :          0 :         bond_ethdev_mode_set(dev, internals->mode);
    1756                 :            : 
    1757                 :          0 :         return retval;
    1758                 :            : }

Generated by: LCOV version 1.14