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: 59 60 98.3 %
Date: 2026-06-08 02:02:55 Functions: 30 33 90.9 %
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        5147 :     KSyncEntry() {
      74        5147 :         Reset();
      75        5147 :     };
      76             :     // Use this constructor if automatic index allocation is needed
      77        3137 :     KSyncEntry(uint32_t index) {
      78        3137 :         Reset(index);
      79        3137 :     };
      80        8284 :     virtual ~KSyncEntry() { assert(refcount_ == 0);};
      81             : 
      82       13372 :     void Reset() {
      83       13372 :         index_ = kInvalidIndex;
      84       13372 :         state_ = INIT;
      85       13372 :         seen_ = false;
      86       13372 :         stale_ = false;
      87       13372 :         del_add_pending_ = false;
      88       13372 :         refcount_ = 0;
      89       13372 :     }
      90        3137 :     void Reset(uint32_t index) {
      91        3137 :         Reset();
      92        3137 :         index_ = index;
      93        3137 :     }
      94             : 
      95             :     // Comparator for boost::set containing all KSyncEntries in an KSyncObject
      96       35329 :     bool operator<(const KSyncEntry &rhs) const {
      97       35329 :         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         562 :     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             :     // Returns true if the entry data is resolved
     131        1743 :     virtual bool IsDataResolved() {return true;}
     132             : 
     133             :     // User define KSync Response handler
     134         958 :     virtual void Response() { };
     135             : 
     136             :     // Allow State Compression for delete.
     137           0 :     virtual bool AllowDeleteStateComp() {return true;}
     138             : 
     139             :     // User defined error handler
     140             :     virtual void ErrorHandler(int err, uint32_t seqno, KSyncEvent event) const;
     141             : 
     142             :     // Error message for vrouter returned errors
     143             :     virtual std::string VrouterError(uint32_t error) const;
     144             :     static std::string VrouterErrorToString(uint32_t error);
     145             : 
     146             :     // Every ksync operation needs an rx-buffer to read response. The rx buffer
     147             :     // are pre-allocated to minimize compuation in ksync-tx-queue
     148             :     // pre-allocation is enabled only for flows for now
     149         793 :     virtual bool pre_alloc_rx_buffer() const { return false; }
     150             :     // ksync-tx supports multiple queues for KSync events. Get index of queue
     151             :     // to use
     152        1586 :     virtual uint32_t GetTableIndex() const { return 0; }
     153             :     // On stale timer expiration, notify entry for same
     154           3 :     virtual void StaleTimerExpired() { }
     155             : 
     156        1558 :     size_t GetIndex() const {return index_;};
     157       35962 :     KSyncState GetState() const {return state_;};
     158         994 :     bool del_add_pending() const {return del_add_pending_;}
     159        6447 :     uint32_t GetRefCount() const {return refcount_;}
     160        1022 :     bool Seen() const {return seen_;}
     161          47 :     bool stale() const {return stale_;}
     162         797 :     void SetSeen() {seen_ = true;}
     163        2748 :     bool IsDeleted() { return (state_ == DEL_ACK_WAIT ||
     164        1373 :                                state_ == DEL_DEFER_DEL_ACK ||
     165        4121 :                                state_ == DEL_DEFER_SYNC ||
     166        2748 :                                state_ == DEL_DEFER_REF); };
     167             : 
     168             :     // return true if an entry is actively owned some module,
     169             :     // i.e., explicit Create was triggered for this entry and it
     170             :     // is not deleted yet by the Creator.
     171             :     // this entry however may still be still in unresolved state.
     172             :     bool IsActive() { return (state_ != TEMP && !IsDeleted()); }
     173             : 
     174          22 :     void set_del_add_pending(bool pending) {del_add_pending_ = pending;}
     175        3408 :     void RecordTransition(KSyncState from, KSyncState to, KSyncEvent event) {
     176        3408 :         t_history_.RecordTransition(from, to, event);
     177        3408 :     }
     178             : 
     179             : protected:
     180             :     void SetIndex(size_t index) {index_ = index;};
     181        3460 :     void SetState(KSyncState state) {state_ = state;};
     182             : private:
     183             :     friend void intrusive_ptr_add_ref(KSyncEntry *p);
     184             :     friend void intrusive_ptr_release(KSyncEntry *p);
     185             :     friend class KSyncSock;
     186             :     friend class KSyncObject;
     187             : 
     188             :     boost::intrusive::set_member_hook<> node_;
     189             : 
     190             :     size_t              index_;
     191             :     KSyncState          state_;
     192             :     std::atomic<int>    refcount_;
     193             :     bool                seen_;
     194             : 
     195             :     // Stale Entry flag indicates an entry as stale, which will be
     196             :     // removed once stale entry timer cleanup gets triggered.
     197             :     bool                stale_;
     198             : 
     199             :     // flag to indicate a pending DelAdd operation on entry
     200             :     // this is set to true when Delete Add operation cannot go
     201             :     // through as entry is waiting of Ack for previous operation
     202             :     bool                del_add_pending_;
     203             : 
     204             :     struct KSyncEntryTransition {
     205             :             KSyncState from_;
     206             :             KSyncState to_;
     207             :             KSyncEvent event_;
     208             :     };
     209             :     class KSyncEntryTransHistory {
     210             :         public:
     211        8284 :             KSyncEntryTransHistory() {
     212        8284 :                 idx_ = 0;
     213       49704 :                 for (int i = 0; i < size_; i++) {
     214       41420 :                     history_[i].event_ = INVALID;
     215             :                 }
     216        8284 :             }
     217             : 
     218        3408 :             void RecordTransition(KSyncState from, KSyncState to,
     219             :                                    KSyncEvent event) {
     220        3408 :                 history_[idx_].from_ = from;
     221        3408 :                 history_[idx_].to_ = to;
     222        3408 :                 history_[idx_].event_ = event;
     223        3408 :                 idx_ = (idx_+1) % size_;
     224        3408 :             }
     225             :         private:
     226             :             static const int size_ = 5;
     227             :             int idx_;
     228             :             struct KSyncEntryTransition history_[size_];
     229             :     };
     230             :     KSyncEntryTransHistory t_history_;
     231             : 
     232             :     DISALLOW_COPY_AND_ASSIGN(KSyncEntry);
     233             : };
     234             : 
     235             : // Implementation of KSyncEntry with with DBTable. Must be used along
     236             : // with KSyncDBObject.
     237             : // Registers with DBTable and drives state-machine based on DBTable
     238             : // notifications
     239             : // Applications are not needed to generate any events to the state-machine
     240             : class KSyncDBEntry : public KSyncEntry, public DBState {
     241             : public:
     242             :     typedef std::list<DBEntry *> DupEntryList;
     243             : 
     244          53 :     KSyncDBEntry() : KSyncEntry(), DBState() { db_entry_ = NULL; };
     245        2329 :     KSyncDBEntry(uint32_t index) : KSyncEntry(index), DBState() { db_entry_ = NULL; };
     246        2382 :     virtual ~KSyncDBEntry() { assert(dup_entry_list_.empty()); }
     247             : 
     248             :     // Check if object is in-sync with kernel.
     249             :     // Return true if object needs sync. Else return false
     250             :     virtual bool Sync(DBEntry *entry) = 0;
     251             : 
     252         732 :     void SetDBEntry(DBEntry *db_entry) { db_entry_ = db_entry; }
     253        1401 :     DBEntry * GetDBEntry() { return db_entry_; }
     254             : 
     255             : private:
     256             :     friend class KSyncDBObject;
     257             : 
     258             :     DBEntry *db_entry_;
     259             :     DupEntryList dup_entry_list_;
     260             :     DISALLOW_COPY_AND_ASSIGN(KSyncDBEntry);
     261             : };
     262             : 
     263             : #endif // ctrlplane_ksync_entry_h

Generated by: LCOV version 1.14