LCOV - code coverage report
Current view: top level - vnsw/agent/uve - vm_uve_table_base.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 111 193 57.5 %
Date: 2026-08-03 02:19:58 Functions: 12 23 52.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <oper/interface_common.h>
       6             : #include <uve/vm_uve_table_base.h>
       7             : #include <uve/agent_uve_base.h>
       8             : 
       9             : using boost::uuids::nil_uuid;
      10             : 
      11           6 : VmUveTableBase::VmUveTableBase(Agent *agent, uint32_t default_intvl)
      12           6 :     : uve_vm_map_(), agent_(agent), uve_vm_map_mutex_(),
      13           6 :       intf_listener_id_(DBTableBase::kInvalidId),
      14           6 :       vm_listener_id_(DBTableBase::kInvalidId), timer_last_visited_(nil_uuid()),
      15           6 :       timer_(TimerManager::CreateTimer
      16           6 :              (*(agent->event_manager())->io_service(),
      17             :               "VmUveTimer",
      18           6 :               TaskScheduler::GetInstance()->GetTaskId(kTaskDBExclude), 0)) {
      19           6 :       expiry_time_ = default_intvl;
      20           6 :       timer_->Start(expiry_time_,
      21             :                     boost::bind(&VmUveTableBase::TimerExpiry, this));
      22           6 : }
      23             : 
      24           6 : VmUveTableBase::~VmUveTableBase() {
      25           6 : }
      26             : 
      27           0 : bool VmUveTableBase::TimerExpiry() {
      28           0 :     UveVmMap::iterator it = uve_vm_map_.lower_bound(timer_last_visited_);
      29           0 :     if (it == uve_vm_map_.end()) {
      30           0 :         timer_last_visited_ = nil_uuid();
      31           0 :         return true;
      32             :     }
      33             : 
      34           0 :     uint32_t count = 0;
      35           0 :     while (it != uve_vm_map_.end() && count < AgentUveBase::kUveCountPerTimer) {
      36           0 :         VmUveEntryBase* entry = it->second.get();
      37           0 :         const boost::uuids::uuid u= it->first;
      38           0 :         UveVmMap::iterator prev = it;
      39           0 :         it++;
      40           0 :         count++;
      41             : 
      42           0 :         if (entry->deleted()) {
      43           0 :             SendVmDeleteMsg(entry->vm_config_name());
      44           0 :             if (!entry->renewed()) {
      45           0 :                 std::scoped_lock lock(uve_vm_map_mutex_);
      46           0 :                 uve_vm_map_.erase(prev);
      47           0 :             } else {
      48           0 :                 entry->set_deleted(false);
      49           0 :                 entry->set_renewed(false);
      50           0 :                 entry->set_changed(false);
      51           0 :                 SendVmMsg(entry, u);
      52             :             }
      53           0 :         } else if (entry->changed()) {
      54           0 :             SendVmMsg(entry, u);
      55           0 :             entry->set_changed(false);
      56             :             /* Clear renew flag to be on safer side. Not really required */
      57           0 :             entry->set_renewed(false);
      58             :         }
      59             :     }
      60             : 
      61           0 :     if (it == uve_vm_map_.end()) {
      62           0 :         timer_last_visited_ = nil_uuid();
      63           0 :         set_expiry_time(agent_->uve()->default_interval());
      64             :     } else {
      65           0 :         timer_last_visited_ = it->first;
      66           0 :         set_expiry_time(agent_->uve()->incremental_interval());
      67             :     }
      68             :     /* Return true to trigger auto-restart of timer */
      69           0 :     return true;
      70             : }
      71             : 
      72           0 : void VmUveTableBase::set_expiry_time(int time) {
      73           0 :     if (time != expiry_time_) {
      74           0 :         expiry_time_ = time;
      75           0 :         timer_->Reschedule(expiry_time_);
      76             :     }
      77           0 : }
      78             : 
      79           0 : void VmUveTableBase::SendVmDeleteMsg(const string &vm_config_name) {
      80           0 :     UveVirtualMachineAgent uve;
      81           0 :     uve.set_name(vm_config_name);
      82           0 :     uve.set_deleted(true);
      83           0 :     DispatchVmMsg(uve);
      84           0 : }
      85             : 
      86          26 : VmUveEntryBase* VmUveTableBase::Add(const VmEntry *vm, bool vm_notify) {
      87          26 :     VmUveEntryPtr uve = Allocate(vm);
      88          26 :     pair<UveVmMap::iterator, bool> ret;
      89          26 :     ret = uve_vm_map_.insert(UveVmPair(vm->GetUuid(), uve));
      90          26 :     UveVmMap::iterator it = ret.first;
      91          26 :     VmUveEntryBase* entry = it->second.get();
      92          26 :     if (!entry->add_by_vm_notify()) {
      93          12 :         entry->set_add_by_vm_notify(vm_notify);
      94             :     }
      95          26 :     if (entry->deleted()) {
      96          18 :         entry->set_renewed(true);
      97             :     }
      98          26 :     return entry;
      99          26 : }
     100             : 
     101          12 : void VmUveTableBase::Delete(const boost::uuids::uuid &u) {
     102          12 :     UveVmMap::iterator it = uve_vm_map_.find(u);
     103          12 :     if (it == uve_vm_map_.end()) {
     104           0 :         return;
     105             :     }
     106          12 :     VmUveEntryBase* entry = it->second.get();
     107             :     /* We need to reset all non-key fields to ensure that they have right
     108             :      * values since the entry is getting re-used. Also update the 'deleted_'
     109             :      * and 'renewed_' flags */
     110          12 :     entry->Reset();
     111          12 :     return;
     112             : }
     113             : 
     114           0 : void VmUveTableBase::Change(const VmEntry *vm) {
     115           0 :     VmUveEntryBase* entry = UveEntryFromVm(vm->GetUuid());
     116           0 :     if (entry == NULL) {
     117           0 :         return;
     118             :     }
     119             : 
     120           0 :     bool send = entry->Update(vm);
     121           0 :     if (send) {
     122           0 :         entry->set_changed(true);
     123             :     }
     124             : }
     125             : 
     126           0 : VmUveTableBase::VmUveEntryPtr VmUveTableBase::Allocate(const VmEntry *vm) {
     127           0 :     VmUveEntryPtr uve(new VmUveEntryBase(agent_, vm->GetCfgName()));
     128           0 :     return uve;
     129             : }
     130             : 
     131          26 : VmUveEntryBase* VmUveTableBase::UveEntryFromVm(const boost::uuids::uuid &u) {
     132          26 :     UveVmMap::iterator it = uve_vm_map_.find(u);
     133          26 :     if (it == uve_vm_map_.end()) {
     134           0 :         return NULL;
     135             :     }
     136          26 :     return it->second.get();
     137             : }
     138             : 
     139           0 : void VmUveTableBase::DispatchVmMsg(const UveVirtualMachineAgent &uve) {
     140           0 :     UveVirtualMachineAgentTrace::Send(uve);
     141           0 : }
     142             : 
     143           0 : void VmUveTableBase::SendVmMsg(VmUveEntryBase *entry,
     144             :                                const boost::uuids::uuid &u) {
     145           0 :     UveVirtualMachineAgent uve;
     146           0 :     if (entry->FrameVmMsg(u, &uve)) {
     147           0 :         DispatchVmMsg(uve);
     148             :     }
     149           0 : }
     150             : 
     151          12 : void VmUveTableBase::MarkChanged(const boost::uuids::uuid &u) {
     152          12 :     VmUveEntryBase* entry = UveEntryFromVm(u);
     153          12 :     if (entry == NULL) {
     154           0 :         return;
     155             :     }
     156          12 :     entry->set_changed(true);
     157          12 :     return;
     158             : }
     159             : 
     160          14 : void VmUveTableBase::InterfaceAddHandler(const VmEntry* vm,
     161             :                                          const VmInterface *vmi) {
     162          14 :     VmUveEntryBase *vm_uve_entry = Add(vm, false);
     163             : 
     164          14 :     vm_uve_entry->InterfaceAdd(vmi->cfg_name());
     165          14 :     vm_uve_entry->set_vm_name(vmi->vm_name());
     166          14 :     vm_uve_entry->set_changed(true);
     167          14 : }
     168             : 
     169          14 : void VmUveTableBase::InterfaceDeleteHandler(const boost::uuids::uuid &u,
     170             :                                             const string &intf_cfg_name) {
     171          14 :     VmUveEntryBase* entry = UveEntryFromVm(u);
     172          14 :     if (entry == NULL) {
     173           0 :         return;
     174             :     }
     175             : 
     176          14 :     entry->InterfaceDelete(intf_cfg_name);
     177          14 :     entry->set_changed(true);
     178             : }
     179             : 
     180           0 : void VmUveTableBase::UpdateVmName(const boost::uuids::uuid &u,
     181             :                                   const string &vm_name) {
     182           0 :     VmUveEntryBase* entry = UveEntryFromVm(u);
     183           0 :     if (entry == NULL) {
     184           0 :         return;
     185             :     }
     186             : 
     187           0 :     entry->set_vm_name(vm_name);
     188           0 :     entry->set_changed(true);
     189             : }
     190             : 
     191          98 : void VmUveTableBase::InterfaceNotify(DBTablePartBase *partition,
     192             :                                      DBEntryBase *e) {
     193          98 :     const VmInterface *vm_port = dynamic_cast<const VmInterface*>(e);
     194          98 :     if (vm_port == NULL) {
     195          27 :         return;
     196             :     }
     197             : 
     198             :     VmUveInterfaceState *state = static_cast<VmUveInterfaceState *>
     199          71 :                       (e->GetState(partition->parent(), intf_listener_id_));
     200          71 :     if (e->IsDeleted() || ((vm_port->vm() == NULL))) {
     201          34 :         if (state) {
     202          14 :             InterfaceDeleteHandler(state->vm_uuid_, state->interface_cfg_name_);
     203          14 :             e->ClearState(partition->parent(), intf_listener_id_);
     204          14 :             delete state;
     205             :         }
     206             :     } else {
     207          37 :         const VmEntry *vm = vm_port->vm();
     208          37 :         VmInterface::FloatingIpSet old_list;
     209             : 
     210          37 :         if (!state) {
     211             :             /* Skip Add notification if it does not have config name */
     212          14 :             if (vm_port->cfg_name().empty()) {
     213           0 :                 return;
     214             :             }
     215          14 :             state = new VmUveInterfaceState(nil_uuid(), "");
     216          14 :             e->SetState(partition->parent(), intf_listener_id_, state);
     217             :         }
     218             :         /* Handle Change of VM in a given VM interface */
     219          60 :         if ((vm->GetUuid() != state->vm_uuid_) ||
     220          23 :             (vm_port->cfg_name() != state->interface_cfg_name_)) {
     221             :             //Handle disassociation of old VM from the VMI
     222          14 :             if (state->vm_uuid_ != nil_uuid() &&
     223           0 :                 !state->interface_cfg_name_.empty()) {
     224           0 :                 InterfaceDeleteHandler(state->vm_uuid_,
     225           0 :                                        state->interface_cfg_name_);
     226             :             }
     227          28 :             if (vm->GetUuid() != nil_uuid() &&
     228          14 :                 !vm_port->cfg_name().empty()) {
     229          14 :                 InterfaceAddHandler(vm, vm_port);
     230             :             }
     231          14 :             state->vm_uuid_ = vm->GetUuid();
     232          14 :             state->interface_cfg_name_ = vm_port->cfg_name();
     233          14 :             state->vm_name_ = vm_port->vm_name();
     234          23 :         } else if (vm_port->vm_name() != state->vm_name_) {
     235           0 :             UpdateVmName(state->vm_uuid_, vm_port->vm_name());
     236           0 :             state->vm_name_ = vm_port->vm_name();
     237             :         }
     238          37 :     }
     239             : }
     240             : 
     241          24 : void VmUveTableBase::VmNotify(DBTablePartBase *partition, DBEntryBase *e) {
     242          24 :     const VmEntry *vm = static_cast<const VmEntry *>(e);
     243             : 
     244             :     VmUveVmState *state = static_cast<VmUveVmState *>
     245          24 :         (e->GetState(partition->parent(), vm_listener_id_));
     246             : 
     247          24 :     if (e->IsDeleted()) {
     248          12 :         if (state) {
     249          12 :             Delete(vm->GetUuid());
     250             : 
     251          12 :             VmStatCollectionStop(state);
     252             : 
     253          12 :             e->ClearState(partition->parent(), vm_listener_id_);
     254          12 :             delete state;
     255             :         }
     256          12 :         return;
     257             :     }
     258             : 
     259          12 :     if (!state) {
     260          12 :         state = new VmUveVmState();
     261          12 :         e->SetState(partition->parent(), vm_listener_id_, state);
     262             : 
     263          12 :         Add(vm, true);
     264             : 
     265          12 :         VmStatCollectionStart(state, vm);
     266          12 :         MarkChanged(vm->GetUuid());
     267             :     } else {
     268           0 :         Change(vm);
     269             :     }
     270             : }
     271             : 
     272           0 : void VmUveTableBase::VmStatCollectionStart(VmUveVmState *state,
     273             :                                            const VmEntry *vm) {
     274           0 : }
     275             : 
     276           0 : void VmUveTableBase::VmStatCollectionStop(VmUveVmState *state) {
     277           0 : }
     278             : 
     279           3 : void VmUveTableBase::RegisterDBClients() {
     280           3 :     InterfaceTable *intf_table = agent_->interface_table();
     281           3 :     intf_listener_id_ = intf_table->Register
     282           3 :                   (boost::bind(&VmUveTableBase::InterfaceNotify, this, _1, _2));
     283             : 
     284           3 :     VmTable *vm_table = agent_->vm_table();
     285           3 :     vm_listener_id_ = vm_table->Register
     286           3 :         (boost::bind(&VmUveTableBase::VmNotify, this, _1, _2));
     287           3 : }
     288             : 
     289           6 : void VmUveTableBase::Shutdown(void) {
     290           6 :     if (vm_listener_id_ != DBTableBase::kInvalidId)
     291           3 :         agent_->vm_table()->Unregister(vm_listener_id_);
     292           6 :     if (intf_listener_id_ != DBTableBase::kInvalidId)
     293           3 :         agent_->interface_table()->Unregister(intf_listener_id_);
     294             : 
     295           6 :     if (timer_) {
     296           6 :         timer_->Cancel();
     297           6 :         TimerManager::DeleteTimer(timer_);
     298           6 :         timer_ = NULL;
     299             :     }
     300           6 : }

Generated by: LCOV version 1.14