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

Generated by: LCOV version 1.14