LCOV - code coverage report
Current view: top level - vnsw/agent/port_ipc - port_subscribe_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 175 481 36.4 %
Date: 2026-11-09 02:10:49 Functions: 27 72 37.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : #include <string>
       6             : #include <sandesh/sandesh_trace.h>
       7             : #include <port_ipc/port_ipc_types.h>
       8             : #include <cmn/agent_cmn.h>
       9             : #include <init/agent_param.h>
      10             : #include <oper/interface_common.h>
      11             : #include <controller/controller_init.h>
      12             : #include "port_subscribe_table.h"
      13             : #include "port_ipc_handler.h"
      14             : 
      15             : using namespace autogen;
      16             : using boost::uuids::nil_uuid;
      17             : 
      18             : /////////////////////////////////////////////////////////////////////////////
      19             : // Init/Shutdown routines
      20             : /////////////////////////////////////////////////////////////////////////////
      21           2 : void PortSubscribeTable::InitDone() {
      22             :     // Register with config DB table for vm-port UUID to IFNode mapping
      23           2 :     vmi_config_table_ = (static_cast<IFMapAgentTable *>
      24           2 :                          (IFMapTable::FindTable(agent_->db(),
      25             :                                                 "virtual-machine-interface")));
      26           4 :     vmi_config_listener_id_ = vmi_config_table_->Register
      27           2 :         (boost::bind(&PortSubscribeTable::Notify, this, _1, _2));
      28           2 : }
      29             : 
      30           2 : void PortSubscribeTable::Shutdown() {
      31           2 :     DBTable::DBStateClear(vmi_config_table_, vmi_config_listener_id_);
      32           2 :     vmi_config_table_->Unregister(vmi_config_listener_id_);
      33           2 : }
      34             : 
      35             : /////////////////////////////////////////////////////////////////////////////
      36             : // PortSubscribeEntry routines
      37             : /////////////////////////////////////////////////////////////////////////////
      38         330 : PortSubscribeEntry::PortSubscribeEntry(Type type, const std::string &ifname,
      39         330 :                                        int32_t version) :
      40         330 :     type_(type), ifname_(ifname), version_(version) {
      41         330 : }
      42             : 
      43         330 : PortSubscribeEntry::~PortSubscribeEntry() {
      44         330 : }
      45             : 
      46             : // Only version number is modifiable
      47           0 : void PortSubscribeEntry::Update(const PortSubscribeEntry *rhs) {
      48           0 :     version_ = rhs->version_;
      49           0 : }
      50             : 
      51         330 : const char *PortSubscribeEntry::TypeToString(Type type) {
      52         330 :     switch (type) {
      53         330 :     case VMPORT:
      54         330 :         return "VM Port";
      55             :         break;
      56             : 
      57           0 :     case NAMESPACE:
      58           0 :         return "Namespace Port";
      59             :         break;
      60             : 
      61           0 :     case REMOTE_PORT:
      62           0 :         return "Remote Port";
      63             :         break;
      64             : 
      65           0 :     default:
      66           0 :         break;
      67             :     }
      68             : 
      69           0 :     return "Invalid";
      70             : }
      71             : 
      72             : /////////////////////////////////////////////////////////////////////////////
      73             : // VmiSubscribeEntry routines
      74             : /////////////////////////////////////////////////////////////////////////////
      75         330 : VmiSubscribeEntry::VmiSubscribeEntry(PortSubscribeEntry::Type type,
      76             :                                      const std::string &ifname,
      77             :                                      uint32_t version,
      78             :                                      const boost::uuids::uuid &vmi_uuid,
      79             :                                      const boost::uuids::uuid vm_uuid,
      80             :                                      const std::string &vm_name,
      81             :                                      const boost::uuids::uuid &vn_uuid,
      82             :                                      const boost::uuids::uuid &project_uuid,
      83             :                                      const Ip4Address &ip4_addr,
      84             :                                      const Ip6Address &ip6_addr,
      85             :                                      const std::string &mac_addr,
      86             :                                      uint16_t tx_vlan_id, uint16_t rx_vlan_id,
      87         330 :                                      uint8_t vhostuser_mode, uint8_t link_state) :
      88         330 :     PortSubscribeEntry(type, ifname, version), vmi_uuid_(vmi_uuid),
      89         660 :     vm_uuid_(vm_uuid), vm_name_(vm_name), vn_uuid_(vn_uuid),
      90         330 :     project_uuid_(project_uuid), ip4_addr_(ip4_addr), ip6_addr_(ip6_addr),
      91         330 :     mac_addr_(mac_addr), tx_vlan_id_(tx_vlan_id), rx_vlan_id_(rx_vlan_id),
      92         330 :     vhostuser_mode_(vhostuser_mode), link_state_(link_state) {
      93         330 : }
      94             : 
      95         495 : VmiSubscribeEntry::~VmiSubscribeEntry() {
      96         495 : }
      97             : 
      98           0 : void VmiSubscribeEntry::Update(const PortSubscribeEntry *rhs) {
      99           0 :     PortSubscribeEntry::Update(rhs);
     100           0 : }
     101             : 
     102         165 : void VmiSubscribeEntry::OnAdd(Agent *agent, PortSubscribeTable *table) const {
     103         165 :     uint16_t tx_vlan_id_p = VmInterface::kInvalidVlanId;
     104         165 :     uint16_t rx_vlan_id_p = VmInterface::kInvalidVlanId;
     105         165 :     string port = Agent::NullString();
     106         165 :     Interface::Transport transport = Interface::TRANSPORT_ETHERNET;
     107         165 :     if (agent->params()->isVmwareMode()) {
     108           0 :         tx_vlan_id_p = tx_vlan_id_;
     109           0 :         rx_vlan_id_p = rx_vlan_id_;
     110           0 :         if (tx_vlan_id_p != VmInterface::kInvalidVlanId ||
     111             :             rx_vlan_id_p != VmInterface::kInvalidVlanId) {
     112             :             // In case of netns instance transport mode and
     113             :             // parent interface shouldnt be set
     114           0 :             port = agent->params()->vmware_physical_port();
     115           0 :             transport = Interface::TRANSPORT_VIRTUAL;
     116             :         }
     117             :     }
     118             : 
     119         165 :     if ((agent->vrouter_on_nic_mode() == true ||
     120         165 :          agent->vrouter_on_host_dpdk() == true) &&
     121           0 :         type_ == PortSubscribeEntry::VMPORT) {
     122           0 :         transport = Interface::TRANSPORT_PMD;
     123             :     }
     124             : 
     125             :     // Add the interface
     126         165 :     VmInterface::NovaAdd(agent->interface_table(), vmi_uuid_, ifname_,
     127         165 :                          ip4_addr_, mac_addr_, vm_name_, project_uuid_,
     128         165 :                          tx_vlan_id_p, rx_vlan_id_p, port, ip6_addr_,
     129         165 :                          vhostuser_mode_, transport, link_state_);
     130             : 
     131             :     // Notify controller module about new port
     132         165 :     if (type_ == PortSubscribeEntry::NAMESPACE)
     133           0 :         return;
     134             : 
     135             :     VNController::ControllerWorkQueueDataType
     136         165 :         data(new ControllerVmiSubscribeData(false, vmi_uuid_, vm_uuid_));
     137         165 :     agent->controller()->Enqueue(data);
     138         165 : }
     139             : 
     140         165 : void VmiSubscribeEntry::OnDelete(Agent *agent, PortSubscribeTable *table)
     141             :     const {
     142         165 :     VmInterface::Delete(agent->interface_table(), vmi_uuid_,
     143             :                         VmInterface::INSTANCE_MSG);
     144         165 :     if (type_ == PortSubscribeEntry::NAMESPACE)
     145           0 :         return;
     146             : 
     147             :     VNController::ControllerWorkQueueDataType
     148         165 :         data(new ControllerVmiSubscribeData(true, vmi_uuid_, vm_uuid_));
     149         165 :     agent->controller()->Enqueue(data);
     150         165 : }
     151             : 
     152        1154 : bool VmiSubscribeEntry::MatchVn(const boost::uuids::uuid &u) const {
     153        1154 :     return vn_uuid_ == u;
     154             : }
     155             : 
     156        1154 : bool VmiSubscribeEntry::MatchVm(const boost::uuids::uuid &u) const {
     157        1154 :     return vm_uuid_ == u;
     158             : }
     159             : 
     160             : /////////////////////////////////////////////////////////////////////////////
     161             : // VmVnPortSubscribeEntry routines
     162             : /////////////////////////////////////////////////////////////////////////////
     163           0 : VmVnPortSubscribeEntry::VmVnPortSubscribeEntry
     164             : (PortSubscribeEntry::Type type, const std::string &ifname, uint32_t version,
     165             :  const boost::uuids::uuid &vm_uuid, const boost::uuids::uuid &vn_uuid,
     166             :  const boost::uuids::uuid &vmi_uuid, const std::string &vm_name,
     167             :  const std::string &vm_identifier, const std::string &vm_ifname,
     168           0 :  const std::string &vm_namespace) :
     169           0 :     PortSubscribeEntry(type, ifname, version), vm_uuid_(vm_uuid),
     170           0 :     vn_uuid_(vn_uuid), vm_name_(vm_name), vm_identifier_(vm_identifier),
     171           0 :     vm_ifname_(vm_ifname), vm_namespace_(vm_namespace), vmi_uuid_(vmi_uuid) {
     172           0 : }
     173             : 
     174           0 : VmVnPortSubscribeEntry::~VmVnPortSubscribeEntry() {
     175           0 : }
     176             : 
     177           0 : void VmVnPortSubscribeEntry::Update(const PortSubscribeEntry *rhs) {
     178           0 :     PortSubscribeEntry::Update(rhs);
     179           0 : }
     180             : 
     181           0 : void VmVnPortSubscribeEntry::OnAdd(Agent *agent, PortSubscribeTable *table)
     182             :     const {
     183           0 :     VmInterface::SetIfNameReq(agent->interface_table(), vmi_uuid_, ifname_);
     184             : 
     185           0 : }
     186             : 
     187           0 : void VmVnPortSubscribeEntry::OnDelete(Agent *agent, PortSubscribeTable *table)
     188             :     const {
     189           0 :     VmInterface::DeleteIfNameReq(agent->interface_table(), vmi_uuid_);
     190           0 : }
     191             : 
     192           0 : bool VmVnPortSubscribeEntry::MatchVn(const boost::uuids::uuid &u) const {
     193           0 :     if (vn_uuid_ == nil_uuid())
     194           0 :         return true;
     195             : 
     196           0 :     return vn_uuid_ == u;
     197             : }
     198             : 
     199           0 : bool VmVnPortSubscribeEntry::MatchVm(const boost::uuids::uuid &u) const {
     200           0 :     return vm_uuid_ == u;
     201             : }
     202             : 
     203             : /////////////////////////////////////////////////////////////////////////////
     204             : // PortSubscribeTable routines
     205             : /////////////////////////////////////////////////////////////////////////////
     206           2 : PortSubscribeTable::PortSubscribeTable(Agent *agent) :
     207           4 :     agent_(agent), interface_table_(agent->interface_table()),
     208           2 :     controller_(agent->controller()),
     209           4 :     vmi_config_table_(NULL), vmi_config_listener_id_(DBTableBase::kInvalidId) {
     210           2 : }
     211             : 
     212           4 : PortSubscribeTable::~PortSubscribeTable() {
     213           2 :     assert(vmi_tree_.size() == 0);
     214           4 : }
     215             : 
     216         165 : void PortSubscribeTable::AddVmi(const boost::uuids::uuid &u,
     217             :                              PortSubscribeEntryPtr entry) {
     218         165 :     std::scoped_lock lock(mutex_);
     219             :     std::pair<VmiTree::iterator, bool> ret =
     220         165 :         vmi_tree_.insert(std::make_pair(u, entry));
     221         165 :     if (ret.second == false) {
     222             :         // Could be a port add for an exisiting VMI with a different VM.
     223             :         // If so need to handle as a del and add.
     224             :         VmiSubscribeEntry *new_entry =
     225           0 :         dynamic_cast<VmiSubscribeEntry *>(entry.get());
     226             :         VmiSubscribeEntry *old_entry =
     227           0 :             dynamic_cast<VmiSubscribeEntry *>(ret.first->second.get());
     228           0 :         if (old_entry->vm_uuid() != new_entry->vm_uuid()) {
     229           0 :             ret.first->second->OnDelete(agent_, this);
     230           0 :             vmi_tree_.erase(ret.first);
     231           0 :             ret = vmi_tree_.insert(std::make_pair(u, entry));
     232             :         } else {
     233           0 :             ret.first->second->Update(entry.get());
     234             :         }
     235             :     }
     236             : 
     237         165 :     ret.first->second->OnAdd(agent_, this);
     238         165 : }
     239             : 
     240         186 : void PortSubscribeTable::DeleteVmi(const boost::uuids::uuid &u) {
     241         186 :     std::scoped_lock lock(mutex_);
     242         186 :     VmiTree::iterator it = vmi_tree_.find(u);
     243         186 :     if (it == vmi_tree_.end())
     244          21 :         return;
     245             : 
     246         165 :     it->second->OnDelete(agent_, this);
     247         165 :     vmi_tree_.erase(it);
     248         186 : }
     249             : 
     250         186 : PortSubscribeEntryPtr PortSubscribeTable::GetVmi(const boost::uuids::uuid &u)
     251             :     const {
     252         186 :     std::scoped_lock lock(mutex_);
     253         186 :     VmiTree::const_iterator it = vmi_tree_.find(u);
     254         186 :     if (it == vmi_tree_.end())
     255          21 :         return PortSubscribeEntryPtr();
     256             : 
     257         165 :     return it->second;
     258         186 : }
     259             : 
     260             : /*
     261             :  * Process add of vm-vn subscribe entry.
     262             :  * Add an entry to vmvn_subscribe_tree_
     263             :  * If VMI config was already received for port then
     264             :  *   - find vmi-uuid from * vmvn_to_vmi_tree_
     265             :  *   - ifmap config resync will be done once vmi is added
     266             :  */
     267           0 : void PortSubscribeTable::AddVmVnPort(const boost::uuids::uuid &vm_uuid,
     268             :                                      const boost::uuids::uuid &vn_uuid,
     269             :                                      const boost::uuids::uuid &vmi_uuid,
     270             :                                      PortSubscribeEntryPtr entry) {
     271           0 :     std::scoped_lock lock(mutex_);
     272             :     std::pair<VmVnTree::iterator, bool> ret = vmvn_subscribe_tree_.insert
     273           0 :         (make_pair(VmVnUuidEntry(vm_uuid, vn_uuid, vmi_uuid),entry));
     274           0 :     if (ret.second == false) {
     275           0 :         ret.first->second->Update(entry.get());
     276             :     }
     277             : 
     278             :     // Find VMI for the vm-vn
     279             :     //boost::uuids::uuid vmi_uuid = VmVnToVmiNoLock(vm_uuid);
     280           0 :     if (vmi_uuid.is_nil())
     281           0 :         return;
     282             : 
     283             :     // If entry is found, it means IFNode for VMI already present
     284             :     // Enqueue vm-add request
     285             :     VmVnPortSubscribeEntry *vmvn_entry =
     286           0 :         static_cast<VmVnPortSubscribeEntry *>(entry.get());
     287           0 :     vmvn_entry->set_vmi_uuid(vmi_uuid);
     288           0 :     vmvn_entry->OnAdd(agent_, this);
     289           0 : }
     290             : 
     291           0 : void PortSubscribeTable::DeleteVmVnPort
     292             : (const boost::uuids::uuid &vm_uuid,
     293             : const boost::uuids::uuid &vn_uuid,
     294             : const boost::uuids::uuid &vmi_uuid) {
     295           0 :     std::scoped_lock lock(mutex_);
     296             :     VmVnTree::iterator it =
     297           0 :         vmvn_subscribe_tree_.find(VmVnUuidEntry(vm_uuid, vn_uuid, vmi_uuid));
     298           0 :     if (it == vmvn_subscribe_tree_.end())
     299           0 :         return;
     300             : 
     301           0 :     it->second->OnDelete(agent_, this);
     302           0 :     vmvn_subscribe_tree_.erase(it);
     303           0 : }
     304             : 
     305        1202 : PortSubscribeEntryPtr PortSubscribeTable::GetVmVnPortNoLock
     306             : (const boost::uuids::uuid &vm_uuid,
     307             :  const boost::uuids::uuid &vn_uuid,
     308             :  const boost::uuids::uuid &vmi_uuid) {
     309             :     VmVnTree::iterator it =
     310        1202 :         vmvn_subscribe_tree_.find(VmVnUuidEntry(vm_uuid, vn_uuid, vmi_uuid));
     311        1202 :     if (it == vmvn_subscribe_tree_.end())
     312        1202 :         return PortSubscribeEntryPtr();
     313             : 
     314           0 :     return it->second;
     315             : }
     316             : 
     317           0 : PortSubscribeEntryPtr PortSubscribeTable::GetVmVnPort
     318             : (const boost::uuids::uuid &vm_uuid,
     319             :  const boost::uuids::uuid &vn_uuid,
     320             :  const boost::uuids::uuid &vmi_uuid) {
     321           0 :     std::scoped_lock lock(mutex_);
     322           0 :     return GetVmVnPortNoLock(vm_uuid, vn_uuid, vmi_uuid);
     323           0 : }
     324             : 
     325             : /////////////////////////////////////////////////////////////////////////////
     326             : // virtual-machine-interface table handler
     327             : /////////////////////////////////////////////////////////////////////////////
     328         336 : void PortSubscribeTable::Notify(DBTablePartBase *partition, DBEntryBase *e) {
     329         336 :     IFMapNode *node = static_cast<IFMapNode *>(e);
     330         336 :     State *state = static_cast<State *>(e->GetState(partition->parent(),
     331             :                                                     vmi_config_listener_id_));
     332         336 :     if (node->IsDeleted()) {
     333         167 :         if (state == NULL)
     334         167 :             return;
     335         167 :         if (state->uuid_ != nil_uuid())
     336         167 :             uuid_ifnode_tree_.erase(state->uuid_);
     337         167 :         node->ClearState(partition->parent(), vmi_config_listener_id_);
     338         167 :         delete state;
     339         167 :         return;
     340             :     }
     341             : 
     342             :     // Allocate DBState
     343         169 :     if (state == NULL) {
     344         167 :         state = new State();
     345         167 :         node->SetState(partition->parent(), vmi_config_listener_id_, state);
     346             :     }
     347             : 
     348             :     boost::uuids::uuid u;
     349             :     VirtualMachineInterface *cfg =
     350         169 :         static_cast <VirtualMachineInterface *> (node->GetObject());
     351         169 :     if (cfg != NULL) {
     352         169 :         autogen::IdPermsType id_perms = cfg->id_perms();
     353         169 :         CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
     354         169 :     }
     355             : 
     356             :     // Update UUID tree
     357         169 :     if (state->uuid_ != u) {
     358             :         // Remove old-uuid
     359         167 :         if (state->uuid_ != nil_uuid()) {
     360           0 :             uuid_ifnode_tree_.erase(state->uuid_);
     361           0 :             state->uuid_ = nil_uuid();
     362             :         }
     363             : 
     364             :         // Set new-uuid
     365         167 :         if (u != nil_uuid()) {
     366         167 :             state->uuid_ = u;
     367         167 :             uuid_ifnode_tree_.insert(std::make_pair(u, node));
     368             :         }
     369             :     }
     370             : }
     371             : 
     372         167 : IFMapNode *PortSubscribeTable::UuidToIFNode(const boost::uuids::uuid &u) const {
     373         167 :     UuidToIFNodeTree::const_iterator it;
     374         167 :     it = uuid_ifnode_tree_.find(u);
     375         167 :     if (it == uuid_ifnode_tree_.end()) {
     376         167 :         return NULL;
     377             :     }
     378           0 :     return it->second;
     379             : }
     380             : 
     381           0 : const PortSubscribeTable::VmiEntry *PortSubscribeTable::VmiToEntry
     382             : (const boost::uuids::uuid &vmi_uuid) const {
     383           0 :     VmiToVmVnTree::const_iterator it = vmi_to_vmvn_tree_.find(vmi_uuid);
     384           0 :     if (it == vmi_to_vmvn_tree_.end())
     385           0 :         return NULL;
     386             : 
     387           0 :     return &it->second;
     388             : }
     389             : 
     390        1202 : static void CopyVmiConfigToInfo(PortSubscribeTable::VmiEntry *entry,
     391             :                                 const VmInterfaceConfigData *data) {
     392        1202 :     entry->vm_uuid_ = data->vm_uuid_;
     393        1202 :     entry->vn_uuid_ = data->vn_uuid_;
     394        1202 :     entry->sub_interface_ = (entry->parent_vmi_.is_nil() == false);
     395        1202 :     entry->parent_vmi_ = data->parent_vmi_;
     396        1202 :     entry->vlan_tag_ = data->rx_vlan_id_;
     397        1202 :     entry->vhostuser_mode_ = data->vhostuser_mode_;
     398        1202 :     entry->mac_ = data->vm_mac_;
     399        1202 :     entry->vmi_cfg = data->GetVmiCfg();
     400        1202 : }
     401             : 
     402             : /*
     403             :  * Update config tables built from VMI IFnode
     404             :  * - Adds entry into vmi_to_vmvn_tree_
     405             :  * - Adds entry to vmvn_to_vmi_tree_
     406             :  */
     407        1202 : void PortSubscribeTable::UpdateVmiIfnodeInfo
     408             : (const boost::uuids::uuid &vmi_uuid, const VmInterfaceConfigData *data) {
     409             :     // Find entry from vmi to vm-vn tree first
     410        1202 :     VmiToVmVnTree::iterator it;
     411        1202 :     it = vmi_to_vmvn_tree_.find(vmi_uuid);
     412             : 
     413        1202 :     if (it != vmi_to_vmvn_tree_.end()) {
     414             :         // Nothing to do if entry already present and vm/vn match
     415        2177 :         if (it->second.vm_uuid_ != data->vm_uuid_ ||
     416        1022 :             it->second.vn_uuid_ != data->vn_uuid_) {
     417             :             // If an entry already present and VM/VN are different, remove the
     418             :             // reverse entry first and then update with new entry
     419         143 :             vmvn_to_vmi_tree_.erase(VmVnUuidEntry(it->second.vm_uuid_,
     420         143 :                                                   it->second.vn_uuid_,
     421             :                                                   vmi_uuid));
     422         143 :             VmVnUuidEntry entry(data->vm_uuid_, data->vn_uuid_, vmi_uuid);
     423         143 :             vmvn_to_vmi_tree_.insert(std::make_pair(entry, vmi_uuid));
     424         143 :         }
     425             : 
     426             :         // Update data fields
     427        1155 :         CopyVmiConfigToInfo(&it->second, data);
     428             :     } else {
     429             :         // Entry not present add to vmi_to_vmvn_tree_ and vmvn_to_vmi_tree_
     430          47 :         VmVnUuidEntry entry(data->vm_uuid_, data->vn_uuid_, vmi_uuid);
     431          47 :         vmvn_to_vmi_tree_.insert(std::make_pair(entry, vmi_uuid));
     432          47 :         VmiEntry vmi_entry;
     433          47 :         CopyVmiConfigToInfo(&vmi_entry, data);
     434          47 :         vmi_to_vmvn_tree_.insert(std::make_pair(vmi_uuid, vmi_entry));
     435          47 :     }
     436        1202 : }
     437             : 
     438             : /*
     439             :  * VMI IFNode config added. Build vmi_to_vmvn_tree_ and vmvn_to_vmi_tree from
     440             :  * interface configuration. It will be used for vm-vn based subscriptions
     441             :  *
     442             :  * If the vm-vn port subscription is already received, the message would have
     443             :  * been ignored since vmi-uuid was not known. Process the vm-vn port
     444             :  * subscription now
     445             :  */
     446        1202 : void PortSubscribeTable::HandleVmiIfnodeAdd(const boost::uuids::uuid &vmi_uuid,
     447             :                                             const VmInterfaceConfigData *data) {
     448        1202 :     std::scoped_lock lock(mutex_);
     449        1202 :     UpdateVmiIfnodeInfo(vmi_uuid, data);
     450             :     // Add vm-interface if possible
     451             :     PortSubscribeEntryPtr entry_ref =
     452        1202 :         GetVmVnPortNoLock(data->vm_uuid_, data->vn_uuid_, vmi_uuid);
     453        1202 :     if (entry_ref.get() == NULL)
     454        1202 :         return;
     455             : 
     456             :     VmVnPortSubscribeEntry *entry =
     457           0 :         dynamic_cast<VmVnPortSubscribeEntry *>(entry_ref.get());
     458             :     // Nothing to do if vmi-uuid doesnt change
     459           0 :     if (entry->vmi_uuid() == vmi_uuid) {
     460           0 :         return;
     461             :     }
     462             : 
     463             :     // vmi-uuid for vmvn-port entry changed. Delete old VMI and add new VMI
     464           0 :     if (entry->vmi_uuid().is_nil() == false) {
     465           0 :         entry->OnDelete(agent_, this);
     466             :     }
     467           0 :     entry->set_vmi_uuid(vmi_uuid);
     468           0 :     if (entry->vmi_uuid().is_nil() == false) {
     469           0 :         entry->OnAdd(agent_, this);
     470             :     }
     471        2404 : }
     472             : 
     473             : /*
     474             :  * Update config tables built from VMI IFnode
     475             :  * - Deletes entry from vmi_to_vmvn_tree_
     476             :  * - Deletes entry from vmvn_to_vmi_tree_
     477             :  */
     478         120 : void PortSubscribeTable::DeleteVmiIfnodeInfo
     479             : (const boost::uuids::uuid &vmi_uuid) {
     480         120 :     VmiToVmVnTree::iterator it;
     481         120 :     it = vmi_to_vmvn_tree_.find(vmi_uuid);
     482         120 :     if (it == vmi_to_vmvn_tree_.end()) {
     483          87 :         return;
     484             :     }
     485             : 
     486             :     // If an entry already present in vm-vn entry, delete entries from
     487             :     // vmi_to_vmvn_tree_ and vmvn_to_vmi_tree_
     488          33 :     vmvn_to_vmi_tree_.erase(VmVnUuidEntry(it->second.vm_uuid_,
     489          33 :                                           it->second.vn_uuid_,
     490             :                                           vmi_uuid));
     491          33 :     vmi_to_vmvn_tree_.erase(it);
     492             : }
     493             : 
     494             : /*
     495             :  * VMI IFNode config deleted. Remove entries from vmi_to_vmvn_tree_ and
     496             :  * vmvn_to_vmi_tree from interface configuration.
     497             :  *
     498             :  * VMI deletion happens only on deletion of vm-vn port subscription. So, dont
     499             :  * enqueue any VMI delete from here
     500             :  */
     501         120 : void PortSubscribeTable::HandleVmiIfnodeDelete
     502             : (const boost::uuids::uuid &vmi_uuid) {
     503         120 :     std::scoped_lock lock(mutex_);
     504         120 :     DeleteVmiIfnodeInfo(vmi_uuid);
     505         120 : }
     506             : 
     507           0 : void PortSubscribeTable::StaleWalk(uint64_t version) {
     508             :     // TODO : The tree can be modified in parallel. Must ensure synchronization
     509           0 :     PortIpcHandler *pih = agent_->port_ipc_handler();
     510           0 :     if (!pih) {
     511           0 :         return;
     512             :     }
     513           0 :     VmiTree::iterator it = vmi_tree_.begin();
     514           0 :     while (it != vmi_tree_.end()) {
     515             :         VmiSubscribeEntry *entry =
     516           0 :             dynamic_cast<VmiSubscribeEntry *>(it->second.get());
     517           0 :         it++;
     518           0 :         if (entry->type() == PortSubscribeEntry::NAMESPACE)
     519           0 :             continue;
     520             : 
     521           0 :         if (entry->version() >= version) {
     522           0 :             continue;
     523             :         }
     524             : 
     525           0 :         std::string msg;
     526           0 :         pih->DeleteVmiUuidEntry(entry->vmi_uuid(), msg);
     527           0 :     }
     528             : 
     529             :     // Audit vm-vn port subscription entries
     530           0 :     VmVnTree::iterator vmvn_it = vmvn_subscribe_tree_.begin();
     531           0 :     while (vmvn_it != vmvn_subscribe_tree_.end()) {
     532             :         VmVnPortSubscribeEntry *entry =
     533           0 :             dynamic_cast<VmVnPortSubscribeEntry *>(vmvn_it->second.get());
     534           0 :         vmvn_it++;
     535           0 :         if (entry->type() == PortSubscribeEntry::NAMESPACE)
     536           0 :             continue;
     537             : 
     538           0 :         if (entry->version() >= version) {
     539           0 :             continue;
     540             :         }
     541             : 
     542           0 :         std::string msg;
     543           0 :         pih->DeleteVmVnPort(entry->vm_uuid(), msg);
     544           0 :     }
     545             : }
     546             : 
     547             : // Get port-subscribe-entry for a VMI
     548             : // First looks at VMI subscription table. If not found, looks into
     549             : // vmvn-port-subscribe table
     550        1202 : PortSubscribeEntryPtr PortSubscribeTable::Get
     551             : (const boost::uuids::uuid &vmi_uuid,
     552             :  const boost::uuids::uuid &vm_uuid,
     553             :  const boost::uuids::uuid &vn_uuid) const {
     554        1202 :     std::scoped_lock lock(mutex_);
     555        1202 :     VmiTree::const_iterator it = vmi_tree_.find(vmi_uuid);
     556        1202 :     if (it != vmi_tree_.end())
     557        1154 :         return it->second;
     558             : 
     559             :     VmVnTree::const_iterator it1 =
     560          48 :         vmvn_subscribe_tree_.find(VmVnUuidEntry(vm_uuid, vn_uuid, vmi_uuid));
     561          48 :     if (it1 != vmvn_subscribe_tree_.end())
     562           0 :         return it1->second;
     563             : 
     564          48 :     return PortSubscribeEntryPtr();
     565        1202 : }
     566             : 
     567           0 : bool PortSubscribeTable::VmVnToVmiSetNoLock
     568             : (const boost::uuids::uuid &vm_uuid,
     569             :  std::set<boost::uuids::uuid> &vmi_uuid_set) const {
     570             :     VmVnToVmiTree::const_iterator it =
     571           0 :         vmvn_to_vmi_tree_.lower_bound(
     572           0 :             VmVnUuidEntry(vm_uuid, nil_uuid(), nil_uuid()));
     573             : 
     574           0 :     while (it != vmvn_to_vmi_tree_.end()) {
     575           0 :         if (it->first.vm_uuid_ == vm_uuid)
     576           0 :             vmi_uuid_set.insert(it->second);
     577           0 :         it++;
     578             :     }
     579             : 
     580           0 :     if (vmi_uuid_set.empty())
     581           0 :         return false;
     582             : 
     583           0 :     return true;
     584             : }
     585             : 
     586           0 : bool PortSubscribeTable::VmVnToVmiSet
     587             : (const boost::uuids::uuid &vm_uuid,
     588             :  std::set<boost::uuids::uuid> &vmi_uuid_set) const {
     589           0 :     std::scoped_lock lock(mutex_);
     590           0 :     return VmVnToVmiSetNoLock(vm_uuid, vmi_uuid_set);
     591           0 : }
     592             : 
     593             : /////////////////////////////////////////////////////////////////////////////
     594             : // Introspect routines
     595             : /////////////////////////////////////////////////////////////////////////////
     596             : class SandeshPortSubscribeTask : public Task {
     597             : public:
     598           0 :     SandeshPortSubscribeTask(Agent *agent, const std::string &context) :
     599             :         Task(agent->task_scheduler()->GetTaskId(kTaskHttpRequstHandler), 0),
     600           0 :         agent_(agent),
     601           0 :         table_(agent->port_ipc_handler()->port_subscribe_table()),
     602           0 :         context_(context) {
     603           0 :     }
     604           0 :     virtual ~SandeshPortSubscribeTask() { }
     605             : 
     606             : protected:
     607             :     Agent *agent_;
     608             :     const PortSubscribeTable *table_;
     609             :     std::string context_;
     610             :     DISALLOW_COPY_AND_ASSIGN(SandeshPortSubscribeTask);
     611             : };
     612             : 
     613             : // vmi_tree_ routes
     614             : class SandeshVmiPortSubscribeTask : public SandeshPortSubscribeTask {
     615             : public:
     616           0 :     SandeshVmiPortSubscribeTask(Agent *agent, const std::string &context,
     617             :                                 const std::string &ifname,
     618           0 :                                 const boost::uuids::uuid &vmi_uuid) :
     619             :         SandeshPortSubscribeTask(agent, context),
     620           0 :         ifname_(ifname), vmi_uuid_(vmi_uuid) {
     621           0 :     }
     622           0 :     virtual ~SandeshVmiPortSubscribeTask() { }
     623             : 
     624             :     virtual bool Run();
     625           0 :     std::string Description() const { return "SandeshVmiPortSubscribeTask"; }
     626             : private:
     627             :     std::string ifname_;
     628             :     boost::uuids::uuid vmi_uuid_;
     629             :     DISALLOW_COPY_AND_ASSIGN(SandeshVmiPortSubscribeTask);
     630             : };
     631             : 
     632           0 : bool SandeshVmiPortSubscribeTask::Run() {
     633           0 :     SandeshVmiPortSubscriptionResp *resp = new SandeshVmiPortSubscriptionResp();
     634             : 
     635           0 :     PortSubscribeTable::VmiTree::const_iterator it = table_->vmi_tree_.begin();
     636           0 :     std::vector<SandeshVmiPortSubscriptionInfo> port_list;
     637           0 :     while (it != table_->vmi_tree_.end()) {
     638             :         const VmiSubscribeEntry *entry =
     639           0 :             dynamic_cast<const VmiSubscribeEntry *> (it->second.get());
     640           0 :         it++;
     641             : 
     642           0 :         if ((ifname_.empty() == false) &&
     643           0 :             (entry->ifname().find(ifname_) == string::npos) ) {
     644           0 :             continue;
     645             :         }
     646             : 
     647           0 :         if (vmi_uuid_.is_nil() == false && entry->vmi_uuid() != vmi_uuid_) {
     648           0 :             continue;
     649             :         }
     650             : 
     651           0 :         SandeshVmiPortSubscriptionInfo info;
     652           0 :         info.set_ifname(entry->ifname());
     653           0 :         info.set_version(entry->version());
     654           0 :         info.set_vmi_uuid(UuidToString(entry->vmi_uuid()));
     655           0 :         info.set_vm_uuid(UuidToString(entry->vm_uuid()));
     656           0 :         info.set_vn_uuid(UuidToString(entry->vn_uuid()));
     657           0 :         info.set_vm_name(entry->vm_name());
     658           0 :         info.set_ip4_addr(entry->ip4_addr().to_string());
     659           0 :         info.set_ip6_addr(entry->ip6_addr().to_string());
     660           0 :         info.set_mac(entry->mac_addr());
     661           0 :         info.set_tx_vlan(entry->tx_vlan_id());
     662           0 :         info.set_rx_vlan(entry->rx_vlan_id());
     663           0 :         info.set_vhostuser_mode(entry->vhostuser_mode());
     664             : 
     665           0 :         port_list.push_back(info);
     666           0 :     }
     667           0 :     resp->set_port_list(port_list);
     668             : 
     669           0 :     resp->set_context(context_);
     670           0 :     resp->set_more(false);
     671           0 :     resp->Response();
     672           0 :     return true;
     673           0 : }
     674             : 
     675           0 : void FetchVmiPortSubscriptionReq::HandleRequest() const {
     676           0 :     Agent *agent = Agent::GetInstance();
     677           0 :     boost::uuids::uuid u = StringToUuid(get_vmi_uuid());
     678             :     SandeshVmiPortSubscribeTask *t =
     679           0 :         new SandeshVmiPortSubscribeTask(agent, context(), get_ifname(), u);
     680           0 :     agent->task_scheduler()->Enqueue(t);
     681           0 : }
     682             : 
     683             : // vmvn_subscribe_tree_ routes
     684             : class SandeshVmVnPortSubscribeTask : public SandeshPortSubscribeTask {
     685             : public:
     686           0 :     SandeshVmVnPortSubscribeTask(Agent *agent, const std::string &context,
     687             :                                 const std::string &ifname,
     688           0 :                                 const boost::uuids::uuid &vm_uuid) :
     689             :         SandeshPortSubscribeTask(agent, context),
     690           0 :         ifname_(ifname), vm_uuid_(vm_uuid) {
     691           0 :     }
     692           0 :     virtual ~SandeshVmVnPortSubscribeTask() { }
     693             : 
     694             :     virtual bool Run();
     695           0 :     std::string Description() const { return "SandeshVmVnPortSubscribeTask"; }
     696             : private:
     697             :     std::string ifname_;
     698             :     boost::uuids::uuid vm_uuid_;
     699             :     DISALLOW_COPY_AND_ASSIGN(SandeshVmVnPortSubscribeTask);
     700             : };
     701             : 
     702           0 : bool SandeshVmVnPortSubscribeTask::Run() {
     703             :     SandeshVmVnPortSubscriptionResp *resp =
     704           0 :         new SandeshVmVnPortSubscriptionResp();
     705             : 
     706             :     PortSubscribeTable::VmVnTree::const_iterator it =
     707           0 :         table_->vmvn_subscribe_tree_.begin();
     708           0 :     std::vector<SandeshVmVnPortSubscriptionInfo> port_list;
     709           0 :     while (it != table_->vmvn_subscribe_tree_.end()) {
     710             :         const VmVnPortSubscribeEntry *entry =
     711           0 :             dynamic_cast<const VmVnPortSubscribeEntry *> (it->second.get());
     712           0 :         it++;
     713             : 
     714           0 :         if ((ifname_.empty() == false) &&
     715           0 :             (entry->ifname().find(ifname_) == string::npos) ) {
     716           0 :             continue;
     717             :         }
     718             : 
     719           0 :         if (vm_uuid_.is_nil() == false && entry->vm_uuid() != vm_uuid_) {
     720           0 :             continue;
     721             :         }
     722             : 
     723           0 :         SandeshVmVnPortSubscriptionInfo info;
     724           0 :         info.set_ifname(entry->ifname());
     725           0 :         info.set_version(entry->version());
     726           0 :         info.set_vm_uuid(UuidToString(entry->vm_uuid()));
     727           0 :         info.set_vn_uuid(UuidToString(nil_uuid()));
     728           0 :         info.set_vm_name(entry->vm_name());
     729           0 :         info.set_vm_identifier(entry->vm_identifier());
     730           0 :         info.set_vm_ifname(entry->vm_ifname());
     731           0 :         info.set_vm_namespace(entry->vm_namespace());
     732           0 :         info.set_vmi_uuid(UuidToString(entry->vmi_uuid()));
     733           0 :         port_list.push_back(info);
     734           0 :     }
     735           0 :     resp->set_port_list(port_list);
     736             : 
     737           0 :     resp->set_context(context_);
     738           0 :     resp->set_more(false);
     739           0 :     resp->Response();
     740           0 :     return true;
     741           0 : }
     742             : 
     743           0 : void FetchVmVnPortSubscriptionReq::HandleRequest() const {
     744           0 :     Agent *agent = Agent::GetInstance();
     745           0 :     boost::uuids::uuid u = StringToUuid(get_vm_uuid());
     746             :     SandeshVmVnPortSubscribeTask *t =
     747           0 :         new SandeshVmVnPortSubscribeTask(agent, context(), get_ifname(), u);
     748           0 :     agent->task_scheduler()->Enqueue(t);
     749           0 : }
     750             : 
     751             : // vmi_to_vmvn_tree_ routes
     752             : class SandeshVmiToVmVnTask : public SandeshPortSubscribeTask {
     753             : public:
     754           0 :     SandeshVmiToVmVnTask(Agent *agent, const std::string &context,
     755           0 :                            const boost::uuids::uuid &vmi_uuid) :
     756             :         SandeshPortSubscribeTask(agent, context),
     757           0 :         vmi_uuid_(vmi_uuid) {
     758           0 :     }
     759           0 :     virtual ~SandeshVmiToVmVnTask() { }
     760             : 
     761             :     virtual bool Run();
     762           0 :     std::string Description() const { return "SandeshVmiToVmVnTask"; }
     763             : private:
     764             :     boost::uuids::uuid vmi_uuid_;
     765             :     DISALLOW_COPY_AND_ASSIGN(SandeshVmiToVmVnTask);
     766             : };
     767             : 
     768           0 : bool SandeshVmiToVmVnTask::Run() {
     769           0 :     SandeshVmiToVmVnResp *resp = new SandeshVmiToVmVnResp();
     770             : 
     771             :     PortSubscribeTable::VmiToVmVnTree::const_iterator it =
     772           0 :         table_->vmi_to_vmvn_tree_.begin();
     773           0 :     std::vector<SandeshVmiToVmVnInfo> port_list;
     774           0 :     while (it != table_->vmi_to_vmvn_tree_.end()) {
     775           0 :         boost::uuids::uuid vmi_uuid = it->first;
     776           0 :         const PortSubscribeTable::VmiEntry *vmi_entry = &it->second;
     777           0 :         boost::uuids::uuid vm_uuid = vmi_entry->vm_uuid_;
     778           0 :         boost::uuids::uuid vn_uuid = vmi_entry->vn_uuid_;
     779           0 :         it++;
     780             : 
     781           0 :         if (vmi_uuid_.is_nil() == false && vmi_uuid != vmi_uuid_) {
     782           0 :             continue;
     783             :         }
     784             : 
     785           0 :         SandeshVmiToVmVnInfo info;
     786           0 :         info.set_vmi_uuid(UuidToString(vmi_uuid));
     787           0 :         info.set_vm_uuid(UuidToString(vm_uuid));
     788           0 :         info.set_vn_uuid(UuidToString(vn_uuid));
     789           0 :         if (vmi_entry->sub_interface_)
     790           0 :             info.set_sub_interface("True");
     791             :         else
     792           0 :             info.set_sub_interface("False");
     793           0 :         info.set_vlan_tag(vmi_entry->vlan_tag_);
     794           0 :         info.set_parent_uuid(UuidToString(vmi_entry->parent_vmi_));
     795           0 :         info.set_mac(vmi_entry->mac_);
     796           0 :         port_list.push_back(info);
     797           0 :     }
     798           0 :     resp->set_port_list(port_list);
     799             : 
     800           0 :     resp->set_context(context_);
     801           0 :     resp->set_more(false);
     802           0 :     resp->Response();
     803           0 :     return true;
     804           0 : }
     805             : 
     806           0 : void FetchVmiToVmVnUuidReq::HandleRequest() const {
     807           0 :     Agent *agent = Agent::GetInstance();
     808           0 :     boost::uuids::uuid u = StringToUuid(get_vmi_uuid());
     809           0 :     agent->task_scheduler()->Enqueue(new SandeshVmiToVmVnTask(agent, context(),
     810           0 :                                                               u));
     811           0 : }
     812             : 
     813             : // vmvn_to_vmi_tree_ routes
     814             : class SandeshVmVnToVmiTask : public SandeshPortSubscribeTask {
     815             : public:
     816           0 :     SandeshVmVnToVmiTask(Agent *agent, const std::string &context,
     817             :                            const boost::uuids::uuid &vm_uuid,
     818           0 :                            const boost::uuids::uuid &vn_uuid) :
     819             :         SandeshPortSubscribeTask(agent, context),
     820           0 :         vm_uuid_(vm_uuid), vn_uuid_(vn_uuid) {
     821           0 :     }
     822           0 :     virtual ~SandeshVmVnToVmiTask() { }
     823             : 
     824             :     virtual bool Run();
     825           0 :     std::string Description() const { return "SandeshVmVnToVmiTask"; }
     826             : private:
     827             :     boost::uuids::uuid vm_uuid_;
     828             :     boost::uuids::uuid vn_uuid_;
     829             :     DISALLOW_COPY_AND_ASSIGN(SandeshVmVnToVmiTask);
     830             : };
     831             : 
     832           0 : bool SandeshVmVnToVmiTask::Run() {
     833           0 :     SandeshVmVnToVmiResp *resp = new SandeshVmVnToVmiResp();
     834             : 
     835             :     PortSubscribeTable::VmVnToVmiTree::const_iterator it =
     836           0 :         table_->vmvn_to_vmi_tree_.begin();
     837           0 :     std::vector<SandeshVmVnToVmiInfo> port_list;
     838           0 :     while (it != table_->vmvn_to_vmi_tree_.end()) {
     839           0 :         boost::uuids::uuid vm_uuid = it->first.vm_uuid_;
     840           0 :         boost::uuids::uuid vn_uuid = it->first.vn_uuid_;
     841           0 :         boost::uuids::uuid vmi_uuid = it->second;
     842           0 :         it++;
     843             : 
     844           0 :         if (vm_uuid_.is_nil() == false && vm_uuid != vm_uuid_) {
     845           0 :             continue;
     846             :         }
     847             : 
     848           0 :         if (vn_uuid_.is_nil() == false && vn_uuid != vn_uuid_) {
     849           0 :             continue;
     850             :         }
     851             : 
     852           0 :         SandeshVmVnToVmiInfo info;
     853           0 :         info.set_vmi_uuid(UuidToString(vmi_uuid));
     854           0 :         info.set_vm_uuid(UuidToString(vm_uuid));
     855           0 :         info.set_vn_uuid(UuidToString(vn_uuid));
     856           0 :         port_list.push_back(info);
     857           0 :     }
     858           0 :     resp->set_port_list(port_list);
     859             : 
     860           0 :     resp->set_context(context_);
     861           0 :     resp->set_more(false);
     862           0 :     resp->Response();
     863           0 :     return true;
     864           0 : }
     865             : 
     866           0 : void FetchVmVnToVmiUuidReq::HandleRequest() const {
     867           0 :     Agent *agent = Agent::GetInstance();
     868           0 :     boost::uuids::uuid u1 = StringToUuid(get_vm_uuid());
     869           0 :     boost::uuids::uuid u2 = StringToUuid(get_vn_uuid());
     870           0 :     agent->task_scheduler()->Enqueue(new SandeshVmVnToVmiTask(agent, context(),
     871           0 :                                                               u1, u2));
     872           0 : }

Generated by: LCOV version 1.14