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-04 02:06:09 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        7665 :     AgentOperDBKey() : AgentKey() { }
      28       31925 :     AgentOperDBKey(DBSubOperation sub_op) : AgentKey(sub_op) { }
      29       39590 :     virtual ~AgentOperDBKey() { }
      30             : };
      31             : 
      32             : struct AgentOperDBData : public AgentData {
      33             : 
      34         677 :     AgentOperDBData(const Agent *agent, IFMapNode *node) :
      35         677 :         AgentData(), agent_(agent) {
      36         677 :         SetIFMapNode(node);
      37         677 :     }
      38         677 :     virtual ~AgentOperDBData() {
      39         677 :         SetIFMapNode(NULL);
      40         677 :     }
      41             : 
      42             : 
      43        1466 :     void SetIFMapNode(IFMapNode *node) {
      44             : 
      45        1466 :         if (node == NULL) {
      46         922 :             ifmap_node_state_ = NULL;
      47         922 :             return;
      48             :         }
      49             : 
      50         544 :         assert(agent_);
      51             : 
      52             :         // We dont allow changing the node
      53         544 :         assert(!ifmap_node_state_);
      54             : 
      55         544 :         IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager();
      56         544 :         ifmap_node_state_ = dep->SetState(node);
      57             :     }
      58             : 
      59        1403 :     IFMapNode *ifmap_node() const {
      60        1403 :         if (!ifmap_node_state_)
      61          51 :             return NULL;
      62        1352 :         IFMapNodeState *state = ifmap_node_state_.get();
      63        1352 :         return state->node();
      64             :     }
      65         160 :     const Agent *agent() const {
      66         160 :         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        6471 :     AgentOperDBEntry() : AgentDBEntry()  { }
      77        6471 :     virtual ~AgentOperDBEntry() { }
      78             : 
      79         853 :     IFMapNode *ifmap_node() const {
      80         853 :         if (!ifmap_node_state_)
      81         205 :             return NULL;
      82         648 :         IFMapNodeState *state = ifmap_node_state_.get();
      83         648 :         return state->node();
      84             :     }
      85             : 
      86         206 :     void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr sref) {
      87         206 :         ifmap_node_state_  = sref;
      88         206 :     }
      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         979 :     virtual void ConfigEventHandler(IFMapNode *node, DBEntry *entry) {
     121         979 :         DBRequest req;
     122         979 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     123         979 :         boost::uuids::uuid new_uuid = boost::uuids::nil_uuid();
     124         979 :         bool uuid_set = IFNodeToUuid(node, new_uuid);
     125         979 :         IFMapNodeState *state = dep->IFMapNodeGet(node);
     126         979 :         boost::uuids::uuid old_uuid = state->uuid();
     127             : 
     128         979 :         if (!node->IsDeleted()) {
     129         827 :             if (entry) {
     130         548 :                 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         827 :             if (uuid_set && dep->IsNodeIdentifiedByUuid(node)) {
     141         666 :                 assert(new_uuid != boost::uuids::nil_uuid());
     142             :             }
     143         827 :             state->set_uuid(new_uuid);
     144         827 :             state->set_oper_db_request_enqueued(true);
     145         827 :             req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     146             :         } else {
     147         152 :             req.oper = DBRequest::DB_ENTRY_DELETE;
     148         152 :             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         152 :             new_uuid = old_uuid;
     154         152 :             if (state) {
     155         152 :                 state->set_oper_db_request_enqueued(false);
     156             :             }
     157             :         }
     158             : 
     159         979 :         if (IFNodeToReq(node, req, new_uuid) == true) {
     160          33 :             Enqueue(&req);
     161             :         }
     162             : 
     163         979 :         return;
     164         979 :     }
     165             : 
     166             : protected:
     167             :     // Handle change in IFMapNode for a DBEntry
     168         638 :     void UpdateIfMapNode(AgentOperDBEntry *entry, IFMapNode *node) {
     169         638 :         if (entry == NULL)
     170           0 :             return;
     171             : 
     172         638 :         IFMapNode *old_node = entry->ifmap_node();
     173             : 
     174         638 :         if (old_node == node)
     175         432 :             return;
     176             : 
     177         206 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     178         206 :         if (old_node) {
     179         103 :             dep->SetObject(old_node, NULL);
     180         103 :             entry->SetIFMapNodeState(NULL);
     181             :         }
     182             : 
     183         206 :         if (node) {
     184         103 :             entry->SetIFMapNodeState(dep->SetState(node));
     185         103 :             dep->SetObject(node, entry);
     186             :         }
     187             :     }
     188             : 
     189             :     // Implement Add, Delete, OnChange to provide common agent functionality
     190             :     // including,
     191         113 :     virtual DBEntry *Add(const DBRequest *req) {
     192             :         AgentOperDBEntry *entry = static_cast<AgentOperDBEntry *>
     193         113 :             (OperDBAdd(req));
     194         113 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     195         113 :         if (data && data->ifmap_node())
     196          64 :             UpdateIfMapNode(entry, data->ifmap_node());
     197         113 :         return entry;
     198             :     }
     199             : 
     200         336 :     virtual bool OnChange(DBEntry *entry, const DBRequest *req) {
     201         336 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     202         336 :         bool ret = OperDBOnChange(entry, req);
     203             : 
     204         336 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     205         336 :         if (data && data->ifmap_node())
     206         334 :             UpdateIfMapNode(oper_entry, data->ifmap_node());
     207         336 :         return ret;
     208             :     }
     209             : 
     210          80 :     virtual bool Resync(DBEntry *entry, const DBRequest *req) {
     211          80 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     212          80 :         bool ret = OperDBResync(entry, req);
     213             : 
     214          80 :         AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get());
     215          80 :         if (data && data->ifmap_node())
     216          80 :             UpdateIfMapNode(oper_entry, data->ifmap_node());
     217          80 :         return ret;
     218             :     }
     219             : 
     220         160 :     virtual bool Delete(DBEntry *entry, const DBRequest *req) {
     221         160 :         AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry);
     222         160 :         bool ret = OperDBDelete(entry, req);
     223             : 
     224         160 :         UpdateIfMapNode(oper_entry, NULL);
     225         160 :         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         389 :     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         165 :     void ConfigEventHandler(IFMapNode *node, DBEntry *entry) {
     251         165 :         if (node->IsDeleted()) {
     252          67 :             ConfigDelete(node);
     253          67 :             tree_.erase(node);
     254          67 :             return;
     255             :         }
     256             : 
     257          98 :         ConfigManagerEnqueue(node);
     258          98 :         return;
     259             :     }
     260             : 
     261             :     // Callback from config-manager
     262          62 :     void ProcessConfig(IFMapNode *node) {
     263          62 :         if (node->IsDeleted()) {
     264           0 :             return;
     265             :         }
     266             : 
     267          62 :         IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager();
     268          62 :         tree_.insert(std::make_pair(node, dep->SetState(node)));
     269          62 :         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