LCOV - code coverage report
Current view: top level - ksync - ksync_entry.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 60 61 98.4 %
Date: 2026-06-18 01:51:13 Functions: 31 34 91.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef ctrlplane_ksync_entry_h
       6             : #define ctrlplane_ksync_entry_h
       7             : 
       8             : #include <boost/intrusive_ptr.hpp>
       9             : #include <boost/intrusive/set.hpp>
      10             : #include <atomic>
      11             : #include <sandesh/common/vns_constants.h>
      12             : #include <sandesh/common/vns_types.h>
      13             : #include <sandesh/sandesh_trace.h>
      14             : #include <db/db_entry.h>
      15             : 
      16             : #define KSYNC_ERROR(obj, ...)\
      17             : do {\
      18             :     if (LoggingDisabled()) break;\
      19             :     obj::Send(g_vns_constants.CategoryNames.find(Category::VROUTER)->second,\
      20             :               SandeshLevel::SYS_DEBUG, __FILE__, __LINE__, ##__VA_ARGS__);\
      21             : } while (false)
      22             : 
      23             : extern SandeshTraceBufferPtr KSyncErrorTraceBuf;
      24             : #define KSYNC_ERROR_TRACE(obj, ...)                                           \
      25             : do {                                                                          \
      26             :     KSyncError##obj::TraceMsg(KSyncErrorTraceBuf,                             \
      27             :                               __FILE__, __LINE__, __VA_ARGS__);               \
      28             : } while (false)
      29             : 
      30             : class KSyncObject;
      31             : class KSyncDBObject;
      32             : 
      33             : class KSyncEntry {
      34             : public:
      35             :     enum KSyncState {
      36             :         INIT,           // Init state. Not notified
      37             :         TEMP,           // Temporary entry created on reference
      38             :         ADD_DEFER,      // Add of entry deferred due to unmet dependencies
      39             :         CHANGE_DEFER,   // Change of entry deferred due to unmet dependencies
      40             :         IN_SYNC,        // Object in sync
      41             :         SYNC_WAIT,      // Waiting on ACK for add/change
      42             :         NEED_SYNC,      // Object changed. Needs Sync
      43             :         DEL_DEFER_SYNC, // Del pending to be sent due to sync_wait
      44             :         DEL_DEFER_REF,  // Del pending to be sent due to ref-count
      45             :         DEL_DEFER_DEL_ACK, // Del pending to be sent due to Del Ack wait
      46             :         DEL_ACK_WAIT,   // Del request sent waiting for ack
      47             :         RENEW_WAIT,     // Object renewal waiting for delete-ack
      48             :         FREE_WAIT       // Entry to be freed
      49             :     };
      50             : 
      51             :     enum KSyncEvent {
      52             :         ADD_CHANGE_REQ,
      53             :         ADD_ACK,
      54             :         CHANGE_ACK,
      55             :         DEL_REQ,
      56             :         DEL_ADD_REQ,
      57             :         DEL_ACK,
      58             :         RE_EVAL,
      59             :         INT_PTR_REL,
      60             :         INVALID
      61             :     };
      62             : 
      63             :     std::string StateString() const;
      64             :     std::string AckOperationString(KSyncEvent ack_event) const;
      65             :     std::string EventString(KSyncEvent event) const;
      66             :     // All referring KSyncEntries must use KSyncEntryPtr. The ref-count
      67             :     // maintained is optionally used to defer DELETE till refcount is 0
      68             :     typedef boost::intrusive_ptr<KSyncEntry> KSyncEntryPtr;
      69             :     static const size_t kInvalidIndex = 0xFFFFFFFF;
      70             :     static const int kDefaultMsgSize = 512;
      71             : 
      72             :     // Use this constructor if automatic index allocation is *not* needed
      73        5105 :     KSyncEntry() {
      74        5105 :         Reset();
      75        5105 :     };
      76             :     // Use this constructor if automatic index allocation is needed
      77        1096 :     KSyncEntry(uint32_t index) {
      78        1096 :         Reset(index);
      79        1096 :     };
      80        6201 :     virtual ~KSyncEntry() { assert(refcount_ == 0);};
      81             : 
      82       11201 :     void Reset() {
      83       11201 :         index_ = kInvalidIndex;
      84       11201 :         state_ = INIT;
      85       11201 :         seen_ = false;
      86       11201 :         stale_ = false;
      87       11201 :         del_add_pending_ = false;
      88       11201 :         refcount_ = 0;
      89       11201 :     }
      90        1096 :     void Reset(uint32_t index) {
      91        1096 :         Reset();
      92        1096 :         index_ = index;
      93        1096 :     }
      94             : 
      95             :     // Comparator for boost::set containing all KSyncEntries in an KSyncObject
      96       11702 :     bool operator<(const KSyncEntry &rhs) const {
      97       11702 :         return IsLess(rhs);
      98             :     };
      99             :     // Comparator to manage the tree
     100             :     virtual bool IsLess(const KSyncEntry &rhs) const = 0;
     101             : 
     102             :     // Convert KSync to String
     103             :     virtual std::string ToString() const = 0;
     104             : 
     105             :     // Create handler.
     106             :     // Return true if operation is complete
     107             :     // Return false if operation asynchronously
     108             :     virtual bool Add() = 0;
     109             : 
     110             :     // Change handler.
     111             :     // Return true if operation is complete
     112             :     // Return false if operation asynchronously
     113             :     virtual bool Change() = 0;
     114             : 
     115             :     // Delete handler.
     116             :     // Return true if operation is complete
     117             :     // Return false if operation asynchronously
     118             :     virtual bool Delete() = 0;
     119             : 
     120             :     // KSyncObject for this entry. Used to release the index
     121             :     virtual KSyncObject *GetObject() const = 0;
     122             :     // Get an unresolved reference.
     123             :     // This entry will be added into resolveq_ of unresolved-entry
     124             :     virtual KSyncEntry *UnresolvedReference() = 0;
     125         130 :     virtual bool ShouldReEvalBackReference() const { return true; }
     126             : 
     127             :     // Returns true if entry is resolved and referring entry can be written
     128             :     bool IsResolved();
     129             : 
     130        1037 :     bool IsInSync() const { return (state_ == IN_SYNC); }
     131             : 
     132             :     // Returns true if the entry data is resolved
     133         667 :     virtual bool IsDataResolved() {return true;}
     134             : 
     135             :     // User define KSync Response handler
     136         101 :     virtual void Response() { };
     137             : 
     138             :     // Allow State Compression for delete.
     139           0 :     virtual bool AllowDeleteStateComp() {return true;}
     140             : 
     141             :     // User defined error handler
     142             :     virtual void ErrorHandler(int err, uint32_t seqno, KSyncEvent event) const;
     143             : 
     144             :     // Error message for vrouter returned errors
     145             :     virtual std::string VrouterError(uint32_t error) const;
     146             :     static std::string VrouterErrorToString(uint32_t error);
     147             : 
     148             :     // Every ksync operation needs an rx-buffer to read response. The rx buffer
     149             :     // are pre-allocated to minimize compuation in ksync-tx-queue
     150             :     // pre-allocation is enabled only for flows for now
     151          80 :     virtual bool pre_alloc_rx_buffer() const { return false; }
     152             :     // ksync-tx supports multiple queues for KSync events. Get index of queue
     153             :     // to use
     154         160 :     virtual uint32_t GetTableIndex() const { return 0; }
     155             :     // On stale timer expiration, notify entry for same
     156           3 :     virtual void StaleTimerExpired() { }
     157             : 
     158         892 :     size_t GetIndex() const {return index_;};
     159       45169 :     KSyncState GetState() const {return state_;};
     160         146 :     bool del_add_pending() const {return del_add_pending_;}
     161        3245 :     uint32_t GetRefCount() const {return refcount_;}
     162         492 :     bool Seen() const {return seen_;}
     163          20 :     bool stale() const {return stale_;}
     164         451 :     void SetSeen() {seen_ = true;}
     165         962 :     bool IsDeleted() { return (state_ == DEL_ACK_WAIT ||
     166         480 :                                state_ == DEL_DEFER_DEL_ACK ||
     167        1442 :                                state_ == DEL_DEFER_SYNC ||
     168         962 :                                state_ == DEL_DEFER_REF); };
     169             : 
     170             :     // return true if an entry is actively owned some module,
     171             :     // i.e., explicit Create was triggered for this entry and it
     172             :     // is not deleted yet by the Creator.
     173             :     // this entry however may still be still in unresolved state.
     174             :     bool IsActive() { return (state_ != TEMP && !IsDeleted()); }
     175             : 
     176          22 :     void set_del_add_pending(bool pending) {del_add_pending_ = pending;}
     177        1526 :     void RecordTransition(KSyncState from, KSyncState to, KSyncEvent event) {
     178        1526 :         t_history_.RecordTransition(from, to, event);
     179        1526 :     }
     180             : 
     181             : protected:
     182             :     void SetIndex(size_t index) {index_ = index;};
     183        1551 :     void SetState(KSyncState state) {state_ = state;};
     184             : private:
     185             :     friend void intrusive_ptr_add_ref(KSyncEntry *p);
     186             :     friend void intrusive_ptr_release(KSyncEntry *p);
     187             :     friend class KSyncSock;
     188             :     friend class KSyncObject;
     189             : 
     190             :     boost::intrusive::set_member_hook<> node_;
     191             : 
     192             :     size_t              index_;
     193             :     KSyncState          state_;
     194             :     std::atomic<int>    refcount_;
     195             :     bool                seen_;
     196             : 
     197             :     // Stale Entry flag indicates an entry as stale, which will be
     198             :     // removed once stale entry timer cleanup gets triggered.
     199             :     bool                stale_;
     200             : 
     201             :     // flag to indicate a pending DelAdd operation on entry
     202             :     // this is set to true when Delete Add operation cannot go
     203             :     // through as entry is waiting of Ack for previous operation
     204             :     bool                del_add_pending_;
     205             : 
     206             :     struct KSyncEntryTransition {
     207             :             KSyncState from_;
     208             :             KSyncState to_;
     209             :             KSyncEvent event_;
     210             :     };
     211             :     class KSyncEntryTransHistory {
     212             :         public:
     213        6201 :             KSyncEntryTransHistory() {
     214        6201 :                 idx_ = 0;
     215       37206 :                 for (int i = 0; i < size_; i++) {
     216       31005 :                     history_[i].event_ = INVALID;
     217             :                 }
     218        6201 :             }
     219             : 
     220        1526 :             void RecordTransition(KSyncState from, KSyncState to,
     221             :                                    KSyncEvent event) {
     222        1526 :                 history_[idx_].from_ = from;
     223        1526 :                 history_[idx_].to_ = to;
     224        1526 :                 history_[idx_].event_ = event;
     225        1526 :                 idx_ = (idx_+1) % size_;
     226        1526 :             }
     227             :         private:
     228             :             static const int size_ = 5;
     229             :             int idx_;
     230             :             struct KSyncEntryTransition history_[size_];
     231             :     };
     232             :     KSyncEntryTransHistory t_history_;
     233             : 
     234             :     DISALLOW_COPY_AND_ASSIGN(KSyncEntry);
     235             : };
     236             : 
     237             : // Implementation of KSyncEntry with with DBTable. Must be used along
     238             : // with KSyncDBObject.
     239             : // Registers with DBTable and drives state-machine based on DBTable
     240             : // notifications
     241             : // Applications are not needed to generate any events to the state-machine
     242             : class KSyncDBEntry : public KSyncEntry, public DBState {
     243             : public:
     244             :     typedef std::list<DBEntry *> DupEntryList;
     245             : 
     246          53 :     KSyncDBEntry() : KSyncEntry(), DBState() { db_entry_ = NULL; };
     247         280 :     KSyncDBEntry(uint32_t index) : KSyncEntry(index), DBState() { db_entry_ = NULL; };
     248         333 :     virtual ~KSyncDBEntry() { assert(dup_entry_list_.empty()); }
     249             : 
     250             :     // Check if object is in-sync with kernel.
     251             :     // Return true if object needs sync. Else return false
     252             :     virtual bool Sync(DBEntry *entry) = 0;
     253             : 
     254         120 :     void SetDBEntry(DBEntry *db_entry) { db_entry_ = db_entry; }
     255         230 :     DBEntry * GetDBEntry() { return db_entry_; }
     256             : 
     257             : private:
     258             :     friend class KSyncDBObject;
     259             : 
     260             :     DBEntry *db_entry_;
     261             :     DupEntryList dup_entry_list_;
     262             :     DISALLOW_COPY_AND_ASSIGN(KSyncDBEntry);
     263             : };
     264             : 
     265             : #endif // ctrlplane_ksync_entry_h

Generated by: LCOV version 1.14