LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - flow_mgmt.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 8 8 100.0 %
Date: 2026-11-09 02:10:49 Functions: 7 7 100.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_TABLE_MGMT_H__
       6             : #define __AGENT_FLOW_TABLE_MGMT_H__
       7             : 
       8             : #include <boost/scoped_ptr.hpp>
       9             : #include "pkt/flow_table.h"
      10             : #include <pkt/flow_mgmt/flow_mgmt_dbclient.h>
      11             : #include <pkt/flow_mgmt/flow_mgmt_tree.h>
      12             : #include "pkt/flow_event.h"
      13             : 
      14             : ////////////////////////////////////////////////////////////////////////////
      15             : // Flow Management module is responsible to keep flow action in-sync with
      16             : // changes to operational-db changes.
      17             : //
      18             : // Flow Management module tracks following,
      19             : // 1. Changes to fields of interest in the operational-db
      20             : // 2. Flows dependenent on operational-db entries
      21             : //
      22             : // On any change to an operational-db, it will ensure the dependent flows are
      23             : // revaluated to keep the flow action in-sync with latest operational state
      24             : //
      25             : // A flow can depend on following operational-entires,
      26             : // 1. Interface : Flow depends on the SG-Id of interface
      27             : // 2. VN        : Flow depends on policy of VN
      28             : // 3. ACL       : Flow depends on ACL Entries in ACL
      29             : // 4. Route     : Flow depends on the SG-Id list in the route for both source
      30             : //                and destination addresses
      31             : // 5. NextHop   : Flow depends on NH for RPF checks and for ECMP Component index
      32             : //
      33             : // An operational entry can potentially have many flows dependent on it. On
      34             : // change to an operational entry if flows are processed inline, it can lead to
      35             : // significant latency. The flow management module runs from a work-queue
      36             : // (flow-manager queue) to avoid the latency.
      37             : //
      38             : // The Flow Management module is responsible only to track the dependency
      39             : // between flows and operational entries. It does not *own* the flow entries.
      40             : // When flow management module identifies that a flow has to be revaluated
      41             : // it will invoke flow-table APIs.
      42             : //
      43             : // There are two sub-modules,
      44             : // - Flow Management DBClient
      45             : //   This module registers to DB notification for all tables of interest. It
      46             : //   enqueues events for flow revaluation in response to DBTable changes
      47             : // - Flow Management Tree module
      48             : //   This module maintains different data-structures to track flows affected
      49             : //   by change to a DBEntry. Its also responsible to trigger revaluation of
      50             : //   flows on change to a DBEntry
      51             : //
      52             : // There are 2 work-queues defined for flow-management,
      53             : // - Flow Management Request
      54             : //   All request events to flow-management module are enqueued thru this.
      55             : //   The Flow Management Tree module acts on events on this queue.
      56             : //   * Add of FLow
      57             : //   * Delete of Flow
      58             : //   * Add of DBEntry
      59             : //   * Change of DBEntry
      60             : //   * Delete of DBEntry
      61             : //   * Export of Flow
      62             : //
      63             : // - Flow Events
      64             : //   Flow Management Tree module may generate events in response to
      65             : //   requests. The response events are enqueued here. Example events are,
      66             : //   * Flow revaluation in response to DBEntry change
      67             : //   * Flow revaluation in response to DBEntry Add/Delete
      68             : //   * Flow deletion in response to DBEntry delete
      69             : //
      70             : // Workflow for flow manager module is given below,
      71             : // 1. Flow Table module will enqueue message to Flow Management queue on
      72             : //    add/delete/change of a flow. On Flow delete event, Flow Table module will
      73             : //    will also enqueue export of the flow.
      74             : // 2. Flow stats collection module will enqueue message to Flow Management
      75             : //    queue on export of flow
      76             : // 3. Flow Management module builds the following tracking information
      77             : //    - Operational entry to list of dependent flows
      78             : //    - Flow entry to list of operational-entries it is dependent on
      79             : // 4. DBClient module registers to DBTables of interest and tracks changes to
      80             : //    operational-db entries
      81             : // 5. Flow Table module will enqueue a message to Flow Management queue on
      82             : //    add/delete/change of operational entries
      83             : // 6. The action in flow-management module for operational entry events will
      84             : //    depend on the operational entry type
      85             : //
      86             : //    VN Add/Change      : Revaluate flows for change in policy
      87             : //    VN Delete          : Delete dependent flows
      88             : //    VMI Add/Change     : Revaluate flows for change in SG entry in VMI
      89             : //    Interface Delete   : Delete dependent flows
      90             : //    NH Add/Change      : Revaluate flows for change in RPF-NH
      91             : //    NH Delete          : Delete dependent flows
      92             : //    ACL Add/Change     : Revaluate flows for change in ACL rules
      93             : //    ACL Delete         : Delete dependent flows
      94             : //    Bridge Add/Change  : Flow entries are revaluated for change in SG
      95             : //    Bridge Delete      : Delete dependent flows
      96             : //    Inet Route Add     : Add of an inet route can potentially alter the route
      97             : //                         used for a route. It can also potentially alter
      98             : //                         other attributes such as floating-ip used etc...
      99             : //                         So, all flows dependent on the "covering route" are
     100             : //                         enqueued for revluation by PktFlowInfo module
     101             : //    Inet Route Change  : Revluate for for change in RPF-NH, VN and SG
     102             : //    Inet Route Delete  : Flows depending on this route will start using the
     103             : //                         covering route. It can also potentially alter
     104             : //                         other attributes such as floating-ip used etc...
     105             : //                         So, all flows dependent on the "covering route" are
     106             : //                         enqueued for revluation by PktFlowInfo module
     107             : //
     108             : // Concurrency and references
     109             : // The Flow Management module can often lead to compute spikes. To ensure this
     110             : // doesnt affect flow setup rates, it is preferable to run flow-management
     111             : // module in parallel to both DBTable and Flow setup/teardown task.
     112             : //
     113             : // Since flow-management module runs in parallel to DBTable/Flow tasks, we must
     114             : // ensure that flows and the operational dbentries are not deleted till
     115             : // flow-management module references are gone. This is achieved by following,
     116             : //
     117             : // Flow reference
     118             : // --------------
     119             : // 1. All message between flow-management and flow-table/flow-stats module will
     120             : //    hold object references. This will ensure ref-count for object dont drop
     121             : //    till messages are processed.
     122             : // 2. Each flow seen by flow-management will hold a reference to FlowEntryInfo
     123             : //    in FlowEntry as flow_mgmt_info_
     124             : //
     125             : // Per FlowEntry mutex is used to synchronize access to same Flow between
     126             : // FlowTable and Flow Management module
     127             : //
     128             : // DBEntry reference
     129             : // -----------------
     130             : // Flow Management module will rely on DBState set by DBClient module to
     131             : // ensure a DBEntry is not deleted till all its flows are deleted.
     132             : //
     133             : // Flow Management DBClient               Flow Management module
     134             : //
     135             : // 1. On DBEntry deletion, enqueue a
     136             : //    message to Flow Management module
     137             : //                                        2. Find all dependent flows and
     138             : //                                           enqueue flow-delete request for
     139             : //                                           all flows. Mark the entry as
     140             : //                                           deleted
     141             : // 3. Delete the flow and enqueue a
     142             : //    flow-deleted message to
     143             : //    flow-management module
     144             : //                                        4. Find all operational entries the
     145             : //                                           flow is dependent on and remove
     146             : //                                           the flow from their dependent tree.
     147             : //                                           If an operational entry is deleted
     148             : //                                           and there are no more dependent
     149             : //                                           flows, enqueue a message to delete
     150             : //                                           the operational entry
     151             : // 5. Remove DBState for the DBEntry
     152             : //
     153             : // RouteTable reference
     154             : // -----------------
     155             : // The Inet and Bridge route tables should not be deleted till all flows using
     156             : // them are deleted. Flow Management module holds Lifetime reference to ensure
     157             : // DBTables are deleted only after all its flows are deleted
     158             : //
     159             : // VRF Reference
     160             : // -------------
     161             : // When a VRF add is seen, the DBClient sub-module will register for Inet and
     162             : // Bridge route tables for the VRF. The unregister for these tables should
     163             : // happen only after all flows on them are deleted. The Flow Management module
     164             : // will enqueue delete of VRF only after flow entries in all Inet and Bridge
     165             : // routes are deleted
     166             : //
     167             : // Additional functionality:
     168             : // -------------------------
     169             : // A few more additional functionality is pushed to flow-management module
     170             : // 1. Logging of flows
     171             : // 2. Flow UVE
     172             : // 3. Tracking per VN flows
     173             : //
     174             : // Duplicate Deletes:
     175             : // -----------------
     176             : // Consider following sequence of events,
     177             : // 1. Add ACL
     178             : // 2. Delete ACL
     179             : // 3. Delete ACL
     180             : //
     181             : // Correspondingly, 3 events are enqueued to Flow Management Request queue.
     182             : // When event (2) is processed, if ACL does not have any more flows, it will
     183             : // result in removing DBState for the ACL and eventual free of ACL before
     184             : // event (3) is processed. When event (3) is being processed, it may refer to
     185             : // a free'd DBEntry
     186             : //
     187             : // We use a gen-id to handle this scenario.The gen-id is incremented on every
     188             : // Delete notification received for DBEntry. When DELETE event is enqueued, it
     189             : // will also carry the gen-id field. The gen-id is also carried in the
     190             : // response events generated.
     191             : //
     192             : // When Flow Management Dbclient module receives FREE_DBENTRY event, it will
     193             : // ignore the message if gen-id does not match with latest value.
     194             : ////////////////////////////////////////////////////////////////////////////
     195             : 
     196             : ////////////////////////////////////////////////////////////////////////////
     197             : // Flow Management module maintains following data structures
     198             : //
     199             : // - FlowEntryTree : Tree of all flow entries
     200             : //   FlowEntryPtr  : Key for the tree. Holds reference to FlowEntry
     201             : //   FlowEntryInfo : Data for the tree. Contains tree of DBEntries the flow is
     202             : //                   dependent on.
     203             : //
     204             : // - FlowMgmtTree  : Per operational entry tree. Tracks flow entries dependent
     205             : //                   on the operational entry
     206             : //
     207             : //                   An entry into the tree can be added when,
     208             : //                   1. Flow is added/changed and it refers to the DBEntry
     209             : //                   or
     210             : //                   2. DBEntry add/change message is got from DBClient
     211             : //
     212             : //                   Entry from the tree is removed,
     213             : //                   1. All flows dependent on the entry are deleted
     214             : //                   AND
     215             : //                   2. DBEntry delete message is got from DBClient
     216             : //
     217             : //   FlowEntryKey  : Key for the tree. Contains DBEntry pointer as key
     218             : //   FlowMgmtEntry : Data fot the tree. Maintains intrusive-list of
     219             : //                   FlowMgmtKeyNodes(which contains references to Flow entries)
     220             : //                   dependent on the DBEntry
     221             : //
     222             : // - AclFlowMgmtTree        : FlowMgmtTree for ACL
     223             : // - InterfaceFlowMgmtTree  : FlowMgmtTree for VM-Interfaces
     224             : // - VnFlowMgmtTree         : FlowMgmtTree for VN
     225             : // - InetRouteFlowMgmtTree  : FlowMgmtTree for IPv4 routes
     226             : // - InetRouteFlowMgmtTree  : FlowMgmtTree for IPv6 routes
     227             : // - BridgeRouteFlowMgmtTree: FlowMgmtTree for Bridge routes
     228             : // - NhFlowMgmtTree         : FlowMgmtTree for NH
     229             : // - VrfFlowMgmtTree        : FlowMgmtTree for VRF. It doesnt track the flows
     230             : //                            for the VRF. But is used to ensure VRF entry is
     231             : //                            not deleted till all route-entries are freed and
     232             : //                            DELETE event for VRF is processed
     233             : // - BgpAsAServiceFlowMgmtTree : FlowMgmtTree per control-node. This is
     234             : //                               maintained per control node because VMI can
     235             : //                               establish a bgp peer session with each control
     236             : //                               node.
     237             : ////////////////////////////////////////////////////////////////////////////
     238             : 
     239             : class FlowMgmtManager {
     240             : public:
     241             :     typedef boost::shared_ptr<FlowMgmtRequest> FlowMgmtRequestPtr;
     242             :     typedef WorkQueue<FlowMgmtRequestPtr> FlowMgmtQueue;
     243             : 
     244             :     // Comparator for FlowEntryPtr
     245             :     struct FlowEntryRefCmp {
     246             :         bool operator()(const FlowEntryPtr &l, const FlowEntryPtr &r) {
     247             :             FlowEntry *lhs = l.get();
     248             :             FlowEntry *rhs = r.get();
     249             : 
     250             :             return (lhs < rhs);
     251             :         }
     252             :     };
     253             : 
     254             :     // We want flow to be valid till Flow Management task is complete. So,
     255             :     // use FlowEntryPtr as key and hold reference to flow till we are done
     256             :     typedef std::map<FlowEntryPtr, FlowEntryInfo, FlowEntryRefCmp>
     257             :         FlowEntryTree;
     258             : 
     259             :     FlowMgmtManager(Agent *agent, uint16_t table_index);
     260           8 :     virtual ~FlowMgmtManager() { }
     261             : 
     262             :     void Init();
     263             :     void Shutdown();
     264             :     static void InitLogQueue(Agent *agent);
     265             :     static void ShutdownLogQueue();
     266             :     static void LogFlowUnlocked(FlowEntry *flow, const std::string &op);
     267             :     static bool LogHandler(FlowMgmtRequestPtr req);
     268             : 
     269             :     bool RequestHandler(FlowMgmtRequestPtr req);
     270             :     bool DBRequestHandler(FlowMgmtRequestPtr req);
     271             :     static bool ProcessEvent(FlowMgmtRequest *req, FlowMgmtKey *key,
     272             :                              FlowMgmtTree *tree);
     273             : 
     274             :     bool DBRequestHandler(FlowMgmtRequest *req, const DBEntry *entry);
     275             :     bool BgpAsAServiceRequestHandler(FlowMgmtRequest *req);
     276             :     bool DbClientHandler(const DBEntry *entry);
     277             :     void EnqueueFlowEvent(FlowEvent *event);
     278             :     void NonOperEntryEvent(FlowEvent::Event event, FlowEntry *flow);
     279             :     void DBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
     280             :                       FlowEntry *flow);
     281             :     void FreeDBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
     282             :                           uint32_t gen_id);
     283             : 
     284        1282 :     Agent *agent() const { return agent_; }
     285             :     uint16_t table_index() const { return table_index_; }
     286             :     void AddEvent(FlowEntry *low);
     287             :     void DeleteEvent(FlowEntry *flow, const RevFlowDepParams &params);
     288             :     void FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes, uint32_t packets,
     289             :                               uint32_t oflow_bytes,
     290             :                               const boost::uuids::uuid &u);
     291             :     void AddDBEntryEvent(const DBEntry *entry, uint32_t gen_id);
     292             :     void ChangeDBEntryEvent(const DBEntry *entry, uint32_t gen_id);
     293             :     void DeleteDBEntryEvent(const DBEntry *entry, uint32_t gen_id);
     294             :     void RouteNHChangeEvent(const DBEntry *entry, uint32_t gen_id);
     295             :     void RetryVrfDeleteEvent(const VrfEntry *vrf);
     296             :     void RetryVrfDelete(uint32_t vrf_id);
     297             :     // Dummy event used for testing
     298             :     void DummyEvent();
     299             : 
     300             :     void VnFlowCounters(const VnEntry *vn,
     301             :                         uint32_t *ingress_flow_count,
     302             :                         uint32_t *egress_flow_count);
     303             :     void InterfaceFlowCount(const Interface *itf, uint64_t *created,
     304             :                             uint64_t *aged, uint32_t *active_flows);
     305             :     bool HasVrfFlows(uint32_t vrf);
     306             : 
     307        3494 :     FlowMgmtDbClient *flow_mgmt_dbclient() const {
     308        3494 :         return flow_mgmt_dbclient_.get();
     309             :     }
     310             : 
     311           5 :     const FlowMgmtQueue *request_queue() const { return &request_queue_; }
     312             :     const FlowMgmtQueue *log_queue() const { return log_queue_; }
     313           1 :     void DisableWorkQueue(bool disable) { request_queue_.set_disable(disable); }
     314             :     void BgpAsAServiceNotify(const boost::uuids::uuid &vm_uuid,
     315             :                              uint32_t source_port);
     316             :     void BgpAsAServiceHealthCheckNotify(const boost::uuids::uuid &vm_uuid,
     317             :                                         uint32_t source_port,
     318             :                                         const boost::uuids::uuid &hc_uuid,
     319             :                                         bool add);
     320             :     void EnqueueUveAddEvent(const FlowEntry *flow) const;
     321             :     void EnqueueUveDeleteEvent(const FlowEntry *flow) const;
     322             : 
     323             :     void FlowUpdateQueueDisable(bool val);
     324             :     size_t FlowUpdateQueueLength();
     325             :     size_t FlowDBQueueLength();
     326         144 :     InetRouteFlowMgmtTree* ip4_route_flow_mgmt_tree() {
     327         144 :         return &ip4_route_flow_mgmt_tree_;
     328             :     }
     329             : 
     330             :     BgpAsAServiceFlowMgmtKey *FindBgpAsAServiceInfo(
     331             :                                 FlowEntry *flow,
     332             :                                 BgpAsAServiceFlowMgmtKey &key);
     333             : 
     334             : private:
     335             :     // Handle Add/Change of a flow. Builds FlowMgmtKeyTree for all objects
     336             :     void AddFlow(FlowEntryPtr &flow);
     337             :     // Handle Delete of a flow. Updates FlowMgmtKeyTree for all objects
     338             :     void DeleteFlow(FlowEntryPtr &flow, const RevFlowDepParams &p);
     339             :     void UpdateFlowStats(FlowEntryPtr &flow, uint32_t bytes, uint32_t packets,
     340             :                          uint32_t oflow_bytes, const boost::uuids::uuid &u);
     341             : 
     342             :     // Add a FlowMgmtKey into the FlowMgmtKeyTree for an object
     343             :     // The FlowMgmtKeyTree for object is passed as argument
     344             :     void AddFlowMgmtKey(FlowEntry *flow, FlowEntryInfo *info,
     345             :                         FlowMgmtKey *key, FlowMgmtKey *old_key);
     346             :     // Delete a FlowMgmtKey from FlowMgmtKeyTree for an object
     347             :     // The FlowMgmtKeyTree for object is passed as argument
     348             :     void DeleteFlowMgmtKey(FlowEntry *flow, FlowEntryInfo *info,
     349             :                            FlowMgmtKey *key, FlowMgmtKeyNode *node);
     350             :     FlowEntryInfo *FindFlowEntryInfo(const FlowEntryPtr &flow);
     351             :     FlowEntryInfo *LocateFlowEntryInfo(FlowEntryPtr &flow);
     352             :     void DeleteFlowEntryInfo(FlowEntryPtr &flow);
     353             :     void MakeFlowMgmtKeyTree(FlowEntry *flow, FlowMgmtKeyTree *tree);
     354             :     void SetAceSandeshData(const AclDBEntry *acl, AclFlowCountResp &data,
     355             :                            const std::string &ace_id);
     356             :     void SetAclFlowSandeshData(const AclDBEntry *acl, AclFlowResp &data,
     357             :                                const int last_count);
     358             :     void ControllerNotify(uint8_t index);
     359             : 
     360             :     Agent *agent_;
     361             :     uint16_t table_index_;
     362             :     AclFlowMgmtTree acl_flow_mgmt_tree_;
     363             :     InterfaceFlowMgmtTree interface_flow_mgmt_tree_;
     364             :     VnFlowMgmtTree vn_flow_mgmt_tree_;
     365             :     InetRouteFlowMgmtTree ip4_route_flow_mgmt_tree_;
     366             :     InetRouteFlowMgmtTree ip6_route_flow_mgmt_tree_;
     367             :     BridgeRouteFlowMgmtTree bridge_route_flow_mgmt_tree_;
     368             :     VrfFlowMgmtTree vrf_flow_mgmt_tree_;
     369             :     NhFlowMgmtTree nh_flow_mgmt_tree_;
     370             :     boost::scoped_ptr<BgpAsAServiceFlowMgmtTree> bgp_as_a_service_flow_mgmt_tree_[MAX_XMPP_SERVERS];
     371             :     std::unique_ptr<FlowMgmtDbClient> flow_mgmt_dbclient_;
     372             :     FlowMgmtQueue request_queue_;
     373             :     FlowMgmtQueue db_event_queue_;
     374             :     static FlowMgmtQueue *log_queue_;
     375             :     DISALLOW_COPY_AND_ASSIGN(FlowMgmtManager);
     376             : };
     377             : 
     378             : #define FLOW_TRACE(obj, ...)\
     379             : do {\
     380             :     Flow##obj::TraceMsg(FlowTraceBuf, __FILE__, __LINE__, ##__VA_ARGS__);\
     381             : } while (false)
     382             : 
     383             : #endif // __AGENT_FLOW_TABLE_MGMT_H__

Generated by: LCOV version 1.14