LCOV - code coverage report
Current view: top level - lib - ovs-lldp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 72 385 18.7 %
Date: 2016-09-14 01:02:56 Functions: 9 34 26.5 %
Branches: 17 192 8.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2015 Nicira, Inc.
       3                 :            :  * Copyright (c) 2014 WindRiver, Inc.
       4                 :            :  * Copyright (c) 2015 Avaya, Inc.
       5                 :            :  *
       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       7                 :            :  * you may not use this file except in compliance with the License.
       8                 :            :  * You may obtain a copy of the License at:
       9                 :            :  *
      10                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      11                 :            :  *
      12                 :            :  * Unless required by applicable law or agreed to in writing, software
      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15                 :            :  * See the License for the specific language governing permissions and
      16                 :            :  * limitations under the License.
      17                 :            :  */
      18                 :            : 
      19                 :            : /* Implementation of Auto Attach.
      20                 :            :  * Based on sample implementation in 802.1ab.  Above copyright and license
      21                 :            :  * applies to all modifications.
      22                 :            :  * Limitations:
      23                 :            :  * - No support for multiple bridge.
      24                 :            :  * - Auto Attach state machine not implemented.
      25                 :            :  * - Auto Attach and LLDP code are bundled together.  The plan is to decoupled
      26                 :            :  *   them.
      27                 :            :  */
      28                 :            : 
      29                 :            : #include <config.h>
      30                 :            : #include "ovs-lldp.h"
      31                 :            : #include <arpa/inet.h>
      32                 :            : #include <inttypes.h>
      33                 :            : #include <netinet/in.h>
      34                 :            : #include <stdbool.h>
      35                 :            : #include <stdlib.h>
      36                 :            : #include <sys/types.h>
      37                 :            : #include "openvswitch/dynamic-string.h"
      38                 :            : #include "flow.h"
      39                 :            : #include "openvswitch/list.h"
      40                 :            : #include "lldp/lldpd.h"
      41                 :            : #include "lldp/lldpd-structs.h"
      42                 :            : #include "netdev.h"
      43                 :            : #include "openvswitch/types.h"
      44                 :            : #include "packets.h"
      45                 :            : #include "poll-loop.h"
      46                 :            : #include "smap.h"
      47                 :            : #include "unixctl.h"
      48                 :            : #include "util.h"
      49                 :            : #include "openvswitch/vlog.h"
      50                 :            : 
      51                 :       2462 : VLOG_DEFINE_THIS_MODULE(ovs_lldp);
      52                 :            : 
      53                 :            : #define LLDP_PROTOCOL_ID        0x0000
      54                 :            : #define LLDP_PROTOCOL_VERSION   0x00
      55                 :            : #define LLDP_TYPE_CONFIG        0x00
      56                 :            : #define LLDP_CHASSIS_TTL        120
      57                 :            : #define ETH_TYPE_LLDP           0x88cc
      58                 :            : #define MINIMUM_ETH_PACKET_SIZE 68
      59                 :            : 
      60                 :            : #define AA_STATUS_MULTIPLE \
      61                 :            :     AA_STATUS(ACTIVE,2,Active) \
      62                 :            :     AA_STATUS(REJECT_GENERIC,3,Reject (Generic)) \
      63                 :            :     AA_STATUS(REJECT_AA_RES_NOTAVAIL,4,Reject (AA resources unavailable)) \
      64                 :            :     AA_STATUS(REJECT_INVALID,6,Reject (Invalid)) \
      65                 :            :     AA_STATUS(REJECT_VLAN_RES_UNAVAIL,8,Reject (VLAN resources unavailable)) \
      66                 :            :     AA_STATUS(REJECT_VLAN_APP_ISSUE,9,Reject (Application interaction issue)) \
      67                 :            :     AA_STATUS(PENDING,255,Pending)
      68                 :            : 
      69                 :            : enum aa_status {
      70                 :            : #define AA_STATUS(NAME, VALUE, STR) AA_STATUS_##NAME = VALUE,
      71                 :            :     AA_STATUS_MULTIPLE
      72                 :            : #undef AA_STATUS
      73                 :            :     AA_STATUS_N_MULTIPLE
      74                 :            : };
      75                 :            : 
      76                 :            : /* Internal structure for an Auto Attach mapping.
      77                 :            :  */
      78                 :            : struct aa_mapping_internal {
      79                 :            :     struct hmap_node hmap_node_isid;
      80                 :            :     struct hmap_node hmap_node_aux;
      81                 :            :     uint32_t         isid;
      82                 :            :     uint16_t         vlan;
      83                 :            :     void             *aux;
      84                 :            :     enum aa_status   status;
      85                 :            : };
      86                 :            : 
      87                 :            : static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
      88                 :            : 
      89                 :            : /* Hash map of all LLDP instances keyed by name (port at the moment).
      90                 :            :  */
      91                 :            : static struct hmap all_lldps__ = HMAP_INITIALIZER(&all_lldps__);
      92                 :            : static struct hmap *const all_lldps OVS_GUARDED_BY(mutex) = &all_lldps__;
      93                 :            : 
      94                 :            : /* Hash map of all the Auto Attach mappings.  Global at the moment (but will
      95                 :            :  * be per bridge).  Used when adding a new port to a bridge so that we can
      96                 :            :  * properly install all the configured mapping on the port and export them
      97                 :            :  * To the Auto Attach server via LLDP.
      98                 :            :  */
      99                 :            : static struct hmap all_mappings__ = HMAP_INITIALIZER(&all_mappings__);
     100                 :            : static struct hmap *const all_mappings OVS_GUARDED_BY(mutex) = &all_mappings__;
     101                 :            : 
     102                 :            : static struct lldp_aa_element_system_id system_id_null;
     103                 :            : 
     104                 :            : /* Convert an LLDP chassis ID to a string.
     105                 :            :  */
     106                 :            : static void
     107                 :          0 : chassisid_to_string(uint8_t *array, size_t len, char **str)
     108                 :            : {
     109                 :            :     unsigned int i;
     110                 :            : 
     111                 :          0 :     *str = xmalloc(len * 3);
     112                 :            : 
     113         [ #  # ]:          0 :     for (i = 0; i < len; i++) {
     114                 :          0 :         snprintf(&(*str)[i * 3], 4, "%02x:", array[i]);
     115                 :            :     }
     116                 :          0 :     (*str)[(i * 3) - 1] = '\0';
     117                 :          0 : }
     118                 :            : 
     119                 :            : /* Find an Auto Attach mapping keyed by I-SID.
     120                 :            :  */
     121                 :            : static struct aa_mapping_internal *
     122                 :          0 : mapping_find_by_isid(struct lldp *lldp, uint32_t isid)
     123                 :            :     OVS_REQUIRES(mutex)
     124                 :            : {
     125                 :            :     struct aa_mapping_internal *m;
     126                 :            : 
     127 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH_IN_BUCKET (m, hmap_node_isid, hash_int(isid, 0),
     128                 :            :                              &lldp->mappings_by_isid) {
     129         [ #  # ]:          0 :         if (isid == m->isid) {
     130                 :          0 :             return m;
     131                 :            :         }
     132                 :            :     }
     133                 :            : 
     134                 :          0 :     return NULL;
     135                 :            : }
     136                 :            : 
     137                 :            : /* Find an Auto Attach mapping keyed by aux.  aux is an opaque pointer created
     138                 :            :  * by the bridge that refers to an OVSDB mapping record.
     139                 :            :  */
     140                 :            : static struct aa_mapping_internal *
     141                 :          0 : mapping_find_by_aux(struct lldp *lldp, const void *aux) OVS_REQUIRES(mutex)
     142                 :            : {
     143                 :            :     struct aa_mapping_internal *m;
     144                 :            : 
     145 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH_IN_BUCKET (m, hmap_node_aux, hash_pointer(aux, 0),
     146                 :            :                              &lldp->mappings_by_aux) {
     147         [ #  # ]:          0 :         if (aux == m->aux) {
     148                 :          0 :             return m;
     149                 :            :         }
     150                 :            :     }
     151                 :            : 
     152                 :          0 :     return NULL;
     153                 :            : }
     154                 :            : 
     155                 :            : /* Convert an Auto Attach request status to a string.
     156                 :            :  */
     157                 :            : static char *
     158                 :          0 : aa_status_to_str(uint8_t status)
     159                 :            : {
     160   [ #  #  #  #  :          0 :     switch (status) {
             #  #  #  # ]
     161                 :            : #define AA_STATUS(NAME, VALUE, STR) case AA_STATUS_##NAME: return #STR;
     162                 :          0 :         AA_STATUS_MULTIPLE
     163                 :            : #undef AA_STATUS
     164                 :          0 :         default: return "Undefined";
     165                 :            :     }
     166                 :            : }
     167                 :            : 
     168                 :            : /* Display LLDP and Auto Attach statistics.
     169                 :            :  */
     170                 :            : static void
     171                 :          0 : aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp)
     172                 :            :     OVS_REQUIRES(mutex)
     173                 :            : {
     174                 :            :     struct lldpd_hardware *hw;
     175                 :            : 
     176                 :          0 :     ds_put_format(ds, "Statistics: %s\n", lldp->name);
     177                 :            : 
     178         [ #  # ]:          0 :     if (!lldp->lldpd) {
     179                 :          0 :         return;
     180                 :            :     }
     181                 :            : 
     182         [ #  # ]:          0 :     LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
     183                 :          0 :         ds_put_format(ds, "\ttx cnt: %"PRIu64"\n", hw->h_tx_cnt);
     184                 :          0 :         ds_put_format(ds, "\trx cnt: %"PRIu64"\n", hw->h_rx_cnt);
     185                 :          0 :         ds_put_format(ds, "\trx discarded cnt: %"PRIu64"\n",
     186                 :            :                       hw->h_rx_discarded_cnt);
     187                 :          0 :         ds_put_format(ds, "\trx unrecognized cnt: %"PRIu64"\n",
     188                 :            :                       hw->h_rx_unrecognized_cnt);
     189                 :          0 :         ds_put_format(ds, "\tageout cnt: %"PRIu64"\n", hw->h_ageout_cnt);
     190                 :          0 :         ds_put_format(ds, "\tinsert cnt: %"PRIu64"\n", hw->h_insert_cnt);
     191                 :          0 :         ds_put_format(ds, "\tdelete cnt: %"PRIu64"\n", hw->h_delete_cnt);
     192                 :          0 :         ds_put_format(ds, "\tdrop cnt: %"PRIu64"\n", hw->h_drop_cnt);
     193                 :            :     }
     194                 :            : }
     195                 :            : 
     196                 :            : static void
     197                 :          0 : aa_print_element_status_port(struct ds *ds, struct lldpd_hardware *hw)
     198                 :            : {
     199                 :            :     struct lldpd_port *port;
     200                 :            : 
     201         [ #  # ]:          0 :     LIST_FOR_EACH (port, p_entries, &hw->h_rports) {
     202         [ #  # ]:          0 :         if (memcmp(&port->p_element.system_id,
     203                 :            :                    &system_id_null,
     204                 :            :                    sizeof port->p_element.system_id)) {
     205                 :          0 :             const char *none_str = "<None>";
     206                 :          0 :             const char *descr = NULL;
     207                 :          0 :             char *id = NULL;
     208                 :            :             char *system;
     209                 :            : 
     210         [ #  # ]:          0 :             if (port->p_chassis) {
     211         [ #  # ]:          0 :                 if (port->p_chassis->c_id_len > 0) {
     212                 :          0 :                     chassisid_to_string(port->p_chassis->c_id,
     213                 :          0 :                                         port->p_chassis->c_id_len, &id);
     214                 :            :                 }
     215                 :            : 
     216                 :          0 :                 descr = port->p_chassis->c_descr;
     217                 :            :             }
     218                 :            : 
     219                 :          0 :             chassisid_to_string((uint8_t *) &port->p_element.system_id,
     220                 :            :                 sizeof port->p_element.system_id, &system);
     221                 :            : 
     222         [ #  # ]:          0 :             ds_put_format(ds, "\tAuto Attach Primary Server Id: %s\n",
     223                 :          0 :                           id ? id : none_str);
     224         [ #  # ]:          0 :             ds_put_format(ds, "\tAuto Attach Primary Server Descr: %s\n",
     225                 :            :                           descr ? descr : none_str);
     226                 :          0 :             ds_put_format(ds, "\tAuto Attach Primary Server System Id: %s\n",
     227                 :            :                           system);
     228                 :            : 
     229                 :          0 :             free(id);
     230                 :          0 :             free(system);
     231                 :            :         }
     232                 :            :     }
     233                 :          0 : }
     234                 :            : 
     235                 :            : /* Auto Attach server broadcast an LLDP message periodically.  Display
     236                 :            :  * the discovered server.
     237                 :            :  */
     238                 :            : static void
     239                 :          0 : aa_print_element_status(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex)
     240                 :            : {
     241                 :            :     struct lldpd_hardware *hw;
     242                 :            : 
     243                 :          0 :     ds_put_format(ds, "LLDP: %s\n", lldp->name);
     244                 :            : 
     245         [ #  # ]:          0 :     if (!lldp->lldpd) {
     246                 :          0 :         return;
     247                 :            :     }
     248                 :            : 
     249         [ #  # ]:          0 :     LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
     250                 :          0 :         aa_print_element_status_port(ds, hw);
     251                 :            :     }
     252                 :            : }
     253                 :            : 
     254                 :            : static void
     255                 :          0 : aa_print_isid_status_port_isid(struct lldp *lldp, struct lldpd_port *port)
     256                 :            :     OVS_REQUIRES(mutex)
     257                 :            : {
     258                 :            :     struct lldpd_aa_isid_vlan_maps_tlv *mapping;
     259                 :            : 
     260         [ #  # ]:          0 :     if (ovs_list_is_empty(&port->p_isid_vlan_maps)) {
     261                 :          0 :         return;
     262                 :            :     }
     263                 :            : 
     264         [ #  # ]:          0 :     LIST_FOR_EACH (mapping, m_entries, &port->p_isid_vlan_maps) {
     265                 :          0 :         uint32_t isid = mapping->isid_vlan_data.isid;
     266                 :          0 :         struct aa_mapping_internal *m = mapping_find_by_isid(lldp, isid);
     267                 :            : 
     268         [ #  # ]:          0 :         VLOG_INFO("h_rport: isid=%u, vlan=%u, status=%d",
     269                 :            :                   isid,
     270                 :            :                   mapping->isid_vlan_data.vlan,
     271                 :            :                   mapping->isid_vlan_data.status);
     272                 :            : 
     273                 :            :         /* Update the status of our internal state for the mapping. */
     274         [ #  # ]:          0 :         if (m) {
     275         [ #  # ]:          0 :             VLOG_INFO("Setting status for ISID=%"PRIu32" to %"PRIu16,
     276                 :            :                       isid, mapping->isid_vlan_data.status);
     277                 :          0 :             m->status = mapping->isid_vlan_data.status;
     278                 :            :         } else {
     279         [ #  # ]:          0 :             VLOG_WARN("Couldn't find mapping for I-SID=%"PRIu32, isid);
     280                 :            :         }
     281                 :            :     }
     282                 :            : }
     283                 :            : 
     284                 :            : static void
     285                 :          0 : aa_print_isid_status_port(struct lldp *lldp, struct lldpd_hardware *hw)
     286                 :            :     OVS_REQUIRES(mutex)
     287                 :            : {
     288                 :            :     struct lldpd_port *port;
     289                 :            : 
     290         [ #  # ]:          0 :     LIST_FOR_EACH (port, p_entries, &hw->h_rports) {
     291                 :          0 :         aa_print_isid_status_port_isid(lldp, port);
     292                 :            :     }
     293                 :          0 : }
     294                 :            : 
     295                 :            : /* The Auto Attach server will broadcast the status of the configured mappings
     296                 :            :  * via LLDP.  Display the status.
     297                 :            :  */
     298                 :            : static void
     299                 :          0 : aa_print_isid_status(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex)
     300                 :            : {
     301                 :            :     struct lldpd_hardware *hw;
     302                 :            :     struct aa_mapping_internal *m;
     303                 :            : 
     304         [ #  # ]:          0 :     if (!lldp->lldpd) {
     305                 :          0 :         return;
     306                 :            :     }
     307                 :            : 
     308                 :          0 :     ds_put_format(ds, "LLDP: %s\n", lldp->name);
     309                 :            : 
     310         [ #  # ]:          0 :     LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
     311                 :          0 :         aa_print_isid_status_port(lldp, hw);
     312                 :            :     }
     313                 :            : 
     314                 :          0 :     ds_put_format(ds, "%-8s %-4s %-11s %-8s\n",
     315                 :            :                       "I-SID",
     316                 :            :                       "VLAN",
     317                 :            :                       "Source",
     318                 :            :                       "Status");
     319                 :          0 :     ds_put_format(ds, "-------- ---- ----------- --------\n");
     320                 :            : 
     321 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (m, hmap_node_isid, &lldp->mappings_by_isid) {
     322                 :          0 :         ds_put_format(ds, "%-8"PRIu32" %-4"PRIu16" %-11s %-11s\n",
     323                 :          0 :                       m->isid, m->vlan, "Switch", aa_status_to_str(m->status));
     324                 :            :     }
     325                 :            : }
     326                 :            : 
     327                 :            : static void
     328                 :          0 : aa_unixctl_status(struct unixctl_conn *conn, int argc OVS_UNUSED,
     329                 :            :                   const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
     330                 :            :     OVS_EXCLUDED(mutex)
     331                 :            : {
     332                 :            :     struct lldp *lldp;
     333                 :          0 :     struct ds ds = DS_EMPTY_INITIALIZER;
     334                 :            : 
     335                 :          0 :     ovs_mutex_lock(&mutex);
     336                 :            : 
     337 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     338                 :          0 :         aa_print_element_status(&ds, lldp);
     339                 :            :     }
     340                 :          0 :     unixctl_command_reply(conn, ds_cstr(&ds));
     341                 :          0 :     ds_destroy(&ds);
     342                 :            : 
     343                 :          0 :     ovs_mutex_unlock(&mutex);
     344                 :          0 : }
     345                 :            : 
     346                 :            : static void
     347                 :          0 : aa_unixctl_show_isid(struct unixctl_conn *conn, int argc OVS_UNUSED,
     348                 :            :                      const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
     349                 :            :     OVS_EXCLUDED(mutex)
     350                 :            : {
     351                 :            :     struct lldp *lldp;
     352                 :          0 :     struct ds ds = DS_EMPTY_INITIALIZER;
     353                 :            : 
     354                 :          0 :     ovs_mutex_lock(&mutex);
     355                 :            : 
     356 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     357                 :          0 :         aa_print_isid_status(&ds, lldp);
     358                 :            :     }
     359                 :          0 :     unixctl_command_reply(conn, ds_cstr(&ds));
     360                 :          0 :     ds_destroy(&ds);
     361                 :            : 
     362                 :          0 :     ovs_mutex_unlock(&mutex);
     363                 :          0 : }
     364                 :            : 
     365                 :            : static void
     366                 :          0 : aa_unixctl_statistics(struct unixctl_conn *conn, int argc OVS_UNUSED,
     367                 :            :                       const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
     368                 :            :     OVS_EXCLUDED(mutex)
     369                 :            : {
     370                 :          0 :     struct ds ds = DS_EMPTY_INITIALIZER;
     371                 :            :     struct lldp *lldp;
     372                 :            : 
     373                 :          0 :     ovs_mutex_lock(&mutex);
     374                 :            : 
     375                 :            :     /* Cycle through all ports and dump the stats for each one */
     376 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     377                 :          0 :         aa_print_lldp_and_aa_stats(&ds, lldp);
     378                 :            :     }
     379                 :            : 
     380                 :          0 :     ovs_mutex_unlock(&mutex);
     381                 :            : 
     382                 :          0 :     unixctl_command_reply(conn, ds_cstr(&ds));
     383                 :          0 : }
     384                 :            : 
     385                 :            : /* An Auto Attach mapping was configured.  Populate the corresponding
     386                 :            :  * structures in the LLDP hardware.
     387                 :            :  */
     388                 :            : static void
     389                 :          0 : update_mapping_on_lldp(struct lldp *lldp, struct lldpd_hardware *hardware,
     390                 :            :                        struct aa_mapping_internal *m)
     391                 :            : {
     392                 :          0 :     struct lldpd_aa_isid_vlan_maps_tlv *lm = xzalloc(sizeof *lm);
     393                 :            : 
     394         [ #  # ]:          0 :     VLOG_INFO("\t\t hardware->h_ifname=%s", hardware->h_ifname);
     395                 :            : 
     396                 :          0 :     lm->isid_vlan_data.isid = m->isid;
     397                 :          0 :     lm->isid_vlan_data.vlan = m->vlan;
     398                 :            : 
     399                 :          0 :     ovs_list_push_back(&hardware->h_lport.p_isid_vlan_maps, &lm->m_entries);
     400                 :            : 
     401                 :            :     /* TODO Should be done in the Auto Attach state machine when a mapping goes
     402                 :            :      * from "pending" to "active".
     403                 :            :      */
     404                 :          0 :     struct bridge_aa_vlan *node = xmalloc(sizeof *node);
     405                 :            : 
     406                 :          0 :     node->port_name = xstrdup(hardware->h_ifname);
     407                 :          0 :     node->vlan = m->vlan;
     408                 :          0 :     node->oper = BRIDGE_AA_VLAN_OPER_ADD;
     409                 :            : 
     410                 :          0 :     ovs_list_push_back(&lldp->active_mapping_queue, &node->list_node);
     411                 :          0 : }
     412                 :            : 
     413                 :            : /* Bridge will poll the list of VLAN that needs to be auto configure based on
     414                 :            :  * the Auto Attach mappings that have been exchanged with the server.
     415                 :            :  */
     416                 :            : int
     417                 :          0 : aa_get_vlan_queued(struct ovs_list *list)
     418                 :            : {
     419                 :            :     struct lldp *lldp;
     420                 :            : 
     421                 :          0 :     ovs_mutex_lock(&mutex);
     422                 :            : 
     423 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     424                 :            :         struct bridge_aa_vlan *node;
     425                 :            : 
     426         [ #  # ]:          0 :         LIST_FOR_EACH_POP (node, list_node, &lldp->active_mapping_queue) {
     427                 :            :             struct bridge_aa_vlan *copy;
     428                 :            : 
     429                 :          0 :             copy = xmalloc(sizeof *copy);
     430                 :          0 :             copy->port_name = xstrdup(node->port_name);
     431                 :          0 :             copy->vlan = node->vlan;
     432                 :          0 :             copy->oper = node->oper;
     433                 :            : 
     434                 :          0 :             ovs_list_push_back(list, &copy->list_node);
     435                 :            : 
     436                 :            :             /* Cleanup */
     437                 :          0 :             free(node->port_name);
     438                 :          0 :             free(node);
     439                 :            :         }
     440                 :            :     }
     441                 :            : 
     442                 :          0 :     ovs_mutex_unlock(&mutex);
     443                 :            : 
     444                 :          0 :     return 0;
     445                 :            : }
     446                 :            : 
     447                 :            : /* Bridge will poll whether or not VLAN have been auto-configured.
     448                 :            :  */
     449                 :            : unsigned int
     450                 :       5132 : aa_get_vlan_queue_size(void)
     451                 :            : {
     452                 :            :     struct lldp *lldp;
     453                 :       5132 :     unsigned int size = 0;
     454                 :            : 
     455                 :       5132 :     ovs_mutex_lock(&mutex);
     456                 :            : 
     457 [ -  + ][ -  + ]:       5132 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     458                 :          0 :         size += ovs_list_size(&lldp->active_mapping_queue);
     459                 :            :     }
     460                 :            : 
     461                 :       5132 :     ovs_mutex_unlock(&mutex);
     462                 :            : 
     463                 :       5132 :     return size;
     464                 :            : }
     465                 :            : 
     466                 :            : /* Configure Auto Attach.
     467                 :            :  */
     468                 :            : int
     469                 :       4700 : aa_configure(const struct aa_settings *s)
     470                 :            : {
     471                 :            :     struct lldp *lldp;
     472                 :            : 
     473                 :       4700 :     ovs_mutex_lock(&mutex);
     474                 :            : 
     475                 :            :     /* TODO Change all instances for now */
     476 [ -  + ][ -  + ]:       4700 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     477                 :            :         struct lldpd_chassis *chassis;
     478                 :            : 
     479         [ #  # ]:          0 :         LIST_FOR_EACH (chassis, list, &lldp->lldpd->g_chassis) {
     480                 :            :             /* System Description */
     481                 :          0 :             free(chassis->c_descr);
     482         [ #  # ]:          0 :             chassis->c_descr = s && s->system_description[0] ?
     483         [ #  # ]:          0 :                 xstrdup(s->system_description) : xstrdup(PACKAGE_STRING);
     484                 :            : 
     485                 :            :             /* System Name */
     486         [ #  # ]:          0 :             if (s) {
     487                 :          0 :                 free(chassis->c_name);
     488                 :          0 :                 chassis->c_name = xstrdup(s->system_name);
     489                 :            :             }
     490                 :            :         }
     491                 :            :     }
     492                 :            : 
     493                 :       4700 :     ovs_mutex_unlock(&mutex);
     494                 :            : 
     495                 :       4700 :     return 0;
     496                 :            : }
     497                 :            : 
     498                 :            : /* Add a new Auto Attach mapping.
     499                 :            :  */
     500                 :            : int
     501                 :          0 : aa_mapping_register(void *aux, const struct aa_mapping_settings *s)
     502                 :            : {
     503                 :            :     struct aa_mapping_internal *bridge_m;
     504                 :            :     struct lldp *lldp;
     505                 :            : 
     506         [ #  # ]:          0 :     VLOG_INFO("Adding mapping ISID=%"PRIu32", VLAN=%"PRIu16", aux=%p",
     507                 :            :               s->isid, s->vlan, aux);
     508                 :            : 
     509                 :          0 :     ovs_mutex_lock(&mutex);
     510                 :            : 
     511                 :            :     /* TODO These mappings should be stores per bridge.  This is used
     512                 :            :      * When a port is added.  Auto Attach mappings need to be added on this
     513                 :            :      * port.
     514                 :            :      */
     515                 :          0 :     bridge_m = xzalloc(sizeof *bridge_m);
     516                 :          0 :     bridge_m->isid = s->isid;
     517                 :          0 :     bridge_m->vlan = s->vlan;
     518                 :          0 :     bridge_m->aux = aux;
     519                 :          0 :     bridge_m->status = AA_STATUS_PENDING;
     520                 :          0 :     hmap_insert(all_mappings, &bridge_m->hmap_node_isid,
     521                 :            :                 hash_int(bridge_m->isid, 0));
     522                 :            : 
     523                 :            : 
     524                 :            :     /* Update mapping on the all the LLDP instances. */
     525 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     526                 :            :         struct lldpd_hardware *hw;
     527                 :            :         struct aa_mapping_internal *m;
     528                 :            : 
     529         [ #  # ]:          0 :         VLOG_INFO("\t lldp->name=%s", lldp->name);
     530                 :            : 
     531         [ #  # ]:          0 :         if (mapping_find_by_isid(lldp, s->isid)) {
     532                 :          0 :             continue;
     533                 :            :         }
     534                 :            : 
     535                 :          0 :         m = xzalloc(sizeof *m);
     536                 :          0 :         m->isid = s->isid;
     537                 :          0 :         m->vlan = s->vlan;
     538                 :          0 :         m->status = AA_STATUS_PENDING;
     539                 :          0 :         m->aux = aux;
     540                 :          0 :         hmap_insert(&lldp->mappings_by_isid, &m->hmap_node_isid,
     541                 :            :                     hash_int(m->isid, 0));
     542                 :          0 :         hmap_insert(&lldp->mappings_by_aux,
     543                 :            :                     &m->hmap_node_aux,
     544                 :            :                     hash_pointer(m->aux, 0));
     545                 :            : 
     546                 :            :         /* Configure the mapping on each port of the LLDP stack. */
     547         [ #  # ]:          0 :         LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
     548                 :          0 :             update_mapping_on_lldp(lldp, hw, m);
     549                 :            :         }
     550                 :            :     }
     551                 :            : 
     552                 :          0 :     ovs_mutex_unlock(&mutex);
     553                 :            : 
     554                 :          0 :     return 0;
     555                 :            : }
     556                 :            : 
     557                 :            : static void
     558                 :          0 : aa_mapping_unregister_mapping(struct lldp *lldp,
     559                 :            :                               struct lldpd_hardware *hw,
     560                 :            :                               struct aa_mapping_internal *m)
     561                 :            : {
     562                 :            :     struct lldpd_aa_isid_vlan_maps_tlv *lm, *lm_next;
     563                 :            : 
     564 [ #  # ][ #  # ]:          0 :     LIST_FOR_EACH_SAFE (lm, lm_next, m_entries,
     565                 :            :                         &hw->h_lport.p_isid_vlan_maps) {
     566                 :          0 :         uint32_t isid = lm->isid_vlan_data.isid;
     567                 :            : 
     568         [ #  # ]:          0 :         if (isid == m->isid) {
     569         [ #  # ]:          0 :             VLOG_INFO("\t\t Removing lport, isid=%u, vlan=%u",
     570                 :            :                       isid,
     571                 :            :                       lm->isid_vlan_data.vlan);
     572                 :            : 
     573                 :          0 :             ovs_list_remove(&lm->m_entries);
     574                 :            : 
     575                 :            :             /* TODO Should be done in the AA SM when a mapping goes
     576                 :            :              * from "pending" to "active".
     577                 :            :              */
     578                 :          0 :             struct bridge_aa_vlan *node = xmalloc(sizeof *node);
     579                 :            : 
     580                 :          0 :             node->port_name = xstrdup(hw->h_ifname);
     581                 :          0 :             node->vlan = m->vlan;
     582                 :          0 :             node->oper = BRIDGE_AA_VLAN_OPER_REMOVE;
     583                 :            : 
     584                 :          0 :             ovs_list_push_back(&lldp->active_mapping_queue, &node->list_node);
     585                 :            : 
     586                 :          0 :             break;
     587                 :            :         }
     588                 :            :     }
     589                 :          0 : }
     590                 :            : 
     591                 :            : /* Remove an existing Auto Attach mapping.
     592                 :            :  */
     593                 :            : int
     594                 :          0 : aa_mapping_unregister(void *aux)
     595                 :            : {
     596                 :            :     struct lldp *lldp;
     597                 :            : 
     598         [ #  # ]:          0 :     VLOG_INFO("Removing mapping aux=%p", aux);
     599                 :            : 
     600                 :          0 :     ovs_mutex_lock(&mutex);
     601                 :            : 
     602 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
     603                 :            :         struct lldpd_hardware *hw;
     604                 :          0 :         struct aa_mapping_internal *m = mapping_find_by_aux(lldp, aux);
     605                 :            : 
     606                 :            :         /* Remove from internal hash tables. */
     607         [ #  # ]:          0 :         if (m) {
     608                 :          0 :             uint32_t isid = m->isid;
     609                 :          0 :             uint16_t vlan = m->vlan;
     610                 :          0 :             struct aa_mapping_internal *p = mapping_find_by_isid(lldp, isid);
     611                 :            : 
     612         [ #  # ]:          0 :             VLOG_INFO("\t Removing mapping ISID=%"PRIu32", VLAN=%"PRIu16
     613                 :            :                       " (lldp->name=%s)", isid, vlan, lldp->name);
     614                 :            : 
     615         [ #  # ]:          0 :             if (p) {
     616                 :          0 :                 hmap_remove(&lldp->mappings_by_isid, &p->hmap_node_isid);
     617                 :            :             }
     618                 :            : 
     619                 :          0 :             hmap_remove(&lldp->mappings_by_aux, &m->hmap_node_aux);
     620                 :            : 
     621                 :            :             /* Remove from all the lldp instances */
     622         [ #  # ]:          0 :             LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
     623         [ #  # ]:          0 :                 VLOG_INFO("\t\t hardware->h_ifname=%s", hw->h_ifname);
     624                 :          0 :                 aa_mapping_unregister_mapping(lldp, hw, m);
     625                 :            :             }
     626                 :          0 :             free(m);
     627                 :            : 
     628                 :            :             /* Remove from the all_mappings */
     629 [ #  # ][ #  # ]:          0 :             HMAP_FOR_EACH (m, hmap_node_isid, all_mappings) {
     630 [ #  # ][ #  # ]:          0 :                 if (m && isid == m->isid && vlan == m->vlan) {
                 [ #  # ]
     631                 :          0 :                     hmap_remove(all_mappings, &m->hmap_node_isid);
     632                 :          0 :                     break;
     633                 :            :                 }
     634                 :            :             }
     635                 :            :         }
     636                 :            :     }
     637                 :            : 
     638                 :          0 :     ovs_mutex_unlock(&mutex);
     639                 :            : 
     640                 :          0 :     return 0;
     641                 :            : }
     642                 :            : 
     643                 :            : void
     644                 :        617 : lldp_init(void)
     645                 :            : {
     646                 :        617 :     unixctl_command_register("autoattach/status", "[bridge]", 0, 1,
     647                 :            :                              aa_unixctl_status, NULL);
     648                 :        617 :     unixctl_command_register("autoattach/show-isid", "[bridge]", 0, 1,
     649                 :            :                              aa_unixctl_show_isid, NULL);
     650                 :        617 :     unixctl_command_register("autoattach/statistics", "[bridge]", 0, 1,
     651                 :            :                              aa_unixctl_statistics, NULL);
     652                 :        617 : }
     653                 :            : 
     654                 :            : /* Returns true if 'lldp' should process packets from 'flow'.  Sets
     655                 :            :  * fields in 'wc' that were used to make the determination.
     656                 :            :  */
     657                 :            : bool
     658                 :          0 : lldp_should_process_flow(struct lldp *lldp, const struct flow *flow)
     659                 :            : {
     660 [ #  # ][ #  # ]:          0 :     return (flow->dl_type == htons(ETH_TYPE_LLDP) && lldp->enabled);
     661                 :            : }
     662                 :            : 
     663                 :            : 
     664                 :            : /* Process an LLDP packet that was received on a bridge port.
     665                 :            :  */
     666                 :            : void
     667                 :          0 : lldp_process_packet(struct lldp *lldp, const struct dp_packet *p)
     668                 :            : {
     669         [ #  # ]:          0 :     if (lldp) {
     670                 :          0 :         lldpd_recv(lldp->lldpd, lldpd_first_hardware(lldp->lldpd),
     671                 :          0 :                    (char *) dp_packet_data(p), dp_packet_size(p));
     672                 :            :     }
     673                 :          0 : }
     674                 :            : 
     675                 :            : /* This code is called periodically to check if the LLDP module has an LLDP
     676                 :            :  * message it wishes to send.  It is called several times every second.
     677                 :            :  */
     678                 :            : bool
     679                 :          0 : lldp_should_send_packet(struct lldp *cfg) OVS_EXCLUDED(mutex)
     680                 :            : {
     681                 :            :     bool ret;
     682                 :            : 
     683                 :          0 :     ovs_mutex_lock(&mutex);
     684                 :          0 :     ret = timer_expired(&cfg->tx_timer);
     685                 :          0 :     ovs_mutex_unlock(&mutex);
     686                 :            : 
     687                 :            :     /* LLDP must be enabled */
     688                 :          0 :     ret &= cfg->enabled;
     689                 :            : 
     690                 :          0 :     return ret;
     691                 :            : }
     692                 :            : 
     693                 :            : /* Returns the next wake up time.
     694                 :            :  */
     695                 :            : long long int
     696                 :          0 : lldp_wake_time(const struct lldp *lldp) OVS_EXCLUDED(mutex)
     697                 :            : {
     698                 :            :     long long int retval;
     699                 :            : 
     700 [ #  # ][ #  # ]:          0 :     if (!lldp || !lldp->enabled) {
     701                 :          0 :         return LLONG_MAX;
     702                 :            :     }
     703                 :            : 
     704                 :          0 :     ovs_mutex_lock(&mutex);
     705                 :          0 :     retval = lldp->tx_timer.t;
     706                 :          0 :     ovs_mutex_unlock(&mutex);
     707                 :            : 
     708                 :          0 :     return retval;
     709                 :            : }
     710                 :            : 
     711                 :            : /* Put the monitor thread to sleep until it's next wake time.
     712                 :            :  */
     713                 :            : long long int
     714                 :          0 : lldp_wait(struct lldp *lldp) OVS_EXCLUDED(mutex)
     715                 :            : {
     716                 :          0 :     long long int wake_time = lldp_wake_time(lldp);
     717                 :          0 :     poll_timer_wait_until(wake_time);
     718                 :          0 :     return wake_time;
     719                 :            : }
     720                 :            : 
     721                 :            : /* Prepare the LLDP packet to be sent on a bridge port.
     722                 :            :  */
     723                 :            : void
     724                 :          0 : lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
     725                 :            :                 const struct eth_addr eth_src) OVS_EXCLUDED(mutex)
     726                 :            : {
     727                 :          0 :     struct lldpd *mylldpd = lldp->lldpd;
     728                 :          0 :     struct lldpd_hardware *hw = lldpd_first_hardware(mylldpd);
     729                 :            :     static const struct eth_addr eth_addr_lldp =
     730                 :            :         { { { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0e } } };
     731                 :            : 
     732                 :          0 :     ovs_mutex_lock(&mutex);
     733                 :            : 
     734                 :          0 :     eth_compose(packet, eth_addr_lldp, eth_src, ETH_TYPE_LLDP, 0);
     735                 :            : 
     736                 :          0 :     lldpd_send(hw, packet);
     737                 :            : 
     738                 :          0 :     timer_set_duration(&lldp->tx_timer, lldp->lldpd->g_config.c_tx_interval);
     739                 :          0 :     ovs_mutex_unlock(&mutex);
     740                 :          0 : }
     741                 :            : 
     742                 :            : /* Configures the LLDP stack.
     743                 :            :  */
     744                 :            : bool
     745                 :      31837 : lldp_configure(struct lldp *lldp, const struct smap *cfg) OVS_EXCLUDED(mutex)
     746                 :            : {
     747         [ -  + ]:      31837 :     if (lldp) {
     748 [ #  # ][ #  # ]:          0 :         if (cfg && smap_get_bool(cfg, "enable", false)) {
     749                 :          0 :             lldp->enabled = true;
     750                 :            :         } else {
     751                 :          0 :             lldp->enabled = false;
     752                 :            :         }
     753                 :            : 
     754                 :          0 :         ovs_mutex_lock(&mutex);
     755                 :          0 :         timer_set_expired(&lldp->tx_timer);
     756                 :          0 :         timer_set_duration(&lldp->tx_timer, LLDP_DEFAULT_TRANSMIT_INTERVAL_MS);
     757                 :          0 :         lldp->lldpd->g_config.c_tx_interval =
     758                 :            :             LLDP_DEFAULT_TRANSMIT_INTERVAL_MS;
     759                 :          0 :         ovs_mutex_unlock(&mutex);
     760                 :            :     }
     761                 :            : 
     762                 :      31837 :     return true;
     763                 :            : }
     764                 :            : 
     765                 :            : /* Create an LLDP stack instance.  At the moment there is one per bridge port.
     766                 :            :  */
     767                 :            : struct lldp *
     768                 :      31837 : lldp_create(const struct netdev *netdev,
     769                 :            :             const uint32_t mtu,
     770                 :            :             const struct smap *cfg) OVS_EXCLUDED(mutex)
     771                 :            : {
     772                 :            :     struct lldp *lldp;
     773                 :            :     struct lldpd_chassis *lchassis;
     774                 :            :     struct lldpd_hardware *hw;
     775                 :            :     struct aa_mapping_internal *m;
     776                 :            : 
     777 [ +  - ][ +  - ]:      31837 :     if (!cfg || !smap_get_bool(cfg, "enable", false)) {
     778                 :      31837 :         return NULL;
     779                 :            :     }
     780                 :            : 
     781                 :          0 :     lldp = xzalloc(sizeof *lldp);
     782                 :          0 :     lldp->name = xstrdup(netdev_get_name(netdev));
     783                 :          0 :     lldp->lldpd = xzalloc(sizeof *lldp->lldpd);
     784                 :            : 
     785                 :          0 :     hmap_init(&lldp->mappings_by_isid);
     786                 :          0 :     hmap_init(&lldp->mappings_by_aux);
     787                 :          0 :     ovs_list_init(&lldp->active_mapping_queue);
     788                 :            : 
     789                 :          0 :     lchassis = xzalloc(sizeof *lchassis);
     790                 :          0 :     lchassis->c_cap_available = LLDP_CAP_BRIDGE;
     791                 :          0 :     lchassis->c_cap_enabled = LLDP_CAP_BRIDGE;
     792                 :          0 :     lchassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
     793                 :          0 :     lchassis->c_id_len = ETH_ADDR_LEN;
     794                 :            : 
     795                 :          0 :     struct eth_addr *mac = xmalloc(ETH_ADDR_LEN);
     796                 :          0 :     netdev_get_etheraddr(netdev, mac);
     797                 :          0 :     lchassis->c_id = &mac->ea[0];
     798                 :            : 
     799                 :          0 :     ovs_list_init(&lchassis->c_mgmt);
     800                 :          0 :     lchassis->c_ttl = lldp->lldpd->g_config.c_tx_interval *
     801                 :          0 :                       lldp->lldpd->g_config.c_tx_hold;
     802                 :          0 :     lchassis->c_ttl = LLDP_CHASSIS_TTL;
     803                 :          0 :     lldpd_assign_cfg_to_protocols(lldp->lldpd);
     804                 :          0 :     ovs_list_init(&lldp->lldpd->g_chassis);
     805                 :          0 :     ovs_list_push_back(&lldp->lldpd->g_chassis, &lchassis->list);
     806                 :            : 
     807         [ #  # ]:          0 :     if ((hw = lldpd_alloc_hardware(lldp->lldpd,
     808                 :          0 :                                    (char *) netdev_get_name(netdev),
     809                 :            :                                    0)) == NULL) {
     810         [ #  # ]:          0 :         VLOG_WARN("Unable to allocate space for %s",
     811                 :            :                   (char *) netdev_get_name(netdev));
     812                 :          0 :         out_of_memory();
     813                 :            :     }
     814                 :            : 
     815                 :          0 :     ovs_refcount_init(&lldp->ref_cnt);
     816                 :            : #ifndef _WIN32
     817                 :          0 :     hw->h_flags |= IFF_RUNNING;
     818                 :            : #endif
     819                 :          0 :     hw->h_mtu = mtu;
     820                 :          0 :     hw->h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
     821                 :          0 :     hw->h_lport.p_id = xstrdup(netdev_get_name(netdev));
     822                 :            : 
     823                 :            :     /* p_id is not necessarily a null terminated string. */
     824                 :          0 :     hw->h_lport.p_id_len = strlen(netdev_get_name(netdev));
     825                 :            : 
     826                 :            :     /* Auto Attach element tlv */
     827                 :          0 :     hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH;
     828                 :          0 :     hw->h_lport.p_element.mgmt_vlan = 0;
     829                 :          0 :     memcpy(&hw->h_lport.p_element.system_id.system_mac,
     830                 :          0 :            lchassis->c_id, lchassis->c_id_len);
     831                 :          0 :     hw->h_lport.p_element.system_id.conn_type =
     832                 :            :         LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE;
     833                 :          0 :     hw->h_lport.p_element.system_id.rsvd = 0;
     834                 :          0 :     hw->h_lport.p_element.system_id.rsvd2[0] = 0;
     835                 :          0 :     hw->h_lport.p_element.system_id.rsvd2[1] = 0;
     836                 :            : 
     837                 :          0 :     ovs_list_init(&hw->h_lport.p_isid_vlan_maps);
     838                 :          0 :     ovs_list_init(&lldp->lldpd->g_hardware);
     839                 :          0 :     ovs_list_push_back(&lldp->lldpd->g_hardware, &hw->h_entries);
     840                 :            : 
     841                 :          0 :     ovs_mutex_lock(&mutex);
     842                 :            : 
     843                 :            :     /* Update port with Auto Attach mappings configured. */
     844 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (m, hmap_node_isid, all_mappings) {
     845                 :            :         struct aa_mapping_internal *p;
     846                 :            : 
     847         [ #  # ]:          0 :         if (mapping_find_by_isid(lldp, m->isid)) {
     848                 :          0 :             continue;
     849                 :            :         }
     850                 :            : 
     851                 :          0 :         p = xmemdup(m, sizeof *p);
     852                 :          0 :         hmap_insert(&lldp->mappings_by_isid, &p->hmap_node_isid,
     853                 :            :                     hash_int(p->isid, 0));
     854                 :          0 :         hmap_insert(&lldp->mappings_by_aux,
     855                 :            :                     &p->hmap_node_aux,
     856                 :            :                     hash_pointer(p->aux, 0));
     857                 :            : 
     858                 :          0 :         update_mapping_on_lldp(lldp, hw, p);
     859                 :            :     }
     860                 :            : 
     861                 :          0 :     hmap_insert(all_lldps, &lldp->hmap_node,
     862                 :            :                 hash_string(netdev_get_name(netdev), 0));
     863                 :            : 
     864                 :          0 :     ovs_mutex_unlock(&mutex);
     865                 :            : 
     866                 :          0 :     return lldp;
     867                 :            : }
     868                 :            : 
     869                 :            : 
     870                 :            : struct lldp *
     871                 :          1 : lldp_create_dummy(void)
     872                 :            : {
     873                 :            :     struct lldp *lldp;
     874                 :            :     struct lldpd_chassis *lchassis;
     875                 :            :     struct lldpd_hardware *hw;
     876                 :            : 
     877                 :          1 :     lldp = xzalloc(sizeof *lldp);
     878                 :          1 :     lldp->name = "dummy-lldp";
     879                 :          1 :     lldp->lldpd = xzalloc(sizeof *lldp->lldpd);
     880                 :            : 
     881                 :          1 :     hmap_init(&lldp->mappings_by_isid);
     882                 :          1 :     hmap_init(&lldp->mappings_by_aux);
     883                 :          1 :     ovs_list_init(&lldp->active_mapping_queue);
     884                 :            : 
     885                 :          1 :     lchassis = xzalloc(sizeof *lchassis);
     886                 :          1 :     lchassis->c_cap_available = LLDP_CAP_BRIDGE;
     887                 :          1 :     lchassis->c_cap_enabled = LLDP_CAP_BRIDGE;
     888                 :          1 :     lchassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
     889                 :          1 :     lchassis->c_id_len = ETH_ADDR_LEN;
     890                 :            : 
     891                 :          1 :     ovs_list_init(&lchassis->c_mgmt);
     892                 :          1 :     lchassis->c_ttl = LLDP_CHASSIS_TTL;
     893                 :          1 :     lldpd_assign_cfg_to_protocols(lldp->lldpd);
     894                 :          1 :     ovs_list_init(&lldp->lldpd->g_chassis);
     895                 :          1 :     ovs_list_push_back(&lldp->lldpd->g_chassis, &lchassis->list);
     896                 :            : 
     897                 :          1 :     hw = lldpd_alloc_hardware(lldp->lldpd, "dummy-hw", 0);
     898                 :            : 
     899                 :          1 :     ovs_refcount_init(&lldp->ref_cnt);
     900                 :            : #ifndef _WIN32
     901                 :          1 :     hw->h_flags |= IFF_RUNNING;
     902                 :            : #endif
     903                 :          1 :     hw->h_mtu = 1500;
     904                 :          1 :     hw->h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
     905                 :          1 :     hw->h_lport.p_id = "dummy-port";
     906                 :            : 
     907                 :            :     /* p_id is not necessarily a null terminated string. */
     908                 :          1 :     hw->h_lport.p_id_len = strlen(hw->h_lport.p_id);
     909                 :            : 
     910                 :            :     /* Auto Attach element tlv */
     911                 :          1 :     hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH;
     912                 :          1 :     hw->h_lport.p_element.mgmt_vlan = 0;
     913                 :          1 :     hw->h_lport.p_element.system_id.conn_type =
     914                 :            :         LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE;
     915                 :          1 :     hw->h_lport.p_element.system_id.rsvd = 0;
     916                 :          1 :     hw->h_lport.p_element.system_id.rsvd2[0] = 0;
     917                 :          1 :     hw->h_lport.p_element.system_id.rsvd2[1] = 0;
     918                 :            : 
     919                 :          1 :     ovs_list_init(&hw->h_lport.p_isid_vlan_maps);
     920                 :          1 :     ovs_list_init(&lldp->lldpd->g_hardware);
     921                 :          1 :     ovs_list_push_back(&lldp->lldpd->g_hardware, &hw->h_entries);
     922                 :            : 
     923                 :          1 :     return lldp;
     924                 :            : }
     925                 :            : 
     926                 :            : /* Unreference a specific LLDP instance.
     927                 :            :  */
     928                 :            : void
     929                 :     246497 : lldp_unref(struct lldp *lldp)
     930                 :            : {
     931         [ +  - ]:     246497 :     if (!lldp) {
     932                 :     246497 :         return;
     933                 :            :     }
     934                 :            : 
     935                 :          0 :     ovs_mutex_lock(&mutex);
     936         [ #  # ]:          0 :     if (ovs_refcount_unref_relaxed(&lldp->ref_cnt) != 1) {
     937                 :          0 :         ovs_mutex_unlock(&mutex);
     938                 :          0 :         return;
     939                 :            :     }
     940                 :            : 
     941                 :          0 :     hmap_remove(all_lldps, &lldp->hmap_node);
     942                 :          0 :     ovs_mutex_unlock(&mutex);
     943                 :            : 
     944                 :          0 :     lldpd_cleanup(lldp->lldpd);
     945                 :          0 :     free(lldp->lldpd);
     946                 :          0 :     free(lldp->name);
     947                 :          0 :     free(lldp);
     948                 :            : }
     949                 :            : 
     950                 :            : /* Reference a specific LLDP instance.
     951                 :            :  */
     952                 :            : struct lldp *
     953                 :          0 : lldp_ref(const struct lldp *lldp_)
     954                 :            : {
     955                 :          0 :     struct lldp *lldp = CONST_CAST(struct lldp *, lldp_);
     956         [ #  # ]:          0 :     if (lldp) {
     957                 :          0 :         ovs_refcount_ref(&lldp->ref_cnt);
     958                 :            :     }
     959                 :          0 :     return lldp;
     960                 :            : }
     961                 :            : 
     962                 :            : void
     963                 :          1 : lldp_destroy_dummy(struct lldp *lldp)
     964                 :            : {
     965                 :            :     struct lldpd_hardware *hw, *hw_next;
     966                 :            :     struct lldpd_chassis *chassis, *chassis_next;
     967                 :            :     struct lldpd *cfg;
     968                 :            : 
     969         [ -  + ]:          1 :     if (!lldp) {
     970                 :          0 :         return;
     971                 :            :     }
     972                 :            : 
     973                 :          1 :     cfg = lldp->lldpd;
     974                 :            : 
     975 [ +  + ][ +  + ]:          2 :     LIST_FOR_EACH_SAFE (hw, hw_next, h_entries, &cfg->g_hardware) {
     976                 :          1 :         ovs_list_remove(&hw->h_entries);
     977                 :          1 :         free(hw->h_lport.p_lastframe);
     978                 :          1 :         free(hw);
     979                 :            :     }
     980                 :            : 
     981 [ +  + ][ +  + ]:          2 :     LIST_FOR_EACH_SAFE (chassis, chassis_next, list, &cfg->g_chassis) {
     982                 :          1 :         ovs_list_remove(&chassis->list);
     983                 :          1 :         free(chassis);
     984                 :            :     }
     985                 :            : 
     986                 :          1 :     free(lldp->lldpd);
     987                 :          1 :     free(lldp);
     988                 :            : }
     989                 :            : 

Generated by: LCOV version 1.12