LCOV - code coverage report
Current view: top level - vnsw/agent/vrouter/ksync - flowtable_ksync.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 51 55 92.7 %
Date: 2026-08-03 02:19:58 Functions: 26 29 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef __AGENT_FLOWTABLE_KSYNC_H__
       6             : #define __AGENT_FLOWTABLE_KSYNC_H__
       7             : 
       8             : #include <boost/asio.hpp>
       9             : #include <boost/bind/bind.hpp>
      10             : 
      11             : #include <db/db_entry.h>
      12             : #include <db/db_table.h>
      13             : #include <db/db_table_partition.h>
      14             : #include <ksync/ksync_index.h>
      15             : #include <ksync/ksync_entry.h>
      16             : #include <ksync/ksync_object.h>
      17             : #include <ksync/ksync_netlink.h>
      18             : #include <vrouter/ksync/agent_ksync_types.h>
      19             : #include <vrouter/ksync/ksync_flow_memory.h>
      20             : #include <pkt/flow_proto.h>
      21             : #include <pkt/flow_table.h>
      22             : #include <vr_types.h>
      23             : #include <vr_flow.h>
      24             : 
      25             : using namespace boost::placeholders;
      26             : 
      27             : class FlowTableKSyncObject;
      28             : class KSyncFlowIndexManager;
      29             : 
      30             : struct FlowKSyncResponseInfo {
      31             :     int ksync_error_;
      32             :     uint32_t flow_handle_;
      33             :     uint8_t gen_id_;
      34             :     uint64_t evict_flow_bytes_;
      35             :     uint64_t evict_flow_packets_;
      36             :     int32_t evict_flow_oflow_;
      37             : 
      38       30276 :     void Reset() {
      39       30276 :         ksync_error_ = 0;
      40       30276 :         flow_handle_ = FlowEntry::kInvalidFlowHandle;
      41       30276 :         gen_id_ = 0;
      42       30276 :         evict_flow_bytes_ = 0;
      43       30276 :         evict_flow_packets_ = 0;
      44       30276 :         evict_flow_oflow_ = 0;
      45       30276 :     }
      46       15044 :     FlowKSyncResponseInfo() {
      47       15044 :         Reset();
      48       15044 :     }
      49             : };
      50             : 
      51             : class FlowTableKSyncEntry : public KSyncNetlinkEntry {
      52             : public:
      53             :     FlowTableKSyncEntry(FlowTableKSyncObject *obj);
      54             :     FlowTableKSyncEntry(FlowTableKSyncObject *obj, FlowEntry *flow,
      55             :                         uint32_t hash_id);
      56             :     virtual ~FlowTableKSyncEntry();
      57             : 
      58             :     void Reset();
      59             :     void Reset(FlowEntry *flow, uint32_t hash_id);
      60             : 
      61         354 :     FlowEntryPtr flow_entry() const {return flow_entry_;}
      62         652 :     uint32_t hash_id() const {return hash_id_;}
      63          22 :     void set_hash_id(uint32_t hash_id) {
      64          22 :         hash_id_ = hash_id;
      65          22 :     }
      66             :     int Encode(sandesh_op::type op, char *buf, int buf_len);
      67             :     KSyncObject *GetObject() const;
      68             : 
      69             :     std::string ToString() const;
      70             :     bool IsLess(const KSyncEntry &rhs) const;
      71             :     int AddMsg(char *buf, int buf_len);
      72             :     int ChangeMsg(char *buf, int buf_len);
      73             :     int DeleteMsg(char *buf, int buf_len);
      74             :     void SetPcapData(FlowEntryPtr fe, std::vector<int8_t> &data);
      75             :     // For flows allocate buffers in ksync-sock context
      76         144 :     virtual bool pre_alloc_rx_buffer() const { return true; }
      77             :     // KSync flow responses must be processed in multiple ksync response queues
      78             :     // to support scaling. Distribute the flows based on flow-table index
      79             :     virtual uint32_t GetTableIndex() const;
      80             :     virtual bool Sync();
      81             :     virtual KSyncEntry *UnresolvedReference();
      82         100 :     virtual bool ShouldReEvalBackReference() const {
      83             :         // no need to re-eval unresolved reference for flow entries, as they
      84             :         // do not depend on anything
      85         100 :         return false;
      86             :     }
      87           0 :     bool AllowDeleteStateComp() {return false;}
      88             :     virtual void ErrorHandler(int, uint32_t, KSyncEvent) const;
      89             :     virtual std::string VrouterError(uint32_t error) const;
      90           0 :     uint8_t gen_id() { return gen_id_; }
      91         144 :     void set_gen_id(uint8_t gen_id) { gen_id_ = gen_id; }
      92             :     uint8_t evict_gen_id() { return evict_gen_id_; }
      93         232 :     void set_evict_gen_id(uint8_t gen_id) { evict_gen_id_ = gen_id; }
      94          78 :     uint8_t vrouter_gen_id() { return vrouter_gen_id_; }
      95         100 :     uint32_t vrouter_hash_id() const { return vrouter_hash_id_; }
      96             :     FlowEvent::Event last_event() const { return last_event_; }
      97             :     void ReleaseToken();
      98         144 :     void ResetKSyncResponseInfo() {
      99         144 :         ksync_response_info_.Reset();
     100         144 :     }
     101         100 :     void SetKSyncResponseInfo(int ksync_error, uint32_t flow_handle,
     102             :                               uint8_t gen_id, uint64_t evict_flow_bytes,
     103             :                               uint64_t evict_flow_packets,
     104             :                               int32_t evict_flow_oflow) {
     105         100 :         ksync_response_info_.ksync_error_ = ksync_error;
     106         100 :         ksync_response_info_.flow_handle_ = flow_handle;
     107         100 :         ksync_response_info_.gen_id_ = gen_id;
     108         100 :         ksync_response_info_.evict_flow_bytes_ = evict_flow_bytes;
     109         100 :         ksync_response_info_.evict_flow_packets_ = evict_flow_packets;
     110         100 :         ksync_response_info_.evict_flow_oflow_ = evict_flow_oflow;
     111         100 :     }
     112         144 :     const FlowKSyncResponseInfo *ksync_response_info() const {
     113         144 :         return &ksync_response_info_;
     114             :     }
     115             : 
     116           0 :     int  ksync_response_error() const {
     117           0 :         return ksync_response_info_.ksync_error_;
     118             :     }
     119             : 
     120           1 :     uint32_t old_first_mirror_index() {
     121           1 :         return old_first_mirror_index_;
     122             :     }
     123          44 :     void set_transaction_id(uint32_t transaction_id) {
     124          44 :         transaction_id_ = transaction_id;
     125          44 :     }
     126         144 :     uint32_t get_transaction_id() const { return transaction_id_;};
     127             : 
     128             : private:
     129             :     friend class KSyncFlowEntryFreeList;
     130             :     friend class KSyncFlowIndexManager;
     131             : 
     132             :     FlowEntryPtr flow_entry_;
     133             :     uint8_t gen_id_;  // contains the last propagated genid from flow module
     134             :     uint8_t evict_gen_id_;  // contains current active gen-id in vrouter
     135             :     uint8_t vrouter_gen_id_;  // Used to identify the last genid sent to vrouter
     136             : 
     137             :     // used to identify last flow index sent to vrouter
     138             :     // helps in knowing whether the vrouter response is index
     139             :     // allocation or not
     140             :     uint32_t vrouter_hash_id_;
     141             : 
     142             :     uint32_t hash_id_;
     143             :     uint32_t old_reverse_flow_id_;
     144             :     uint32_t old_action_;
     145             :     uint32_t old_component_nh_idx_;
     146             :     uint32_t old_first_mirror_index_;
     147             :     uint32_t old_second_mirror_index_;
     148             :     bool trap_flow_;
     149             :     uint16_t old_drop_reason_;
     150             :     bool ecmp_;
     151             :     bool enable_rpf_;
     152             :     uint32_t src_nh_id_;
     153             :     FlowEvent::Event last_event_;
     154             :     boost::shared_ptr<Token> token_;
     155             :     FlowKSyncResponseInfo ksync_response_info_;
     156             :     FlowTableKSyncObject *ksync_obj_;
     157             :     boost::intrusive::list_member_hook<> free_list_node_;
     158             :     uint32_t qos_config_idx;
     159             :     uint32_t transaction_id_;
     160             :     uint8_t underlay_gw_index;
     161             :     DISALLOW_COPY_AND_ASSIGN(FlowTableKSyncEntry);
     162             : };
     163             : 
     164             : /////////////////////////////////////////////////////////////////////////////
     165             : // Class to manage free-list of flow ksync entries
     166             : // Flow allocation can happen from multiple threads. In scaled scenarios
     167             : // allocation of flow-entries in multi-thread environment adds overheads.
     168             : // The KSyncFlowEntryFreeList helps to maintain a per task free-list. Alloc/Free
     169             : // can happen without lock.
     170             : //
     171             : // Alloc and Free happens in a chunk. Alloc/Free are done based on thresholds
     172             : // in task context of the corresponding flow-table
     173             : /////////////////////////////////////////////////////////////////////////////
     174             : class KSyncFlowEntryFreeList {
     175             : public:
     176             :     static const uint32_t kInitCount = (25 * 1000);
     177             :     static const uint32_t kTestInitCount = (5 * 1000);
     178             :     static const uint32_t kGrowSize = (1 * 1000);
     179             :     static const uint32_t kMinThreshold = (4 * 1000);
     180             :     static const uint32_t kMaxThreshold = (100 * 1000);
     181             : 
     182             :     typedef boost::intrusive::member_hook<FlowTableKSyncEntry,
     183             :             boost::intrusive::list_member_hook<>,
     184             :             &FlowTableKSyncEntry::free_list_node_> Node;
     185             :     typedef boost::intrusive::list<FlowTableKSyncEntry, Node> FreeList;
     186             : 
     187             :     KSyncFlowEntryFreeList(FlowTableKSyncObject *object);
     188             :     KSyncFlowEntryFreeList(FlowTableKSyncObject *object, FlowEntry *flow,
     189             :                            uint32_t hash_id);
     190             :     virtual ~KSyncFlowEntryFreeList();
     191             : 
     192             :     void Reset();
     193             :     void Reset(FlowEntryPtr fe, uint32_t hash_id);
     194             : 
     195             :     FlowTableKSyncEntry *Allocate(const KSyncEntry *key);
     196             :     void Free(FlowTableKSyncEntry *flow);
     197             :     void Grow();
     198           5 :     uint32_t max_count() const { return max_count_; }
     199             :     uint32_t free_count() const { return free_list_.size(); }
     200             :     uint32_t alloc_count() const { return (max_count_ - free_list_.size()); }
     201           7 :     uint32_t total_alloc() const { return total_alloc_; }
     202           7 :     uint32_t total_free() const { return total_free_; }
     203             : 
     204             : private:
     205             :     FlowTableKSyncObject *object_;
     206             :     uint32_t max_count_;
     207             :     bool grow_pending_;
     208             :     uint64_t total_alloc_;
     209             :     uint64_t total_free_;
     210             :     FreeList free_list_;
     211             :     DISALLOW_COPY_AND_ASSIGN(KSyncFlowEntryFreeList);
     212             : };
     213             : 
     214             : class FlowTableKSyncObject : public KSyncObject {
     215             : public:
     216             :      // flow dependency timer on mirror entry in msec
     217             :     static const uint32_t kFlowDepSyncTimeout = 1000;
     218             :     static const uint32_t KFlowUnresolvedListYield = 32;
     219             :     FlowTableKSyncObject(KSync *ksync);
     220             :     FlowTableKSyncObject(KSync *ksync, int max_index);
     221             :     virtual ~FlowTableKSyncObject();
     222             : 
     223             :     void Init();
     224             :     void Shutdown() { }
     225             : 
     226             :     KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index);
     227             :     void Free(KSyncEntry *key);
     228         354 :     bool DoEventTrace(void) { return false; }
     229             :     FlowTableKSyncEntry *Find(FlowEntry *key);
     230             : 
     231         144 :     vr_flow_req &flow_req() { return flow_req_; }
     232         413 :     KSync *ksync() const { return ksync_; }
     233           3 :     void set_flow_table(FlowTable *table) { flow_table_ = table; }
     234         288 :     FlowTable *flow_table() const { return flow_table_; }
     235             :     void UpdateFlowHandle(FlowTableKSyncEntry *entry, uint32_t flow_handle);
     236             :     void UpdateKey(KSyncEntry *entry, uint32_t flow_handle);
     237             :     uint32_t GetKey(KSyncEntry *entry);
     238             : 
     239             :     void GrowFreeList();
     240           5 :     KSyncFlowEntryFreeList *free_list() { return &free_list_; }
     241             : 
     242             :     void NetlinkAck(KSyncEntry *entry, KSyncEntry::KSyncEvent event);
     243             :     void GenerateKSyncEvent(FlowTableKSyncEntry *entry,
     244             :                             KSyncEntry::KSyncEvent event);
     245             :     void StartTimer();
     246             :     bool TimerExpiry();
     247             :     void UpdateUnresolvedFlowEntry(FlowEntryPtr flowptr);
     248             : private:
     249             :     friend class KSyncSandeshContext;
     250             :     friend class FlowTable;
     251             :     KSync *ksync_;
     252             :     FlowTable *flow_table_;
     253             :     vr_flow_req flow_req_;
     254             :     KSyncFlowEntryFreeList free_list_;
     255             :     std::list<FlowEntryPtr> unresolved_flow_list_;
     256             :     Timer * timer_;
     257             :     DISALLOW_COPY_AND_ASSIGN(FlowTableKSyncObject);
     258             : };
     259             : 
     260             : #endif /* __AGENT_FLOWTABLE_KSYNC_H__ */

Generated by: LCOV version 1.14