LCOV - code coverage report
Current view: top level - lib - lacp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 410 441 93.0 %
Date: 2016-09-14 01:02:56 Functions: 34 35 97.1 %
Branches: 196 274 71.5 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
       2                 :            :  *
       3                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            :  * you may not use this file except in compliance with the License.
       5                 :            :  * You may obtain a copy of the License at:
       6                 :            :  *
       7                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            :  *
       9                 :            :  * Unless required by applicable law or agreed to in writing, software
      10                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            :  * See the License for the specific language governing permissions and
      13                 :            :  * limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <config.h>
      17                 :            : #include "lacp.h"
      18                 :            : 
      19                 :            : #include <stdlib.h>
      20                 :            : 
      21                 :            : #include "connectivity.h"
      22                 :            : #include "openvswitch/dynamic-string.h"
      23                 :            : #include "hash.h"
      24                 :            : #include "openvswitch/hmap.h"
      25                 :            : #include "dp-packet.h"
      26                 :            : #include "ovs-atomic.h"
      27                 :            : #include "packets.h"
      28                 :            : #include "poll-loop.h"
      29                 :            : #include "seq.h"
      30                 :            : #include "openvswitch/shash.h"
      31                 :            : #include "timer.h"
      32                 :            : #include "timeval.h"
      33                 :            : #include "unixctl.h"
      34                 :            : #include "openvswitch/vlog.h"
      35                 :            : #include "util.h"
      36                 :            : 
      37                 :       1288 : VLOG_DEFINE_THIS_MODULE(lacp);
      38                 :            : 
      39                 :            : /* Masks for lacp_info state member. */
      40                 :            : #define LACP_STATE_ACT  0x01 /* Activity. Active or passive? */
      41                 :            : #define LACP_STATE_TIME 0x02 /* Timeout. Short or long timeout? */
      42                 :            : #define LACP_STATE_AGG  0x04 /* Aggregation. Is the link is bondable? */
      43                 :            : #define LACP_STATE_SYNC 0x08 /* Synchronization. Is the link in up to date? */
      44                 :            : #define LACP_STATE_COL  0x10 /* Collecting. Is the link receiving frames? */
      45                 :            : #define LACP_STATE_DIST 0x20 /* Distributing. Is the link sending frames? */
      46                 :            : #define LACP_STATE_DEF  0x40 /* Defaulted. Using default partner info? */
      47                 :            : #define LACP_STATE_EXP  0x80 /* Expired. Using expired partner info? */
      48                 :            : 
      49                 :            : #define LACP_FAST_TIME_TX 1000  /* Fast transmission rate. */
      50                 :            : #define LACP_SLOW_TIME_TX 30000 /* Slow transmission rate. */
      51                 :            : #define LACP_RX_MULTIPLIER 3    /* Multiply by TX rate to get RX rate. */
      52                 :            : 
      53                 :            : #define LACP_INFO_LEN 15
      54                 :            : OVS_PACKED(
      55                 :            : struct lacp_info {
      56                 :            :     ovs_be16 sys_priority;            /* System priority. */
      57                 :            :     struct eth_addr sys_id;           /* System ID. */
      58                 :            :     ovs_be16 key;                     /* Operational key. */
      59                 :            :     ovs_be16 port_priority;           /* Port priority. */
      60                 :            :     ovs_be16 port_id;                 /* Port ID. */
      61                 :            :     uint8_t state;                    /* State mask.  See LACP_STATE macros. */
      62                 :            : });
      63                 :            : BUILD_ASSERT_DECL(LACP_INFO_LEN == sizeof(struct lacp_info));
      64                 :            : 
      65                 :            : #define LACP_PDU_LEN 110
      66                 :            : struct lacp_pdu {
      67                 :            :     uint8_t subtype;          /* Always 1. */
      68                 :            :     uint8_t version;          /* Always 1. */
      69                 :            : 
      70                 :            :     uint8_t actor_type;       /* Always 1. */
      71                 :            :     uint8_t actor_len;        /* Always 20. */
      72                 :            :     struct lacp_info actor;   /* LACP actor information. */
      73                 :            :     uint8_t z1[3];            /* Reserved.  Always 0. */
      74                 :            : 
      75                 :            :     uint8_t partner_type;     /* Always 2. */
      76                 :            :     uint8_t partner_len;      /* Always 20. */
      77                 :            :     struct lacp_info partner; /* LACP partner information. */
      78                 :            :     uint8_t z2[3];            /* Reserved.  Always 0. */
      79                 :            : 
      80                 :            :     uint8_t collector_type;   /* Always 3. */
      81                 :            :     uint8_t collector_len;    /* Always 16. */
      82                 :            :     ovs_be16 collector_delay; /* Maximum collector delay. Set to UINT16_MAX. */
      83                 :            :     uint8_t z3[64];           /* Combination of several fields.  Always 0. */
      84                 :            : };
      85                 :            : BUILD_ASSERT_DECL(LACP_PDU_LEN == sizeof(struct lacp_pdu));
      86                 :            : 
      87                 :            : /* Implementation. */
      88                 :            : 
      89                 :            : enum slave_status {
      90                 :            :     LACP_CURRENT,   /* Current State.  Partner up to date. */
      91                 :            :     LACP_EXPIRED,   /* Expired State.  Partner out of date. */
      92                 :            :     LACP_DEFAULTED, /* Defaulted State.  No partner. */
      93                 :            : };
      94                 :            : 
      95                 :            : struct lacp {
      96                 :            :     struct ovs_list node;         /* Node in all_lacps list. */
      97                 :            :     char *name;                   /* Name of this lacp object. */
      98                 :            :     struct eth_addr sys_id;       /* System ID. */
      99                 :            :     uint16_t sys_priority;        /* System Priority. */
     100                 :            :     bool active;                  /* Active or Passive. */
     101                 :            : 
     102                 :            :     struct hmap slaves;      /* Slaves this LACP object controls. */
     103                 :            :     struct slave *key_slave; /* Slave whose ID will be the aggregation key. */
     104                 :            : 
     105                 :            :     bool fast;               /* True if using fast probe interval. */
     106                 :            :     bool negotiated;         /* True if LACP negotiations were successful. */
     107                 :            :     bool update;             /* True if lacp_update() needs to be called. */
     108                 :            :     bool fallback_ab; /* True if fallback to active-backup on LACP failure. */
     109                 :            : 
     110                 :            :     struct ovs_refcount ref_cnt;
     111                 :            : };
     112                 :            : 
     113                 :            : struct slave {
     114                 :            :     void *aux;                    /* Handle used to identify this slave. */
     115                 :            :     struct hmap_node node;        /* Node in master's slaves map. */
     116                 :            : 
     117                 :            :     struct lacp *lacp;            /* LACP object containing this slave. */
     118                 :            :     uint16_t port_id;             /* Port ID. */
     119                 :            :     uint16_t port_priority;       /* Port Priority. */
     120                 :            :     uint16_t key;                 /* Aggregation Key. 0 if default. */
     121                 :            :     char *name;                   /* Name of this slave. */
     122                 :            : 
     123                 :            :     enum slave_status status;     /* Slave status. */
     124                 :            :     bool attached;                /* Attached. Traffic may flow. */
     125                 :            :     struct lacp_info partner;     /* Partner information. */
     126                 :            :     struct lacp_info ntt_actor;   /* Used to decide if we Need To Transmit. */
     127                 :            :     struct timer tx;              /* Next message transmission timer. */
     128                 :            :     struct timer rx;              /* Expected message receive timer. */
     129                 :            : 
     130                 :            :     uint32_t count_rx_pdus;       /* dot3adAggPortStatsLACPDUsRx */
     131                 :            :     uint32_t count_rx_pdus_bad;   /* dot3adAggPortStatsIllegalRx */
     132                 :            :     uint32_t count_tx_pdus;       /* dot3adAggPortStatsLACPDUsTx */
     133                 :            : };
     134                 :            : 
     135                 :            : static struct ovs_mutex mutex;
     136                 :            : static struct ovs_list all_lacps__ = OVS_LIST_INITIALIZER(&all_lacps__);
     137                 :            : static struct ovs_list *const all_lacps OVS_GUARDED_BY(mutex) = &all_lacps__;
     138                 :            : 
     139                 :            : static void lacp_update_attached(struct lacp *) OVS_REQUIRES(mutex);
     140                 :            : 
     141                 :            : static void slave_destroy(struct slave *) OVS_REQUIRES(mutex);
     142                 :            : static void slave_set_defaulted(struct slave *) OVS_REQUIRES(mutex);
     143                 :            : static void slave_set_expired(struct slave *) OVS_REQUIRES(mutex);
     144                 :            : static void slave_get_actor(struct slave *, struct lacp_info *actor)
     145                 :            :     OVS_REQUIRES(mutex);
     146                 :            : static void slave_get_priority(struct slave *, struct lacp_info *priority)
     147                 :            :     OVS_REQUIRES(mutex);
     148                 :            : static bool slave_may_tx(const struct slave *)
     149                 :            :     OVS_REQUIRES(mutex);
     150                 :            : static struct slave *slave_lookup(const struct lacp *, const void *slave)
     151                 :            :     OVS_REQUIRES(mutex);
     152                 :            : static bool info_tx_equal(struct lacp_info *, struct lacp_info *)
     153                 :            :     OVS_REQUIRES(mutex);
     154                 :            : 
     155                 :            : static unixctl_cb_func lacp_unixctl_show;
     156                 :            : 
     157                 :            : /* Populates 'pdu' with a LACP PDU comprised of 'actor' and 'partner'. */
     158                 :            : static void
     159                 :         80 : compose_lacp_pdu(const struct lacp_info *actor,
     160                 :            :                  const struct lacp_info *partner, struct lacp_pdu *pdu)
     161                 :            : {
     162                 :         80 :     memset(pdu, 0, sizeof *pdu);
     163                 :            : 
     164                 :         80 :     pdu->subtype = 1;
     165                 :         80 :     pdu->version = 1;
     166                 :            : 
     167                 :         80 :     pdu->actor_type = 1;
     168                 :         80 :     pdu->actor_len = 20;
     169                 :         80 :     pdu->actor = *actor;
     170                 :            : 
     171                 :         80 :     pdu->partner_type = 2;
     172                 :         80 :     pdu->partner_len = 20;
     173                 :         80 :     pdu->partner = *partner;
     174                 :            : 
     175                 :         80 :     pdu->collector_type = 3;
     176                 :         80 :     pdu->collector_len = 16;
     177                 :         80 :     pdu->collector_delay = htons(0);
     178                 :         80 : }
     179                 :            : 
     180                 :            : /* Parses 'b' which represents a packet containing a LACP PDU.  This function
     181                 :            :  * returns NULL if 'b' is malformed, or does not represent a LACP PDU format
     182                 :            :  * supported by OVS.  Otherwise, it returns a pointer to the lacp_pdu contained
     183                 :            :  * within 'b'. */
     184                 :            : static const struct lacp_pdu *
     185                 :         54 : parse_lacp_packet(const struct dp_packet *p)
     186                 :            : {
     187                 :            :     const struct lacp_pdu *pdu;
     188                 :            : 
     189                 :         54 :     pdu = dp_packet_at(p, (uint8_t *)dp_packet_l3(p) - (uint8_t *)dp_packet_data(p),
     190                 :            :                     LACP_PDU_LEN);
     191                 :            : 
     192 [ +  - ][ +  - ]:         54 :     if (pdu && pdu->subtype == 1
     193 [ +  - ][ +  - ]:         54 :         && pdu->actor_type == 1 && pdu->actor_len == 20
     194 [ +  - ][ +  - ]:         54 :         && pdu->partner_type == 2 && pdu->partner_len == 20) {
     195                 :         54 :         return pdu;
     196                 :            :     } else {
     197                 :          0 :         return NULL;
     198                 :            :     }
     199                 :            : }
     200                 :            : 
     201                 :            : /* LACP Protocol Implementation. */
     202                 :            : 
     203                 :            : /* Initializes the lacp module. */
     204                 :            : void
     205                 :        617 : lacp_init(void)
     206                 :            : {
     207                 :        617 :     unixctl_command_register("lacp/show", "[port]", 0, 1,
     208                 :            :                              lacp_unixctl_show, NULL);
     209                 :        617 : }
     210                 :            : 
     211                 :            : static void
     212                 :      12199 : lacp_lock(void) OVS_ACQUIRES(mutex)
     213                 :            : {
     214                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     215                 :            : 
     216         [ +  + ]:      12199 :     if (ovsthread_once_start(&once)) {
     217                 :          9 :         ovs_mutex_init_recursive(&mutex);
     218                 :          9 :         ovsthread_once_done(&once);
     219                 :            :     }
     220                 :      12199 :     ovs_mutex_lock(&mutex);
     221                 :      12199 : }
     222                 :            : 
     223                 :            : static void
     224                 :      12199 : lacp_unlock(void) OVS_RELEASES(mutex)
     225                 :            : {
     226                 :      12199 :     ovs_mutex_unlock(&mutex);
     227                 :      12199 : }
     228                 :            : 
     229                 :            : /* Creates a LACP object. */
     230                 :            : struct lacp *
     231                 :         13 : lacp_create(void) OVS_EXCLUDED(mutex)
     232                 :            : {
     233                 :            :     struct lacp *lacp;
     234                 :            : 
     235                 :         13 :     lacp = xzalloc(sizeof *lacp);
     236                 :         13 :     hmap_init(&lacp->slaves);
     237                 :         13 :     ovs_refcount_init(&lacp->ref_cnt);
     238                 :            : 
     239                 :         13 :     lacp_lock();
     240                 :         13 :     ovs_list_push_back(all_lacps, &lacp->node);
     241                 :         13 :     lacp_unlock();
     242                 :         13 :     return lacp;
     243                 :            : }
     244                 :            : 
     245                 :            : struct lacp *
     246                 :        229 : lacp_ref(const struct lacp *lacp_)
     247                 :            : {
     248                 :        229 :     struct lacp *lacp = CONST_CAST(struct lacp *, lacp_);
     249         [ +  - ]:        229 :     if (lacp) {
     250                 :        229 :         ovs_refcount_ref(&lacp->ref_cnt);
     251                 :            :     }
     252                 :        229 :     return lacp;
     253                 :            : }
     254                 :            : 
     255                 :            : /* Destroys 'lacp' and its slaves. Does nothing if 'lacp' is NULL. */
     256                 :            : void
     257                 :     228401 : lacp_unref(struct lacp *lacp) OVS_EXCLUDED(mutex)
     258                 :            : {
     259 [ +  + ][ +  + ]:     228401 :     if (lacp && ovs_refcount_unref_relaxed(&lacp->ref_cnt) == 1) {
     260                 :            :         struct slave *slave, *next;
     261                 :            : 
     262                 :         13 :         lacp_lock();
     263 [ +  - ][ -  + ]:         13 :         HMAP_FOR_EACH_SAFE (slave, next, node, &lacp->slaves) {
                 [ -  + ]
     264                 :          0 :             slave_destroy(slave);
     265                 :            :         }
     266                 :            : 
     267                 :         13 :         hmap_destroy(&lacp->slaves);
     268                 :         13 :         ovs_list_remove(&lacp->node);
     269                 :         13 :         free(lacp->name);
     270                 :         13 :         free(lacp);
     271                 :         13 :         lacp_unlock();
     272                 :            :     }
     273                 :     228401 : }
     274                 :            : 
     275                 :            : /* Configures 'lacp' with settings from 's'. */
     276                 :            : void
     277                 :         20 : lacp_configure(struct lacp *lacp, const struct lacp_settings *s)
     278                 :            :     OVS_EXCLUDED(mutex)
     279                 :            : {
     280         [ -  + ]:         20 :     ovs_assert(!eth_addr_is_zero(s->id));
     281                 :            : 
     282                 :         20 :     lacp_lock();
     283 [ +  + ][ -  + ]:         20 :     if (!lacp->name || strcmp(s->name, lacp->name)) {
     284                 :         13 :         free(lacp->name);
     285                 :         13 :         lacp->name = xstrdup(s->name);
     286                 :            :     }
     287                 :            : 
     288         [ +  + ]:         20 :     if (!eth_addr_equals(lacp->sys_id, s->id)
     289         [ -  + ]:          7 :         || lacp->sys_priority != s->priority) {
     290                 :         13 :         lacp->sys_id = s->id;
     291                 :         13 :         lacp->sys_priority = s->priority;
     292                 :         13 :         lacp->update = true;
     293                 :            :     }
     294                 :            : 
     295                 :         20 :     lacp->active = s->active;
     296                 :         20 :     lacp->fast = s->fast;
     297                 :            : 
     298         [ -  + ]:         20 :     if (lacp->fallback_ab != s->fallback_ab_cfg) {
     299                 :          0 :         lacp->fallback_ab = s->fallback_ab_cfg;
     300                 :          0 :         lacp->update = true;
     301                 :            :     }
     302                 :            : 
     303                 :         20 :     lacp_unlock();
     304                 :         20 : }
     305                 :            : 
     306                 :            : /* Returns true if 'lacp' is configured in active mode, false if 'lacp' is
     307                 :            :  * configured for passive mode. */
     308                 :            : bool
     309                 :          0 : lacp_is_active(const struct lacp *lacp) OVS_EXCLUDED(mutex)
     310                 :            : {
     311                 :            :     bool ret;
     312                 :          0 :     lacp_lock();
     313                 :          0 :     ret = lacp->active;
     314                 :          0 :     lacp_unlock();
     315                 :          0 :     return ret;
     316                 :            : }
     317                 :            : 
     318                 :            : /* Processes 'packet' which was received on 'slave_'.  This function should be
     319                 :            :  * called on all packets received on 'slave_' with Ethernet Type ETH_TYPE_LACP.
     320                 :            :  */
     321                 :            : void
     322                 :         54 : lacp_process_packet(struct lacp *lacp, const void *slave_,
     323                 :            :                     const struct dp_packet *packet)
     324                 :            :     OVS_EXCLUDED(mutex)
     325                 :            : {
     326                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     327                 :            :     const struct lacp_pdu *pdu;
     328                 :            :     long long int tx_rate;
     329                 :            :     struct slave *slave;
     330                 :            : 
     331                 :         54 :     lacp_lock();
     332                 :         54 :     slave = slave_lookup(lacp, slave_);
     333         [ -  + ]:         54 :     if (!slave) {
     334                 :          0 :         goto out;
     335                 :            :     }
     336                 :         54 :     slave->count_rx_pdus++;
     337                 :            : 
     338                 :         54 :     pdu = parse_lacp_packet(packet);
     339         [ -  + ]:         54 :     if (!pdu) {
     340                 :          0 :     slave->count_rx_pdus_bad++;
     341         [ #  # ]:          0 :         VLOG_WARN_RL(&rl, "%s: received an unparsable LACP PDU.", lacp->name);
     342                 :          0 :         goto out;
     343                 :            :     }
     344                 :            : 
     345                 :         54 :     slave->status = LACP_CURRENT;
     346         [ +  + ]:         54 :     tx_rate = lacp->fast ? LACP_FAST_TIME_TX : LACP_SLOW_TIME_TX;
     347                 :         54 :     timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER * tx_rate);
     348                 :            : 
     349                 :         54 :     slave->ntt_actor = pdu->partner;
     350                 :            : 
     351                 :            :     /* Update our information about our partner if it's out of date.  This may
     352                 :            :      * cause priorities to change so re-calculate attached status of all
     353                 :            :      * slaves.  */
     354         [ +  + ]:         54 :     if (memcmp(&slave->partner, &pdu->actor, sizeof pdu->actor)) {
     355                 :         30 :         lacp->update = true;
     356                 :         30 :         slave->partner = pdu->actor;
     357                 :            :     }
     358                 :            : 
     359                 :            : out:
     360                 :         54 :     lacp_unlock();
     361                 :         54 : }
     362                 :            : 
     363                 :            : /* Returns the lacp_status of the given 'lacp' object (which may be NULL). */
     364                 :            : enum lacp_status
     365                 :       5410 : lacp_status(const struct lacp *lacp) OVS_EXCLUDED(mutex)
     366                 :            : {
     367         [ +  + ]:       5410 :     if (lacp) {
     368                 :            :         enum lacp_status ret;
     369                 :            : 
     370                 :       3894 :         lacp_lock();
     371         [ +  - ]:       3894 :         ret = lacp->negotiated ? LACP_NEGOTIATED : LACP_CONFIGURED;
     372                 :       3894 :         lacp_unlock();
     373                 :       3894 :         return ret;
     374                 :            :     } else {
     375                 :            :         /* Don't take 'mutex'.  It might not even be initialized, since we
     376                 :            :          * don't know that any lacp object has been created. */
     377                 :       1516 :         return LACP_DISABLED;
     378                 :            :     }
     379                 :            : }
     380                 :            : 
     381                 :            : /* Registers 'slave_' as subordinate to 'lacp'.  This should be called at least
     382                 :            :  * once per slave in a LACP managed bond.  Should also be called whenever a
     383                 :            :  * slave's settings change. */
     384                 :            : void
     385                 :         41 : lacp_slave_register(struct lacp *lacp, void *slave_,
     386                 :            :                     const struct lacp_slave_settings *s)
     387                 :            :     OVS_EXCLUDED(mutex)
     388                 :            : {
     389                 :            :     struct slave *slave;
     390                 :            : 
     391                 :         41 :     lacp_lock();
     392                 :         41 :     slave = slave_lookup(lacp, slave_);
     393         [ +  + ]:         41 :     if (!slave) {
     394                 :         27 :         slave = xzalloc(sizeof *slave);
     395                 :         27 :         slave->lacp = lacp;
     396                 :         27 :         slave->aux = slave_;
     397                 :         27 :         hmap_insert(&lacp->slaves, &slave->node, hash_pointer(slave_, 0));
     398                 :         27 :         slave_set_defaulted(slave);
     399                 :            : 
     400         [ +  + ]:         27 :         if (!lacp->key_slave) {
     401                 :         13 :             lacp->key_slave = slave;
     402                 :            :         }
     403                 :            :     }
     404                 :            : 
     405 [ +  + ][ -  + ]:         41 :     if (!slave->name || strcmp(s->name, slave->name)) {
     406                 :         27 :         free(slave->name);
     407                 :         27 :         slave->name = xstrdup(s->name);
     408                 :            :     }
     409                 :            : 
     410         [ +  + ]:         41 :     if (slave->port_id != s->id
     411         [ +  - ]:         14 :         || slave->port_priority != s->priority
     412         [ -  + ]:         14 :         || slave->key != s->key) {
     413                 :         27 :         slave->port_id = s->id;
     414                 :         27 :         slave->port_priority = s->priority;
     415                 :         27 :         slave->key = s->key;
     416                 :            : 
     417                 :         27 :         lacp->update = true;
     418                 :            : 
     419 [ -  + ][ #  # ]:         27 :         if (lacp->active || lacp->negotiated) {
     420                 :         27 :             slave_set_expired(slave);
     421                 :            :         }
     422                 :            :     }
     423                 :         41 :     lacp_unlock();
     424                 :         41 : }
     425                 :            : 
     426                 :            : /* Unregisters 'slave_' with 'lacp'.  */
     427                 :            : void
     428                 :         27 : lacp_slave_unregister(struct lacp *lacp, const void *slave_)
     429                 :            :     OVS_EXCLUDED(mutex)
     430                 :            : {
     431                 :            :     struct slave *slave;
     432                 :            : 
     433                 :         27 :     lacp_lock();
     434                 :         27 :     slave = slave_lookup(lacp, slave_);
     435         [ +  - ]:         27 :     if (slave) {
     436                 :         27 :         slave_destroy(slave);
     437                 :         27 :         lacp->update = true;
     438                 :            :     }
     439                 :         27 :     lacp_unlock();
     440                 :         27 : }
     441                 :            : 
     442                 :            : /* This function should be called whenever the carrier status of 'slave_' has
     443                 :            :  * changed.  If 'lacp' is null, this function has no effect.*/
     444                 :            : void
     445                 :         97 : lacp_slave_carrier_changed(const struct lacp *lacp, const void *slave_)
     446                 :            :     OVS_EXCLUDED(mutex)
     447                 :            : {
     448                 :            :     struct slave *slave;
     449         [ +  - ]:         97 :     if (!lacp) {
     450                 :         97 :         return;
     451                 :            :     }
     452                 :            : 
     453                 :          0 :     lacp_lock();
     454                 :          0 :     slave = slave_lookup(lacp, slave_);
     455         [ #  # ]:          0 :     if (!slave) {
     456                 :          0 :         goto out;
     457                 :            :     }
     458                 :            : 
     459 [ #  # ][ #  # ]:          0 :     if (slave->status == LACP_CURRENT || slave->lacp->active) {
     460                 :          0 :         slave_set_expired(slave);
     461                 :            :     }
     462                 :            : 
     463                 :            : out:
     464                 :          0 :     lacp_unlock();
     465                 :            : }
     466                 :            : 
     467                 :            : static bool
     468                 :        213 : slave_may_enable__(struct slave *slave) OVS_REQUIRES(mutex)
     469                 :            : {
     470                 :            :     /* The slave may be enabled if it's attached to an aggregator and its
     471                 :            :      * partner is synchronized.*/
     472 [ +  + ][ +  + ]:        251 :     return slave->attached && (slave->partner.state & LACP_STATE_SYNC
     473 [ +  - ][ -  + ]:         38 :             || (slave->lacp && slave->lacp->fallback_ab
     474         [ #  # ]:          0 :                 && slave->status == LACP_DEFAULTED));
     475                 :            : }
     476                 :            : 
     477                 :            : /* This function should be called before enabling 'slave_' to send or receive
     478                 :            :  * traffic.  If it returns false, 'slave_' should not enabled.  As a
     479                 :            :  * convenience, returns true if 'lacp' is NULL. */
     480                 :            : bool
     481                 :       7020 : lacp_slave_may_enable(const struct lacp *lacp, const void *slave_)
     482                 :            :     OVS_EXCLUDED(mutex)
     483                 :            : {
     484         [ +  + ]:       7020 :     if (lacp) {
     485                 :            :         struct slave *slave;
     486                 :            :         bool ret;
     487                 :            : 
     488                 :        152 :         lacp_lock();
     489                 :        152 :         slave = slave_lookup(lacp, slave_);
     490 [ +  - ][ +  + ]:        152 :         ret = slave ? slave_may_enable__(slave) : false;
     491                 :        152 :         lacp_unlock();
     492                 :        152 :         return ret;
     493                 :            :     } else {
     494                 :       6868 :         return true;
     495                 :            :     }
     496                 :            : }
     497                 :            : 
     498                 :            : /* Returns true if partner information on 'slave_' is up to date.  'slave_'
     499                 :            :  * not being current, generally indicates a connectivity problem, or a
     500                 :            :  * misconfigured (or broken) partner. */
     501                 :            : bool
     502                 :        145 : lacp_slave_is_current(const struct lacp *lacp, const void *slave_)
     503                 :            :     OVS_EXCLUDED(mutex)
     504                 :            : {
     505                 :            :     struct slave *slave;
     506                 :            :     bool ret;
     507                 :            : 
     508                 :        145 :     lacp_lock();
     509                 :        145 :     slave = slave_lookup(lacp, slave_);
     510 [ +  - ][ +  + ]:        145 :     ret = slave ? slave->status != LACP_DEFAULTED : false;
     511                 :        145 :     lacp_unlock();
     512                 :        145 :     return ret;
     513                 :            : }
     514                 :            : 
     515                 :            : /* This function should be called periodically to update 'lacp'. */
     516                 :            : void
     517                 :       3909 : lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
     518                 :            : {
     519                 :            :     struct slave *slave;
     520                 :            : 
     521                 :       3909 :     lacp_lock();
     522 [ +  + ][ -  + ]:      14690 :     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
     523         [ +  + ]:      10781 :         if (timer_expired(&slave->rx)) {
     524                 :         70 :             enum slave_status old_status = slave->status;
     525                 :            : 
     526         [ +  + ]:         70 :             if (slave->status == LACP_CURRENT) {
     527                 :          4 :                 slave_set_expired(slave);
     528         [ +  + ]:         66 :             } else if (slave->status == LACP_EXPIRED) {
     529                 :          2 :                 slave_set_defaulted(slave);
     530                 :            :             }
     531         [ +  + ]:         70 :             if (slave->status != old_status) {
     532                 :          6 :                 seq_change(connectivity_seq_get());
     533                 :            :             }
     534                 :            :         }
     535                 :            :     }
     536                 :            : 
     537         [ +  + ]:       3909 :     if (lacp->update) {
     538                 :         27 :         lacp_update_attached(lacp);
     539                 :            :     }
     540                 :            : 
     541 [ +  + ][ -  + ]:      14690 :     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
     542                 :            :         struct lacp_info actor;
     543                 :            : 
     544         [ -  + ]:      10781 :         if (!slave_may_tx(slave)) {
     545                 :          0 :             continue;
     546                 :            :         }
     547                 :            : 
     548                 :      10781 :         slave_get_actor(slave, &actor);
     549                 :            : 
     550         [ +  + ]:      10781 :         if (timer_expired(&slave->tx)
     551         [ +  + ]:      10710 :             || !info_tx_equal(&actor, &slave->ntt_actor)) {
     552                 :            :             long long int duration;
     553                 :            :             struct lacp_pdu pdu;
     554                 :            : 
     555                 :         80 :             slave->ntt_actor = actor;
     556                 :         80 :             compose_lacp_pdu(&actor, &slave->partner, &pdu);
     557                 :         80 :             send_pdu(slave->aux, &pdu, sizeof pdu);
     558                 :         80 :         slave->count_tx_pdus++;
     559                 :            : 
     560         [ +  + ]:         80 :             duration = (slave->partner.state & LACP_STATE_TIME
     561                 :            :                         ? LACP_FAST_TIME_TX
     562                 :            :                         : LACP_SLOW_TIME_TX);
     563                 :            : 
     564                 :         80 :             timer_set_duration(&slave->tx, duration);
     565                 :      10781 :             seq_change(connectivity_seq_get());
     566                 :            :         }
     567                 :            :     }
     568                 :       3909 :     lacp_unlock();
     569                 :       3909 : }
     570                 :            : 
     571                 :            : /* Causes poll_block() to wake up when lacp_run() needs to be called again. */
     572                 :            : void
     573                 :       3902 : lacp_wait(struct lacp *lacp) OVS_EXCLUDED(mutex)
     574                 :            : {
     575                 :            :     struct slave *slave;
     576                 :            : 
     577                 :       3902 :     lacp_lock();
     578 [ +  + ][ -  + ]:      14669 :     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
     579         [ +  - ]:      10767 :         if (slave_may_tx(slave)) {
     580                 :      10767 :             timer_wait(&slave->tx);
     581                 :            :         }
     582                 :            : 
     583         [ +  + ]:      10767 :         if (slave->status != LACP_DEFAULTED) {
     584                 :      10701 :             timer_wait(&slave->rx);
     585                 :            :         }
     586                 :            :     }
     587                 :       3902 :     lacp_unlock();
     588                 :       3902 : }
     589                 :            : 
     590                 :            : /* Static Helpers. */
     591                 :            : 
     592                 :            : /* Updates the attached status of all slaves controlled by 'lacp' and sets its
     593                 :            :  * negotiated parameter to true if any slaves are attachable. */
     594                 :            : static void
     595                 :         27 : lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
     596                 :            : {
     597                 :            :     struct slave *lead, *slave;
     598                 :            :     struct lacp_info lead_pri;
     599                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
     600                 :            : 
     601                 :         27 :     lacp->update = false;
     602                 :            : 
     603                 :         27 :     lead = NULL;
     604 [ +  + ][ -  + ]:         84 :     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
     605                 :            :         struct lacp_info pri;
     606                 :            : 
     607                 :         57 :         slave->attached = false;
     608                 :            : 
     609                 :            :         /* XXX: In the future allow users to configure the expected system ID.
     610                 :            :          * For now just special case loopback. */
     611         [ -  + ]:         57 :         if (eth_addr_equals(slave->partner.sys_id, slave->lacp->sys_id)) {
     612         [ #  # ]:          0 :             VLOG_WARN_RL(&rl, "slave %s: Loopback detected. Slave is "
     613                 :            :                          "connected to its own bond", slave->name);
     614                 :          2 :             continue;
     615                 :            :         }
     616                 :            : 
     617         [ +  + ]:         57 :         if (slave->status == LACP_DEFAULTED) {
     618         [ -  + ]:          2 :             if (lacp->fallback_ab) {
     619                 :          0 :                 slave->attached = true;
     620                 :            :             }
     621                 :          2 :             continue;
     622                 :            :         }
     623                 :            : 
     624                 :         55 :         slave->attached = true;
     625                 :         55 :         slave_get_priority(slave, &pri);
     626                 :            : 
     627 [ +  + ][ +  + ]:         55 :         if (!lead || memcmp(&pri, &lead_pri, sizeof pri) < 0) {
     628                 :         33 :             lead = slave;
     629                 :         55 :             lead_pri = pri;
     630                 :            :         }
     631                 :            :     }
     632                 :            : 
     633                 :         27 :     lacp->negotiated = lead != NULL;
     634                 :            : 
     635         [ +  - ]:         27 :     if (lead) {
     636 [ +  + ][ -  + ]:         84 :         HMAP_FOR_EACH (slave, node, &lacp->slaves) {
     637 [ -  + ][ #  # ]:         57 :             if ((lacp->fallback_ab && slave->status == LACP_DEFAULTED)
     638         [ +  + ]:         57 :                 || lead->partner.key != slave->partner.key
     639         [ -  + ]:         55 :                 || !eth_addr_equals(lead->partner.sys_id,
     640                 :            :                                     slave->partner.sys_id)) {
     641                 :          2 :                 slave->attached = false;
     642                 :            :             }
     643                 :            :         }
     644                 :            :     }
     645                 :         27 : }
     646                 :            : 
     647                 :            : static void
     648                 :         27 : slave_destroy(struct slave *slave) OVS_REQUIRES(mutex)
     649                 :            : {
     650         [ +  - ]:         27 :     if (slave) {
     651                 :         27 :         struct lacp *lacp = slave->lacp;
     652                 :            : 
     653                 :         27 :         lacp->update = true;
     654                 :         27 :         hmap_remove(&lacp->slaves, &slave->node);
     655                 :            : 
     656         [ +  + ]:         27 :         if (lacp->key_slave == slave) {
     657                 :         26 :             struct hmap_node *slave_node = hmap_first(&lacp->slaves);
     658                 :            : 
     659         [ +  + ]:         26 :             if (slave_node) {
     660                 :         13 :                 lacp->key_slave = CONTAINER_OF(slave_node, struct slave, node);
     661                 :            :             } else {
     662                 :         13 :                 lacp->key_slave = NULL;
     663                 :            :             }
     664                 :            :         }
     665                 :            : 
     666                 :         27 :         free(slave->name);
     667                 :         27 :         free(slave);
     668                 :            :     }
     669                 :         27 : }
     670                 :            : 
     671                 :            : static void
     672                 :         29 : slave_set_defaulted(struct slave *slave) OVS_REQUIRES(mutex)
     673                 :            : {
     674                 :         29 :     memset(&slave->partner, 0, sizeof slave->partner);
     675                 :            : 
     676                 :         29 :     slave->lacp->update = true;
     677                 :         29 :     slave->status = LACP_DEFAULTED;
     678                 :         29 : }
     679                 :            : 
     680                 :            : static void
     681                 :         31 : slave_set_expired(struct slave *slave) OVS_REQUIRES(mutex)
     682                 :            : {
     683                 :         31 :     slave->status = LACP_EXPIRED;
     684                 :         31 :     slave->partner.state |= LACP_STATE_TIME;
     685                 :         31 :     slave->partner.state &= ~LACP_STATE_SYNC;
     686                 :            : 
     687                 :         31 :     timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER * LACP_FAST_TIME_TX);
     688                 :         31 : }
     689                 :            : 
     690                 :            : static void
     691                 :      10864 : slave_get_actor(struct slave *slave, struct lacp_info *actor)
     692                 :            :     OVS_REQUIRES(mutex)
     693                 :            : {
     694                 :      10864 :     struct lacp *lacp = slave->lacp;
     695                 :            :     uint16_t key;
     696                 :      10864 :     uint8_t state = 0;
     697                 :            : 
     698         [ +  - ]:      10864 :     if (lacp->active) {
     699                 :      10864 :         state |= LACP_STATE_ACT;
     700                 :            :     }
     701                 :            : 
     702         [ +  + ]:      10864 :     if (lacp->fast) {
     703                 :      10294 :         state |= LACP_STATE_TIME;
     704                 :            :     }
     705                 :            : 
     706         [ +  + ]:      10864 :     if (slave->attached) {
     707                 :      10796 :         state |= LACP_STATE_SYNC;
     708                 :            :     }
     709                 :            : 
     710         [ +  + ]:      10864 :     if (slave->status == LACP_DEFAULTED) {
     711                 :         68 :         state |= LACP_STATE_DEF;
     712                 :            :     }
     713                 :            : 
     714         [ +  + ]:      10864 :     if (slave->status == LACP_EXPIRED) {
     715                 :        276 :         state |= LACP_STATE_EXP;
     716                 :            :     }
     717                 :            : 
     718         [ +  + ]:      10864 :     if (hmap_count(&lacp->slaves) > 1) {
     719                 :      10848 :         state |= LACP_STATE_AGG;
     720                 :            :     }
     721                 :            : 
     722 [ +  + ][ -  + ]:      10864 :     if (slave->attached || !lacp->negotiated) {
     723                 :      10796 :         state |= LACP_STATE_COL | LACP_STATE_DIST;
     724                 :            :     }
     725                 :            : 
     726                 :      10864 :     key = lacp->key_slave->key;
     727         [ +  + ]:      10864 :     if (!key) {
     728                 :       9903 :         key = lacp->key_slave->port_id;
     729                 :            :     }
     730                 :            : 
     731                 :      10864 :     actor->state = state;
     732                 :      10864 :     actor->key = htons(key);
     733                 :      10864 :     actor->port_priority = htons(slave->port_priority);
     734                 :      10864 :     actor->port_id = htons(slave->port_id);
     735                 :      10864 :     actor->sys_priority = htons(lacp->sys_priority);
     736                 :      10864 :     actor->sys_id = lacp->sys_id;
     737                 :      10864 : }
     738                 :            : 
     739                 :            : /* Given 'slave', populates 'priority' with data representing its LACP link
     740                 :            :  * priority.  If two priority objects populated by this function are compared
     741                 :            :  * using memcmp, the higher priority link will be less than the lower priority
     742                 :            :  * link. */
     743                 :            : static void
     744                 :         55 : slave_get_priority(struct slave *slave, struct lacp_info *priority)
     745                 :            :     OVS_REQUIRES(mutex)
     746                 :            : {
     747                 :            :     uint16_t partner_priority, actor_priority;
     748                 :            : 
     749                 :            :     /* Choose the lacp_info of the higher priority system by comparing their
     750                 :            :      * system priorities and mac addresses. */
     751                 :         55 :     actor_priority = slave->lacp->sys_priority;
     752                 :         55 :     partner_priority = ntohs(slave->partner.sys_priority);
     753         [ +  + ]:         55 :     if (actor_priority < partner_priority) {
     754                 :          8 :         slave_get_actor(slave, priority);
     755         [ +  + ]:         47 :     } else if (partner_priority < actor_priority) {
     756                 :         23 :         *priority = slave->partner;
     757         [ +  + ]:         24 :     } else if (eth_addr_compare_3way(slave->lacp->sys_id,
     758                 :            :                                      slave->partner.sys_id) < 0) {
     759                 :         12 :         slave_get_actor(slave, priority);
     760                 :            :     } else {
     761                 :         12 :         *priority = slave->partner;
     762                 :            :     }
     763                 :            : 
     764                 :            :     /* Key and state are not used in priority comparisons. */
     765                 :         55 :     priority->key = 0;
     766                 :         55 :     priority->state = 0;
     767                 :         55 : }
     768                 :            : 
     769                 :            : static bool
     770                 :      21548 : slave_may_tx(const struct slave *slave) OVS_REQUIRES(mutex)
     771                 :            : {
     772 [ -  + ][ #  # ]:      21548 :     return slave->lacp->active || slave->status != LACP_DEFAULTED;
     773                 :            : }
     774                 :            : 
     775                 :            : static struct slave *
     776                 :        421 : slave_lookup(const struct lacp *lacp, const void *slave_) OVS_REQUIRES(mutex)
     777                 :            : {
     778                 :            :     struct slave *slave;
     779                 :            : 
     780 [ +  + ][ -  + ]:        511 :     HMAP_FOR_EACH_IN_BUCKET (slave, node, hash_pointer(slave_, 0),
     781                 :            :                              &lacp->slaves) {
     782         [ +  + ]:        484 :         if (slave->aux == slave_) {
     783                 :        394 :             return slave;
     784                 :            :         }
     785                 :            :     }
     786                 :            : 
     787                 :         27 :     return NULL;
     788                 :            : }
     789                 :            : 
     790                 :            : /* Two lacp_info structures are tx_equal if and only if they do not differ in
     791                 :            :  * ways which would require a lacp_pdu transmission. */
     792                 :            : static bool
     793                 :      10710 : info_tx_equal(struct lacp_info *a, struct lacp_info *b)
     794                 :            : {
     795                 :            : 
     796                 :            :     /* LACP specification dictates that we transmit whenever the actor and
     797                 :            :      * remote_actor differ in the following fields: Port, Port Priority,
     798                 :            :      * System, System Priority, Aggregation Key, Activity State, Timeout State,
     799                 :            :      * Sync State, and Aggregation State. The state flags are most likely to
     800                 :            :      * change so are checked first. */
     801                 :      10710 :     return !((a->state ^ b->state) & (LACP_STATE_ACT
     802                 :            :                                       | LACP_STATE_TIME
     803                 :            :                                       | LACP_STATE_SYNC
     804                 :            :                                       | LACP_STATE_AGG))
     805         [ +  - ]:      10701 :         && a->port_id == b->port_id
     806         [ +  - ]:      10701 :         && a->port_priority == b->port_priority
     807         [ +  - ]:      10701 :         && a->key == b->key
     808         [ +  - ]:      10701 :         && a->sys_priority == b->sys_priority
     809 [ +  + ][ +  - ]:      21411 :         && eth_addr_equals(a->sys_id, b->sys_id);
     810                 :            : }
     811                 :            : 
     812                 :            : static struct lacp *
     813                 :         26 : lacp_find(const char *name) OVS_REQUIRES(mutex)
     814                 :            : {
     815                 :            :     struct lacp *lacp;
     816                 :            : 
     817         [ +  - ]:         39 :     LIST_FOR_EACH (lacp, node, all_lacps) {
     818         [ +  + ]:         39 :         if (!strcmp(lacp->name, name)) {
     819                 :         26 :             return lacp;
     820                 :            :         }
     821                 :            :     }
     822                 :            : 
     823                 :          0 :     return NULL;
     824                 :            : }
     825                 :            : 
     826                 :            : static void
     827                 :        122 : ds_put_lacp_state(struct ds *ds, uint8_t state)
     828                 :            : {
     829         [ +  + ]:        122 :     if (state & LACP_STATE_ACT) {
     830                 :        117 :         ds_put_cstr(ds, " activity");
     831                 :            :     }
     832                 :            : 
     833         [ +  + ]:        122 :     if (state & LACP_STATE_TIME) {
     834                 :        119 :         ds_put_cstr(ds, " timeout");
     835                 :            :     }
     836                 :            : 
     837         [ +  + ]:        122 :     if (state & LACP_STATE_AGG) {
     838                 :        116 :         ds_put_cstr(ds, " aggregation");
     839                 :            :     }
     840                 :            : 
     841         [ +  + ]:        122 :     if (state & LACP_STATE_SYNC) {
     842                 :        113 :         ds_put_cstr(ds, " synchronized");
     843                 :            :     }
     844                 :            : 
     845         [ +  + ]:        122 :     if (state & LACP_STATE_COL) {
     846                 :        115 :         ds_put_cstr(ds, " collecting");
     847                 :            :     }
     848                 :            : 
     849         [ +  + ]:        122 :     if (state & LACP_STATE_DIST) {
     850                 :        115 :         ds_put_cstr(ds, " distributing");
     851                 :            :     }
     852                 :            : 
     853         [ +  + ]:        122 :     if (state & LACP_STATE_DEF) {
     854                 :          2 :         ds_put_cstr(ds, " defaulted");
     855                 :            :     }
     856                 :            : 
     857         [ +  + ]:        122 :     if (state & LACP_STATE_EXP) {
     858                 :         26 :         ds_put_cstr(ds, " expired");
     859                 :            :     }
     860                 :        122 : }
     861                 :            : 
     862                 :            : static void
     863                 :         30 : lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
     864                 :            : {
     865                 :         30 :     struct shash slave_shash = SHASH_INITIALIZER(&slave_shash);
     866                 :         30 :     const struct shash_node **sorted_slaves = NULL;
     867                 :            : 
     868                 :            :     struct slave *slave;
     869                 :            :     int i;
     870                 :            : 
     871                 :         30 :     ds_put_format(ds, "---- %s ----\n", lacp->name);
     872         [ +  - ]:         30 :     ds_put_format(ds, "\tstatus: %s", lacp->active ? "active" : "passive");
     873         [ +  - ]:         30 :     if (lacp->negotiated) {
     874                 :         30 :         ds_put_cstr(ds, " negotiated");
     875                 :            :     }
     876                 :         30 :     ds_put_cstr(ds, "\n");
     877                 :            : 
     878                 :         30 :     ds_put_format(ds, "\tsys_id: " ETH_ADDR_FMT "\n", ETH_ADDR_ARGS(lacp->sys_id));
     879                 :         30 :     ds_put_format(ds, "\tsys_priority: %u\n", lacp->sys_priority);
     880                 :         30 :     ds_put_cstr(ds, "\taggregation key: ");
     881         [ +  - ]:         30 :     if (lacp->key_slave) {
     882         [ +  + ]:         30 :         ds_put_format(ds, "%u", lacp->key_slave->key
     883                 :         27 :                                 ? lacp->key_slave->key
     884                 :          3 :                                 : lacp->key_slave->port_id);
     885                 :            :     } else {
     886                 :          0 :         ds_put_cstr(ds, "none");
     887                 :            :     }
     888                 :         30 :     ds_put_cstr(ds, "\n");
     889                 :            : 
     890                 :         30 :     ds_put_cstr(ds, "\tlacp_time: ");
     891         [ +  + ]:         30 :     if (lacp->fast) {
     892                 :         29 :         ds_put_cstr(ds, "fast\n");
     893                 :            :     } else {
     894                 :          1 :         ds_put_cstr(ds, "slow\n");
     895                 :            :     }
     896                 :            : 
     897 [ +  + ][ -  + ]:         91 :     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
     898                 :         61 :         shash_add(&slave_shash, slave->name, slave);
     899                 :            :     }
     900                 :         30 :     sorted_slaves = shash_sort(&slave_shash);
     901                 :            : 
     902         [ +  + ]:         91 :     for (i = 0; i < shash_count(&slave_shash); i++) {
     903                 :            :         char *status;
     904                 :            :         struct lacp_info actor;
     905                 :            : 
     906                 :         61 :         slave = sorted_slaves[i]->data;
     907                 :         61 :         slave_get_actor(slave, &actor);
     908   [ +  +  +  - ]:         61 :         switch (slave->status) {
     909                 :            :         case LACP_CURRENT:
     910                 :         54 :             status = "current";
     911                 :         54 :             break;
     912                 :            :         case LACP_EXPIRED:
     913                 :          5 :             status = "expired";
     914                 :          5 :             break;
     915                 :            :         case LACP_DEFAULTED:
     916                 :          2 :             status = "defaulted";
     917                 :          2 :             break;
     918                 :            :         default:
     919                 :          0 :             OVS_NOT_REACHED();
     920                 :            :         }
     921                 :            : 
     922         [ +  + ]:         61 :         ds_put_format(ds, "\nslave: %s: %s %s\n", slave->name, status,
     923                 :         61 :                       slave->attached ? "attached" : "detached");
     924                 :         61 :         ds_put_format(ds, "\tport_id: %u\n", slave->port_id);
     925                 :         61 :         ds_put_format(ds, "\tport_priority: %u\n", slave->port_priority);
     926         [ +  + ]:         61 :         ds_put_format(ds, "\tmay_enable: %s\n", (slave_may_enable__(slave)
     927                 :            :                                                  ? "true" : "false"));
     928                 :            : 
     929                 :         61 :         ds_put_format(ds, "\n\tactor sys_id: " ETH_ADDR_FMT "\n",
     930                 :        366 :                       ETH_ADDR_ARGS(actor.sys_id));
     931                 :         61 :         ds_put_format(ds, "\tactor sys_priority: %u\n",
     932                 :         61 :                       ntohs(actor.sys_priority));
     933                 :         61 :         ds_put_format(ds, "\tactor port_id: %u\n",
     934                 :         61 :                       ntohs(actor.port_id));
     935                 :         61 :         ds_put_format(ds, "\tactor port_priority: %u\n",
     936                 :         61 :                       ntohs(actor.port_priority));
     937                 :         61 :         ds_put_format(ds, "\tactor key: %u\n",
     938                 :         61 :                       ntohs(actor.key));
     939                 :         61 :         ds_put_cstr(ds, "\tactor state:");
     940                 :         61 :         ds_put_lacp_state(ds, actor.state);
     941                 :         61 :         ds_put_cstr(ds, "\n\n");
     942                 :            : 
     943                 :         61 :         ds_put_format(ds, "\tpartner sys_id: " ETH_ADDR_FMT "\n",
     944                 :        366 :                       ETH_ADDR_ARGS(slave->partner.sys_id));
     945                 :         61 :         ds_put_format(ds, "\tpartner sys_priority: %u\n",
     946                 :         61 :                       ntohs(slave->partner.sys_priority));
     947                 :         61 :         ds_put_format(ds, "\tpartner port_id: %u\n",
     948                 :         61 :                       ntohs(slave->partner.port_id));
     949                 :         61 :         ds_put_format(ds, "\tpartner port_priority: %u\n",
     950                 :         61 :                       ntohs(slave->partner.port_priority));
     951                 :         61 :         ds_put_format(ds, "\tpartner key: %u\n",
     952                 :         61 :                       ntohs(slave->partner.key));
     953                 :         61 :         ds_put_cstr(ds, "\tpartner state:");
     954                 :         61 :         ds_put_lacp_state(ds, slave->partner.state);
     955                 :         61 :         ds_put_cstr(ds, "\n");
     956                 :            :     }
     957                 :            : 
     958                 :         30 :     shash_destroy(&slave_shash);
     959                 :         30 :     free(sorted_slaves);
     960                 :         30 : }
     961                 :            : 
     962                 :            : static void
     963                 :         29 : lacp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[],
     964                 :            :                   void *aux OVS_UNUSED) OVS_EXCLUDED(mutex)
     965                 :            : {
     966                 :         29 :     struct ds ds = DS_EMPTY_INITIALIZER;
     967                 :            :     struct lacp *lacp;
     968                 :            : 
     969                 :         29 :     lacp_lock();
     970         [ +  + ]:         29 :     if (argc > 1) {
     971                 :         26 :         lacp = lacp_find(argv[1]);
     972         [ -  + ]:         26 :         if (!lacp) {
     973                 :          0 :             unixctl_command_reply_error(conn, "no such lacp object");
     974                 :          0 :             goto out;
     975                 :            :         }
     976                 :         26 :         lacp_print_details(&ds, lacp);
     977                 :            :     } else {
     978         [ +  + ]:          7 :         LIST_FOR_EACH (lacp, node, all_lacps) {
     979                 :          4 :             lacp_print_details(&ds, lacp);
     980                 :            :         }
     981                 :            :     }
     982                 :            : 
     983                 :         29 :     unixctl_command_reply(conn, ds_cstr(&ds));
     984                 :         29 :     ds_destroy(&ds);
     985                 :            : 
     986                 :            : out:
     987                 :         29 :     lacp_unlock();
     988                 :         29 : }
     989                 :            : 
     990                 :            : /* Extract a snapshot of the current state and counters for a slave port.
     991                 :            :    Return false if the slave is not active. */
     992                 :            : bool
     993                 :          2 : lacp_get_slave_stats(const struct lacp *lacp, const void *slave_, struct lacp_slave_stats *stats)
     994                 :            :     OVS_EXCLUDED(mutex)
     995                 :            : {
     996                 :            :     struct slave *slave;
     997                 :            :     struct lacp_info actor;
     998                 :            :     bool ret;
     999                 :            : 
    1000                 :          2 :     ovs_mutex_lock(&mutex);
    1001                 :            : 
    1002                 :          2 :     slave = slave_lookup(lacp, slave_);
    1003         [ +  - ]:          2 :     if (slave) {
    1004                 :          2 :     ret = true;
    1005                 :          2 :     slave_get_actor(slave, &actor);
    1006                 :          2 :     stats->dot3adAggPortActorSystemID = actor.sys_id;
    1007                 :          2 :     stats->dot3adAggPortPartnerOperSystemID = slave->partner.sys_id;
    1008         [ +  - ]:          2 :     stats->dot3adAggPortAttachedAggID = (lacp->key_slave->key ?
    1009                 :          2 :                          lacp->key_slave->key :
    1010                 :          0 :                          lacp->key_slave->port_id);
    1011                 :            : 
    1012                 :            :     /* Construct my admin-state.  Assume aggregation is configured on. */
    1013                 :          2 :     stats->dot3adAggPortActorAdminState = LACP_STATE_AGG;
    1014         [ +  - ]:          2 :     if (lacp->active) {
    1015                 :          2 :         stats->dot3adAggPortActorAdminState |= LACP_STATE_ACT;
    1016                 :            :     }
    1017         [ +  - ]:          2 :     if (lacp->fast) {
    1018                 :          2 :         stats->dot3adAggPortActorAdminState |= LACP_STATE_TIME;
    1019                 :            :     }
    1020                 :            :     /* XXX Not sure how to know the partner admin state. It
    1021                 :            :      * might have to be captured and remembered during the
    1022                 :            :      * negotiation phase.
    1023                 :            :      */
    1024                 :          2 :     stats->dot3adAggPortPartnerAdminState = 0;
    1025                 :            : 
    1026                 :          2 :     stats->dot3adAggPortActorOperState = actor.state;
    1027                 :          2 :     stats->dot3adAggPortPartnerOperState = slave->partner.state;
    1028                 :            : 
    1029                 :            :     /* Read out the latest counters */
    1030                 :          2 :     stats->dot3adAggPortStatsLACPDUsRx = slave->count_rx_pdus;
    1031                 :          2 :     stats->dot3adAggPortStatsIllegalRx = slave->count_rx_pdus_bad;
    1032                 :          2 :     stats->dot3adAggPortStatsLACPDUsTx = slave->count_tx_pdus;
    1033                 :            :     } else {
    1034                 :          0 :         ret = false;
    1035                 :            :     }
    1036                 :          2 :     ovs_mutex_unlock(&mutex);
    1037                 :          2 :     return ret;
    1038                 :            : 
    1039                 :            : }

Generated by: LCOV version 1.12