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: 52 55 94.5 %
Date: 2026-11-09 02:10:49 Functions: 27 29 93.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14