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: 117 128 91.4 %
Date: 2026-06-11 01:56:02 Functions: 25 31 80.6 %
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        3349 :     AgentOperDBKey() : AgentKey() { }
      28       31301 :     AgentOperDBKey(DBSubOperation sub_op) : AgentKey(sub_op) { }
      29       34650 :     virtual ~AgentOperDBKey() { }
      30             : };
      31             : 
      32             : struct AgentOperDBData : public AgentData {
      33             : 
      34         331 :     AgentOperDBData(const Agent *agent, IFMapNode *node) :
      35         331 :         AgentData(), agent_(agent) {
      36         331 :         SetIFMapNode(node);
      37         331 :     }
      38         331 :     virtual ~AgentOperDBData() {
      39         331 :         SetIFMapNode(NULL);
      40         331 :     }
      41             : 
      42             : 
      43         732 :     void SetIFMapNode(IFMapNode *node) {
      44             : 
      45         732 :         if (node == NULL) {
      46         466 :             ifmap_node_state_ = NULL;
      47         466 :             return;
      48             :         }
      49             : 
      50         266 :         assert(agent_);
      51             : 
      52             :         // We dont allow changing the node
      53         266 :         assert(!ifmap_node_state_);
      54             : 
      55         266 :         IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager();
      56         266 :         ifmap_node_state_ = dep->SetState(node);
      57             :     }
      58             : 
      59         649 :     IFMapNode *ifmap_node() const {
      60         649 :         if (!ifmap_node_state_)
      61          27 :             return NULL;
      62         622 :         IFMapNodeState *state = ifmap_node_state_.get();
      63         622 :         return state->node();
      64             :     }
      65         132 :     const Agent *agent() const {
      66         132 :         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        3306 :     AgentOperDBEntry() : AgentDBEntry()  { }
      77        3306 :     virtual ~AgentOperDBEntry() { }
      78             : 
      79         385 :     IFMapNode *ifmap_node() const {
      80         385 :         if (!ifmap_node_state_)
      81          96 :             return NULL;
      82         289 :         IFMapNodeState *state = ifmap_node_state_.get();
      83         289 :         return state->node();
      84             :     }
      85             : 
      86          94 :     void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr sref) {
      87          94 :         ifmap_node_state_  = sref;
      88          94 :     }
      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          32 :     AgentOperDBTable(DB *db, const std::string &name) :
      98          32 :         AgentDBTable(db, name) {
      99          32 :     }
     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          32 :     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         478 :     virtual void ConfigEventHandler(IFMapNode *node, DBEntry *entry) {
     121         478 :         DBRequest req;
     122         478 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     123         478 :         boost::uuids::uuid new_uuid = boost::uuids::nil_uuid();
     124         478 :         bool uuid_set = IFNodeToUuid(node, new_uuid);
     125         478 :         IFMapNodeState *state = dep->IFMapNodeGet(node);
     126         478 :         boost::uuids::uuid old_uuid = state->uuid();
     127             : 
     128         478 :         if (!node->IsDeleted()) {
     129         409 :             if (entry) {
     130         216 :                 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         409 :             if (uuid_set && dep->IsNodeIdentifiedByUuid(node)) {
     141         346 :                 assert(new_uuid != boost::uuids::nil_uuid());
     142             :             }
     143         409 :             state->set_uuid(new_uuid);
     144         409 :             state->set_oper_db_request_enqueued(true);
     145         409 :             req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     146             :         } else {
     147          69 :             req.oper = DBRequest::DB_ENTRY_DELETE;
     148          69 :             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          69 :             new_uuid = old_uuid;
     154          69 :             if (state) {
     155          69 :                 state->set_oper_db_request_enqueued(false);
     156             :             }
     157             :         }
     158             : 
     159         478 :         if (IFNodeToReq(node, req, new_uuid) == true) {
     160          19 :             Enqueue(&req);
     161             :         }
     162             : 
     163         478 :         return;
     164         478 :     }
     165             : 
     166             : protected:
     167             :     // Handle change in IFMapNode for a DBEntry
     168         306 :     void UpdateIfMapNode(AgentOperDBEntry *entry, IFMapNode *node) {
     169         306 :         if (entry == NULL)
     170           0 :             return;
     171             : 
     172         306 :         IFMapNode *old_node = entry->ifmap_node();
     173             : 
     174         306 :         if (old_node == node)
     175         212 :             return;
     176             : 
     177          94 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     178          94 :         if (old_node) {
     179          47 :             dep->SetObject(old_node, NULL);
     180          47 :             entry->SetIFMapNodeState(NULL);
     181             :         }
     182             : 
     183          94 :         if (node) {
     184          47 :             entry->SetIFMapNodeState(dep->SetState(node));
     185          47 :             dep->SetObject(node, entry);
     186             :         }
     187             :     }
     188             : 
     189             :     // Implement Add, Delete, OnChange to provide common agent functionality
     190             :     // including,
     191          58 :     virtual DBEntry *Add(const DBRequest *req) {
     192             :         AgentOperDBEntry *entry = static_cast<AgentOperDBEntry *>
     193          58 :             (OperDBAdd(req));
     194          58 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     195          58 :         if (data && data->ifmap_node())
     196          35 :             UpdateIfMapNode(entry, data->ifmap_node());
     197          58 :         return entry;
     198             :     }
     199             : 
     200         158 :     virtual bool OnChange(DBEntry *entry, const DBRequest *req) {
     201         158 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     202         158 :         bool ret = OperDBOnChange(entry, req);
     203             : 
     204         158 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     205         158 :         if (data && data->ifmap_node())
     206         155 :             UpdateIfMapNode(oper_entry, data->ifmap_node());
     207         158 :         return ret;
     208             :     }
     209             : 
     210          39 :     virtual bool Resync(DBEntry *entry, const DBRequest *req) {
     211          39 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     212          39 :         bool ret = OperDBResync(entry, req);
     213             : 
     214          39 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     215          39 :         if (data && data->ifmap_node())
     216          38 :             UpdateIfMapNode(oper_entry, data->ifmap_node());
     217          39 :         return ret;
     218             :     }
     219             : 
     220          78 :     virtual bool Delete(DBEntry *entry, const DBRequest *req) {
     221          78 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     222          78 :         bool ret = OperDBDelete(entry, req);
     223             : 
     224          78 :         UpdateIfMapNode(oper_entry, NULL);
     225          78 :         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          14 :     OperIFMapTable(Agent *agent) : agent_(agent), oper_(agent->oper_db()) { }
     241          14 :     virtual ~OperIFMapTable() {
     242          14 :         assert(tree_.size() == 0);
     243          14 :     }
     244             : 
     245         100 :     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          39 :     void ConfigEventHandler(IFMapNode *node, DBEntry *entry) {
     251          39 :         if (node->IsDeleted()) {
     252          18 :             ConfigDelete(node);
     253          18 :             tree_.erase(node);
     254          18 :             return;
     255             :         }
     256             : 
     257          21 :         ConfigManagerEnqueue(node);
     258          21 :         return;
     259             :     }
     260             : 
     261             :     // Callback from config-manager
     262          13 :     void ProcessConfig(IFMapNode *node) {
     263          13 :         if (node->IsDeleted()) {
     264           0 :             return;
     265             :         }
     266             : 
     267          13 :         IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager();
     268          13 :         tree_.insert(std::make_pair(node, dep->SetState(node)));
     269          13 :         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