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

Generated by: LCOV version 1.14