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

Generated by: LCOV version 1.14