LCOV - code coverage report
Current view: top level - vnsw/agent/oper - oper_db.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 64 128 50.0 %
Date: 2026-06-18 01:51:13 Functions: 21 31 67.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef SRC_VNSW_AGENT_OPER_OPER_DB_H_
       6             : #define SRC_VNSW_AGENT_OPER_OPER_DB_H_
       7             : 
       8             : /////////////////////////////////////////////////////////////////////////////
       9             : // This file defines set of common agent oper-db class with following
      10             : // - Support IFMap dependency tracking.
      11             : //      - The IFMapNode for a request is passed in the AgentOperDBData object
      12             : //      - AgentOperDBTable::Add allocates a AgentOperDBEntry and sets the
      13             : //        AgentOperDBEntry allocated as "state" for IFMapNode passed
      14             : //      - AgentOperDBTable::OnChange and AgentOperDBTable::Resync will check
      15             : //        if there is change in IFMapNode for the AgentOperDBEntry. If so,
      16             : //        it will release state from the previous IFMapNode and set state to
      17             : //        the new IFMapNode
      18             : //      - AgentOperDBTable::Delete will release the state added for IFMapNode
      19             : /////////////////////////////////////////////////////////////////////////////
      20             : #include <cmn/agent_cmn.h>
      21             : #include <cmn/agent_db.h>
      22             : #include <operdb_init.h>
      23             : #include <ifmap_dependency_manager.h>
      24             : #include <ifmap/ifmap_node.h>
      25             : 
      26             : struct AgentOperDBKey : public AgentKey {
      27         282 :     AgentOperDBKey() : AgentKey() { }
      28       15104 :     AgentOperDBKey(DBSubOperation sub_op) : AgentKey(sub_op) { }
      29       15386 :     virtual ~AgentOperDBKey() { }
      30             : };
      31             : 
      32             : struct AgentOperDBData : public AgentData {
      33             : 
      34          13 :     AgentOperDBData(const Agent *agent, IFMapNode *node) :
      35          13 :         AgentData(), agent_(agent) {
      36          13 :         SetIFMapNode(node);
      37          13 :     }
      38          13 :     virtual ~AgentOperDBData() {
      39          13 :         SetIFMapNode(NULL);
      40          13 :     }
      41             : 
      42             : 
      43          26 :     void SetIFMapNode(IFMapNode *node) {
      44             : 
      45          26 :         if (node == NULL) {
      46          26 :             ifmap_node_state_ = NULL;
      47          26 :             return;
      48             :         }
      49             : 
      50           0 :         assert(agent_);
      51             : 
      52             :         // We dont allow changing the node
      53           0 :         assert(!ifmap_node_state_);
      54             : 
      55           0 :         IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager();
      56           0 :         ifmap_node_state_ = dep->SetState(node);
      57             :     }
      58             : 
      59           8 :     IFMapNode *ifmap_node() const {
      60           8 :         if (!ifmap_node_state_)
      61           8 :             return NULL;
      62           0 :         IFMapNodeState *state = ifmap_node_state_.get();
      63           0 :         return state->node();
      64             :     }
      65           0 :     const Agent *agent() const {
      66           0 :         return agent_;
      67             :     }
      68             : private:
      69             :     const Agent *agent_;
      70             :     // IFMap Node pointer for the object
      71             :     IFMapDependencyManager::IFMapNodePtr ifmap_node_state_;
      72             : };
      73             : 
      74             : class AgentOperDBEntry : public AgentDBEntry {
      75             : public:
      76         244 :     AgentOperDBEntry() : AgentDBEntry()  { }
      77         244 :     virtual ~AgentOperDBEntry() { }
      78             : 
      79           9 :     IFMapNode *ifmap_node() const {
      80           9 :         if (!ifmap_node_state_)
      81           9 :             return NULL;
      82           0 :         IFMapNodeState *state = ifmap_node_state_.get();
      83           0 :         return state->node();
      84             :     }
      85             : 
      86           0 :     void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr sref) {
      87           0 :         ifmap_node_state_  = sref;
      88           0 :     }
      89             : private:
      90             :     friend class AgentOperDBTable;
      91             :     IFMapDependencyManager::IFMapNodePtr ifmap_node_state_;
      92             :     DISALLOW_COPY_AND_ASSIGN(AgentOperDBEntry);
      93             : };
      94             : 
      95             : class AgentOperDBTable : public AgentDBTable {
      96             : public:
      97          16 :     AgentOperDBTable(DB *db, const std::string &name) :
      98          16 :         AgentDBTable(db, name) {
      99          16 :     }
     100             : 
     101             :     AgentOperDBTable(DB *db, const std::string &name,
     102             :                      bool del_on_zero_refcount) :
     103             :         AgentDBTable(db, name, del_on_zero_refcount) {
     104             :     }
     105          16 :     virtual ~AgentOperDBTable() { }
     106             : 
     107             :     // AgentOperDBTable implements Add/OnChange/Delete/Resync APIs for
     108             :     // AgentDBTable. They will in-turn invoke
     109             :     // OperDBAdd/OperDBOnChange/OperDBDelete/OperDBResync correspondingly
     110             :     virtual DBEntry *OperDBAdd(const DBRequest *req) = 0;
     111             :     virtual bool OperDBOnChange(DBEntry *entry, const DBRequest *req) = 0;
     112             :     virtual bool OperDBDelete(DBEntry *entry, const DBRequest *req) = 0;
     113           0 :     virtual bool OperDBResync(DBEntry *entry, const DBRequest *req) {
     114           0 :         return false;
     115             :     }
     116             : 
     117             :     // Default callback handler from IFMap Dependency tracker. We invoke
     118             :     // IFNodeToReq to keep all IFMap handling at one place
     119             : 
     120           0 :     virtual void ConfigEventHandler(IFMapNode *node, DBEntry *entry) {
     121           0 :         DBRequest req;
     122           0 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     123           0 :         boost::uuids::uuid new_uuid = boost::uuids::nil_uuid();
     124           0 :         bool uuid_set = IFNodeToUuid(node, new_uuid);
     125           0 :         IFMapNodeState *state = dep->IFMapNodeGet(node);
     126           0 :         boost::uuids::uuid old_uuid = state->uuid();
     127             : 
     128           0 :         if (!node->IsDeleted()) {
     129           0 :             if (entry) {
     130           0 :                 if ((old_uuid != new_uuid)) {
     131           0 :                     if (old_uuid != boost::uuids::nil_uuid()) {
     132           0 :                         req.oper = DBRequest::DB_ENTRY_DELETE;
     133           0 :                         if (IFNodeToReq(node, req, old_uuid) == true) {
     134           0 :                             assert(req.oper == DBRequest::DB_ENTRY_DELETE);
     135           0 :                             Enqueue(&req);
     136             :                         }
     137             :                     }
     138             :                 }
     139             :             }
     140           0 :             if (uuid_set && dep->IsNodeIdentifiedByUuid(node)) {
     141           0 :                 assert(new_uuid != boost::uuids::nil_uuid());
     142             :             }
     143           0 :             state->set_uuid(new_uuid);
     144           0 :             state->set_oper_db_request_enqueued(true);
     145           0 :             req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     146             :         } else {
     147           0 :             req.oper = DBRequest::DB_ENTRY_DELETE;
     148           0 :             if (uuid_set && (old_uuid == boost::uuids::nil_uuid()) &&
     149           0 :                 (dep->IsNodeIdentifiedByUuid(node))) {
     150             :                 //Node was never added so no point sending delete
     151           0 :                 return;
     152             :             }
     153           0 :             new_uuid = old_uuid;
     154           0 :             if (state) {
     155           0 :                 state->set_oper_db_request_enqueued(false);
     156             :             }
     157             :         }
     158             : 
     159           0 :         if (IFNodeToReq(node, req, new_uuid) == true) {
     160           0 :             Enqueue(&req);
     161             :         }
     162             : 
     163           0 :         return;
     164           0 :     }
     165             : 
     166             : protected:
     167             :     // Handle change in IFMapNode for a DBEntry
     168           6 :     void UpdateIfMapNode(AgentOperDBEntry *entry, IFMapNode *node) {
     169           6 :         if (entry == NULL)
     170           0 :             return;
     171             : 
     172           6 :         IFMapNode *old_node = entry->ifmap_node();
     173             : 
     174           6 :         if (old_node == node)
     175           6 :             return;
     176             : 
     177           0 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     178           0 :         if (old_node) {
     179           0 :             dep->SetObject(old_node, NULL);
     180           0 :             entry->SetIFMapNodeState(NULL);
     181             :         }
     182             : 
     183           0 :         if (node) {
     184           0 :             entry->SetIFMapNodeState(dep->SetState(node));
     185           0 :             dep->SetObject(node, entry);
     186             :         }
     187             :     }
     188             : 
     189             :     // Implement Add, Delete, OnChange to provide common agent functionality
     190             :     // including,
     191           6 :     virtual DBEntry *Add(const DBRequest *req) {
     192             :         AgentOperDBEntry *entry = static_cast<AgentOperDBEntry *>
     193           6 :             (OperDBAdd(req));
     194           6 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     195           6 :         if (data && data->ifmap_node())
     196           0 :             UpdateIfMapNode(entry, data->ifmap_node());
     197           6 :         return entry;
     198             :     }
     199             : 
     200           2 :     virtual bool OnChange(DBEntry *entry, const DBRequest *req) {
     201           2 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     202           2 :         bool ret = OperDBOnChange(entry, req);
     203             : 
     204           2 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     205           2 :         if (data && data->ifmap_node())
     206           0 :             UpdateIfMapNode(oper_entry, data->ifmap_node());
     207           2 :         return ret;
     208             :     }
     209             : 
     210           0 :     virtual bool Resync(DBEntry *entry, const DBRequest *req) {
     211           0 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     212           0 :         bool ret = OperDBResync(entry, req);
     213             : 
     214           0 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     215           0 :         if (data && data->ifmap_node())
     216           0 :             UpdateIfMapNode(oper_entry, data->ifmap_node());
     217           0 :         return ret;
     218             :     }
     219             : 
     220           6 :     virtual bool Delete(DBEntry *entry, const DBRequest *req) {
     221           6 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     222           6 :         bool ret = OperDBDelete(entry, req);
     223             : 
     224           6 :         UpdateIfMapNode(oper_entry, NULL);
     225           6 :         return ret;
     226             :     }
     227             : 
     228             : private:
     229             :     DISALLOW_COPY_AND_ASSIGN(AgentOperDBTable);
     230             : };
     231             : 
     232             : // Oper-DB works on few IFMap tables which do not have corresponding
     233             : // oper DBTable.
     234             : // Example : virtual-router, network-ipam etc...
     235             : // The IFMap nodes are registered with ifmap-dependency-manager. The class
     236             : // OperIFMapTable is responsible to manage notifications of such IFMap tables
     237             : class OperIFMapTable {
     238             : public:
     239             :     typedef std::map<IFMapNode *, IFMapDependencyManager::IFMapNodePtr> Tree;
     240           7 :     OperIFMapTable(Agent *agent) : agent_(agent), oper_(agent->oper_db()) { }
     241           7 :     virtual ~OperIFMapTable() {
     242           7 :         assert(tree_.size() == 0);
     243           7 :     }
     244             : 
     245          47 :     Agent *agent() const { return agent_; }
     246             :     OperDB *oper() const { return oper_; }
     247             :     uint32_t Size() const { return tree_.size(); }
     248             : 
     249             :     // Callback from ifmap-dependnecy-manager
     250           4 :     void ConfigEventHandler(IFMapNode *node, DBEntry *entry) {
     251           4 :         if (node->IsDeleted()) {
     252           1 :             ConfigDelete(node);
     253           1 :             tree_.erase(node);
     254           1 :             return;
     255             :         }
     256             : 
     257           3 :         ConfigManagerEnqueue(node);
     258           3 :         return;
     259             :     }
     260             : 
     261             :     // Callback from config-manager
     262           3 :     void ProcessConfig(IFMapNode *node) {
     263           3 :         if (node->IsDeleted()) {
     264           0 :             return;
     265             :         }
     266             : 
     267           3 :         IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager();
     268           3 :         tree_.insert(std::make_pair(node, dep->SetState(node)));
     269           3 :         ConfigAddChange(node);
     270             :     }
     271             : 
     272             :     virtual void ConfigDelete(IFMapNode *node) = 0;
     273             :     virtual void ConfigAddChange(IFMapNode *node) = 0;
     274             :     virtual void ConfigManagerEnqueue(IFMapNode *node) = 0;
     275             : private:
     276             :     Agent *agent_;
     277             :     OperDB *oper_;
     278             :     Tree tree_;
     279             :     DISALLOW_COPY_AND_ASSIGN(OperIFMapTable);
     280             : };
     281             : #endif  // SRC_VNSW_AGENT_OPER_OPER_DB_H_

Generated by: LCOV version 1.14