LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - flow_event.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 52 78 66.7 %
Date: 2026-06-08 02:02:55 Functions: 24 36 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #ifndef __AGENT_FLOW_EVENT_H__
       5             : #define __AGENT_FLOW_EVENT_H__
       6             : 
       7             : #include <sys/resource.h>
       8             : #include <ksync/ksync_entry.h>
       9             : #include "flow_table.h"
      10             : 
      11             : class FlowTokenPool;
      12             : 
      13             : ////////////////////////////////////////////////////////////////////////////
      14             : // Control events for flow management
      15             : ////////////////////////////////////////////////////////////////////////////
      16             : class FlowEvent {
      17             : public:
      18             :     enum Event {
      19             :         INVALID,
      20             :         // Flow add message from VRouter
      21             :         VROUTER_FLOW_MSG,
      22             :         // Message to update a flow
      23             :         FLOW_MESSAGE,
      24             :         // Event to delete a flow entry
      25             :         DELETE_FLOW,
      26             :         // Event by audit module to delete a flow
      27             :         AUDIT_FLOW,
      28             :         // In agent, flow is evicted if index is allocated for another flow
      29             :         // We delete the flow on eviction. There is a corner case where evicted
      30             :         // flow is added in parallel with different index. In that case
      31             :         // we ignore the operation
      32             :         EVICT_FLOW,
      33             :         // Revaluate flow due to deletion of a DBEntry. Other than for INET
      34             :         // routes, delete of a DBEntry will result in deletion of flows using
      35             :         // the DBEntry
      36             :         DELETE_DBENTRY,
      37             :         // Revaluate route due to change in a DBEntry. This event is used to
      38             :         // revaluate a flow on add/change of interface, vm, vn etc...
      39             :         // The action typically invovles only re-evaluating ACL lookup actions
      40             :         REVALUATE_DBENTRY,
      41             :         // Add/Delete of route can result in flow using a next higher/lower
      42             :         // prefix. The event will recompute the complete flow due to change
      43             :         // in route used for flow
      44             :         RECOMPUTE_FLOW,
      45             :         // Flow entry should be freed from kTaskFlowEvent task context.
      46             :         // Event to ensure flow entry is freed from right context
      47             :         FREE_FLOW_REF,
      48             :         // A DBEntry should be freed from kTaskFlowEvent task context.
      49             :         // Event to ensure DBEntry entry reference is freed from right context
      50             :         FREE_DBENTRY,
      51             :         // Grow the free-list entries for flow and ksync
      52             :         GROW_FREE_LIST,
      53             :         // Generate KSync event for the flow
      54             :         KSYNC_EVENT,
      55             :         // Pkt is re-entering processing in new partition
      56             :         REENTRANT,
      57             :         // Need to resolve the Flow entry whic is depending on Mirror entry
      58             :         UNRESOLVED_FLOW_ENTRY,
      59             :     };
      60             : 
      61             :     FlowEvent() :
      62             :         event_(INVALID), flow_(NULL), pkt_info_(), db_entry_(NULL),
      63             :         gen_id_(0), evict_gen_id_(0),
      64             :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(0) {
      65             :     }
      66             : 
      67             :     FlowEvent(Event event) :
      68             :         event_(event), flow_(NULL), pkt_info_(), db_entry_(NULL),
      69             :         gen_id_(0), evict_gen_id_(0), table_index_(0) {
      70             :     }
      71             : 
      72          44 :     FlowEvent(Event event, FlowEntry *flow) :
      73          44 :         event_(event), flow_(flow), pkt_info_(), db_entry_(NULL),
      74          88 :         table_index_(0) {
      75          44 :     }
      76             : 
      77           0 :     FlowEvent(Event event, uint32_t table_index) :
      78           0 :         event_(event), flow_(NULL), pkt_info_(), db_entry_(NULL),
      79           0 :         gen_id_(0), evict_gen_id_(0),
      80           0 :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(table_index) {
      81           0 :     }
      82             : 
      83         171 :     FlowEvent(Event event, FlowEntry *flow, uint32_t flow_handle,
      84         171 :               uint8_t gen_id) :
      85         171 :         event_(event), flow_(flow), pkt_info_(), db_entry_(NULL),
      86         342 :         gen_id_(gen_id), evict_gen_id_(0), flow_handle_(flow_handle),
      87         342 :         table_index_(0) {
      88         171 :     }
      89             : 
      90           0 :     FlowEvent(Event event, FlowEntry *flow, uint32_t flow_handle,
      91           0 :               uint8_t gen_id, uint8_t evict_gen_id) :
      92           0 :         event_(event), flow_(flow), pkt_info_(), db_entry_(NULL),
      93           0 :         gen_id_(gen_id), evict_gen_id_(evict_gen_id), flow_handle_(flow_handle),
      94           0 :         table_index_(0) {
      95           0 :     }
      96             : 
      97         144 :     FlowEvent(Event event, FlowEntry *flow, const DBEntry *db_entry) :
      98         144 :         event_(event), flow_(flow), pkt_info_(), db_entry_(db_entry),
      99         144 :         gen_id_(0), evict_gen_id_(0),
     100         288 :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(0) {
     101         144 :     }
     102             : 
     103             :     FlowEvent(Event event, const DBEntry *db_entry, uint32_t gen_id) :
     104             :         event_(event), flow_(NULL), pkt_info_(), db_entry_(db_entry),
     105             :         gen_id_(gen_id), evict_gen_id_(0),
     106             :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(0) {
     107             :     }
     108             : 
     109         282 :     FlowEvent(Event event, uint16_t table_index, const DBEntry *db_entry,
     110         282 :               uint32_t gen_id) :
     111         282 :         event_(event), flow_(NULL), pkt_info_(), db_entry_(db_entry),
     112         282 :         gen_id_(gen_id), evict_gen_id_(0),
     113         564 :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(table_index) {
     114         282 :     }
     115             : 
     116             :     FlowEvent(Event event, const FlowKey &key) :
     117             :         event_(event), flow_(NULL), pkt_info_(), db_entry_(NULL),
     118             :         gen_id_(0), evict_gen_id_(0), flow_key_(key),
     119             :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(0) {
     120             :     }
     121             : 
     122           0 :     FlowEvent(Event event, const FlowKey &key, uint32_t flow_handle,
     123           0 :               uint8_t gen_id) :
     124           0 :         event_(event), flow_(NULL), pkt_info_(), db_entry_(NULL),
     125           0 :         gen_id_(gen_id), evict_gen_id_(0), flow_key_(key),
     126           0 :         flow_handle_(flow_handle), table_index_(0) {
     127           0 :     }
     128             : 
     129          22 :     FlowEvent(Event event, PktInfoPtr pkt_info, FlowEntry *flow,
     130          22 :               uint32_t table_index) :
     131          22 :         event_(event), flow_(flow), pkt_info_(pkt_info), db_entry_(NULL),
     132          22 :         gen_id_(0), evict_gen_id_(0), flow_key_(),
     133          22 :         flow_handle_(FlowEntry::kInvalidFlowHandle), table_index_(table_index) {
     134          22 :     }
     135             : 
     136             :     FlowEvent(const FlowEvent &rhs) :
     137             :         event_(rhs.event_), flow_(rhs.flow()), pkt_info_(rhs.pkt_info_),
     138             :         db_entry_(rhs.db_entry_), gen_id_(rhs.gen_id_),
     139             :         evict_gen_id_(rhs.evict_gen_id_), flow_key_(rhs.flow_key_),
     140             :         flow_handle_(rhs.flow_handle_), table_index_(rhs.table_index_) {
     141             :     }
     142             : 
     143        1182 :     virtual ~FlowEvent() {
     144        1182 :     }
     145             : 
     146        4399 :     Event event() const { return event_; }
     147        2064 :     FlowEntry *flow() const { return flow_.get(); }
     148             :     FlowEntryPtr &flow_ref() { return flow_; }
     149         144 :     void set_flow(FlowEntry *flow) { flow_ = flow; }
     150         285 :     const DBEntry *db_entry() const { return db_entry_; }
     151         144 :     void set_db_entry(const DBEntry *db_entry) { db_entry_ = db_entry; }
     152         407 :     uint32_t gen_id() const { return gen_id_; }
     153           0 :     uint32_t evict_gen_id() const { return evict_gen_id_; }
     154           0 :     const FlowKey &get_flow_key() const { return flow_key_; }
     155          44 :     PktInfoPtr pkt_info() const { return pkt_info_; }
     156         425 :     uint32_t flow_handle() const { return flow_handle_; }
     157         282 :     uint32_t table_index() const { return table_index_;}
     158             : private:
     159             :     Event event_;
     160             :     FlowEntryPtr flow_;
     161             :     PktInfoPtr pkt_info_;
     162             :     const DBEntry *db_entry_;
     163             :     uint32_t gen_id_;
     164             :     uint32_t evict_gen_id_;
     165             :     FlowKey flow_key_;
     166             :     uint32_t flow_handle_;
     167             :     uint32_t table_index_;
     168             : };
     169             : 
     170             : ////////////////////////////////////////////////////////////////////////////
     171             : // Event to process VRouter response for flow operation. VRouter response for
     172             : // flow is made of two messages,
     173             : // - vr_flow response which will contains,
     174             : //   - Return code for the operation
     175             : //   - flow-handle allocated for flow
     176             : //   - gen-id for he hash-entry allocated
     177             : //   - stats for the flow being evicted by VRouter
     178             : // - vr_response
     179             : //   - contains ksync-event to be generated for the flow
     180             : //
     181             : // The event combines data from both the messages. The event-handler will
     182             : // process both the vrouter response messages
     183             : //
     184             : // The flow-handle and gen-id are got from base class (FlowEvent)
     185             : ////////////////////////////////////////////////////////////////////////////
     186             : class FlowEventKSync : public FlowEvent {
     187             : public:
     188         144 :     FlowEventKSync(const KSyncEntry::KSyncEntryPtr ksync_entry,
     189             :                    KSyncEntry::KSyncEvent ksync_event, uint32_t flow_handle,
     190             :                    uint32_t gen_id, int ksync_error, uint64_t evict_flow_bytes,
     191             :                    uint64_t evict_flow_packets, uint64_t evict_flow_oflow,
     192         144 :                    uint32_t transaction_id) :
     193             :         FlowEvent(KSYNC_EVENT, NULL, flow_handle, gen_id),
     194         288 :         ksync_entry_(ksync_entry), ksync_event_(ksync_event),
     195         144 :         ksync_error_(ksync_error), evict_flow_bytes_(evict_flow_bytes),
     196         144 :         evict_flow_packets_(evict_flow_packets),
     197         144 :         evict_flow_oflow_(evict_flow_oflow),
     198         144 :         transaction_id_(transaction_id) {
     199         144 :     }
     200             : 
     201             :     FlowEventKSync(const FlowEventKSync &rhs) :
     202             :         FlowEvent(rhs), ksync_entry_(rhs.ksync_entry_),
     203             :         ksync_event_(rhs.ksync_event_), ksync_error_(rhs.ksync_error_),
     204             :         evict_flow_bytes_(rhs.evict_flow_bytes_),
     205             :         evict_flow_packets_(rhs.evict_flow_packets_),
     206             :         evict_flow_oflow_(rhs.evict_flow_oflow_),
     207             :         transaction_id_(rhs.transaction_id_)  {
     208             :     }
     209             : 
     210         288 :     virtual ~FlowEventKSync() { }
     211             : 
     212         576 :     KSyncEntry *ksync_entry() const { return ksync_entry_.get(); }
     213         288 :     KSyncEntry::KSyncEvent ksync_event() const { return ksync_event_; }
     214         244 :     int ksync_error() const { return ksync_error_; }
     215           0 :     uint64_t evict_flow_bytes() const { return evict_flow_bytes_; }
     216           0 :     uint64_t evict_flow_packets() const { return evict_flow_packets_; }
     217           0 :     uint64_t evict_flow_oflow() const { return evict_flow_oflow_; }
     218         100 :     uint32_t transaction_id() const { return transaction_id_; }
     219             : private:
     220             :     KSyncEntry::KSyncEntryPtr ksync_entry_;
     221             :     KSyncEntry::KSyncEvent ksync_event_;
     222             :     int ksync_error_;
     223             :     uint64_t evict_flow_bytes_;
     224             :     uint64_t evict_flow_packets_;
     225             :     uint64_t evict_flow_oflow_;
     226             :     uint32_t transaction_id_;
     227             : };
     228             : 
     229             : ////////////////////////////////////////////////////////////////////////////
     230             : // FlowProto uses following queues,
     231             : //
     232             : // - FlowEventQueue
     233             : //   This queue contains events for flow add, flow eviction etc...
     234             : //   See FlowProto::FlowEventHandler for events handled in this queue
     235             : // - KSyncFlowEventQueue
     236             : //   This queue contains events generated from KSync response for a flow
     237             : // - DeleteFlowEventQueue
     238             : //   This queue contains events generated for flow-ageing
     239             : // - UpdateFlowEventQueue
     240             : //   This queue contains events generated as result of config changes such
     241             : //   as add/delete/change of interface, vn, vm, acl, nh, route etc...
     242             : //
     243             : // All queues are defined from a base class FlowEventQueueBase.
     244             : // FlowEventQueueBase implements a wrapper around the WorkQueues with following
     245             : // additional functionality,
     246             : //
     247             : // - Rate Control using Tokens
     248             : //   All the queues give above can potentially add/change/delete flows in the
     249             : //   vrouter. So, the queues given above acts as producer and VRouter acts as
     250             : //   consumer. VRouter is a slow consumer of events. To provide fairness
     251             : //   across queues, a "token" based scheme is used. See flow_token.h for more
     252             : //   information
     253             : //
     254             : //   The queue will stop the WorkQueue when it runs out of tokens. The queue
     255             : //   is started again after a minimum number of tokens become available
     256             : //
     257             : // - Time limits
     258             : //   Intermittently, it is observed that some of the queues take large amount
     259             : //   of time. Latencies in queue such as KSync queue or delete-queue can result
     260             : //   in flow-setup latencies. So, we want to impose an upper bound on the
     261             : //   amount of time taken in single run of WorkQueue.
     262             : //
     263             : //   We take timestamp at start of queue, and check latency for every 8
     264             : //   events processed in the queue. If the latency goes beyond a limit, the
     265             : //   WorkQueue run is aborted.
     266             : ////////////////////////////////////////////////////////////////////////////
     267             : class FlowEventQueueBase {
     268             : public:
     269             :     typedef WorkQueue<FlowEvent *> Queue;
     270             : 
     271             :     FlowEventQueueBase(FlowProto *proto, const std::string &name,
     272             :                        uint32_t task_id, int task_instance,
     273             :                        FlowTokenPool *pool, uint16_t latency_limit,
     274             :                        uint32_t max_iterations);
     275             :     virtual ~FlowEventQueueBase();
     276             :     virtual bool HandleEvent(FlowEvent *event) = 0;
     277             :     virtual bool Handler(FlowEvent *event);
     278             : 
     279             :     void Shutdown();
     280             :     void Enqueue(FlowEvent *event);
     281             :     bool TokenCheck();
     282             :     bool TaskEntry();
     283             :     void TaskExit(bool done);
     284           0 :     void set_disable(bool val) { queue_->set_disable(val); }
     285           0 :     uint32_t Length() { return queue_->Length(); }
     286           0 :     void MayBeStartRunner() { queue_->MayBeStartRunner(); }
     287           0 :     Queue *queue() const { return queue_; }
     288          11 :     uint64_t events_processed() const { return events_processed_; }
     289             :     uint64_t events_enqueued() const { return queue_->NumEnqueues(); }
     290             : 
     291             : protected:
     292             :     bool CanEnqueue(FlowEvent *event);
     293             :     bool CanProcess(FlowEvent *event);
     294             :     void ProcessDone(FlowEvent *event, bool update_rev_flow);
     295             : 
     296             :     Queue *queue_;
     297             :     FlowProto *flow_proto_;
     298             :     FlowTokenPool *token_pool_;
     299             :     uint64_t task_start_;
     300             :     // Number of entries processed in single run of WorkQueue
     301             :     uint32_t count_;
     302             :     // Number of events processed. Skips event that are state-compressed
     303             :     // due to Flow PendingActions
     304             :     uint64_t events_processed_;
     305             :     uint16_t latency_limit_;
     306             :     struct rusage rusage_;
     307             : };
     308             : 
     309             : class FlowEventQueue : public FlowEventQueueBase {
     310             : public:
     311             :     FlowEventQueue(Agent *agent, FlowProto *proto, FlowTable *table,
     312             :                    FlowTokenPool *pool, uint16_t latency_limit,
     313             :                    uint32_t max_iterations);
     314             :     virtual ~FlowEventQueue();
     315             : 
     316             :     bool HandleEvent(FlowEvent *event);
     317             : private:
     318             :     FlowTable *flow_table_;
     319             : };
     320             : 
     321             : class DeleteFlowEventQueue : public FlowEventQueueBase {
     322             : public:
     323             :     DeleteFlowEventQueue(Agent *agent, FlowProto *proto, FlowTable *table,
     324             :                          FlowTokenPool *pool, uint16_t latency_limit,
     325             :                          uint32_t max_iterations);
     326             :     virtual ~DeleteFlowEventQueue();
     327             : 
     328             :     bool HandleEvent(FlowEvent *event);
     329             : private:
     330             :     FlowTable *flow_table_;
     331             : };
     332             : 
     333             : class KSyncFlowEventQueue : public FlowEventQueueBase {
     334             : public:
     335             :     KSyncFlowEventQueue(Agent *agent, FlowProto *proto, FlowTable *table,
     336             :                         FlowTokenPool *pool, uint16_t latency_limit,
     337             :                         uint32_t max_iterations);
     338             :     virtual ~KSyncFlowEventQueue();
     339             : 
     340             :     bool HandleEvent(FlowEvent *event);
     341             : private:
     342             :     FlowTable *flow_table_;
     343             : };
     344             : 
     345             : class UpdateFlowEventQueue : public FlowEventQueueBase {
     346             : public:
     347             :     UpdateFlowEventQueue(Agent *agent, FlowProto *proto,
     348             :                          FlowTokenPool *pool, uint16_t latency_limit,
     349             :                          uint32_t max_iterations);
     350             :     virtual ~UpdateFlowEventQueue();
     351             : 
     352             :     bool HandleEvent(FlowEvent *event);
     353             : };
     354             : 
     355             : #endif //  __AGENT_FLOW_EVENT_H__

Generated by: LCOV version 1.14