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: 60 78 76.9 %
Date: 2026-11-09 02:10:49 Functions: 27 36 75.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14