LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - flow_mgmt.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 412 556 74.1 %
Date: 2026-06-08 02:02:55 Functions: 34 49 69.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include <bitset>
       2             : #include <boost/uuid/uuid_io.hpp>
       3             : #include "cmn/agent.h"
       4             : #include "controller/controller_init.h"
       5             : #include "oper/bgp_as_service.h"
       6             : #include "oper/health_check.h"
       7             : #include "pkt/flow_proto.h"
       8             : #include <pkt/flow_mgmt.h>
       9             : #include <pkt/flow_mgmt/flow_mgmt_entry.h>
      10             : #include <pkt/flow_mgmt/flow_entry_info.h>
      11             : #include <pkt/flow_mgmt/flow_mgmt_request.h>
      12             : #include <pkt/flow_mgmt/flow_mgmt_dbclient.h>
      13             : #include "uve/flow_uve_stats_request.h"
      14             : #include "uve/agent_uve_stats.h"
      15             : #include "vrouter/flow_stats/flow_stats_collector.h"
      16             : 
      17             : FlowMgmtManager::FlowMgmtQueue *FlowMgmtManager::log_queue_;
      18             : /////////////////////////////////////////////////////////////////////////////
      19             : // FlowMgmtManager methods
      20             : /////////////////////////////////////////////////////////////////////////////
      21           1 : FlowMgmtManager::FlowMgmtManager(Agent *agent, uint16_t table_index) :
      22           1 :     agent_(agent),
      23           1 :     table_index_(table_index),
      24           1 :     acl_flow_mgmt_tree_(this),
      25           1 :     interface_flow_mgmt_tree_(this),
      26           1 :     vn_flow_mgmt_tree_(this),
      27           1 :     ip4_route_flow_mgmt_tree_(this),
      28           1 :     ip6_route_flow_mgmt_tree_(this),
      29           1 :     bridge_route_flow_mgmt_tree_(this),
      30           1 :     vrf_flow_mgmt_tree_(this),
      31           1 :     nh_flow_mgmt_tree_(this),
      32           1 :     flow_mgmt_dbclient_(new FlowMgmtDbClient(agent, this)),
      33           1 :     request_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
      34             :                    table_index,
      35             :                    boost::bind(&FlowMgmtManager::RequestHandler, this, _1)),
      36           1 :     db_event_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
      37             :                     table_index,
      38             :                     boost::bind(&FlowMgmtManager::DBRequestHandler, this, _1),
      39           4 :                     db_event_queue_.kMaxSize, 1) {
      40           1 :     request_queue_.set_name("Flow management");
      41           1 :     request_queue_.set_measure_busy_time(agent->MeasureQueueDelay());
      42           1 :     db_event_queue_.set_name("Flow DB Event Queue");
      43           3 :     for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
      44           2 :         bgp_as_a_service_flow_mgmt_tree_[count].reset(
      45           2 :             new BgpAsAServiceFlowMgmtTree(this, count));
      46             :     }
      47           1 : }
      48             : 
      49           1 : void FlowMgmtManager::Init() {
      50           1 :     flow_mgmt_dbclient_->Init();
      51           1 :     agent_->acl_table()->set_ace_flow_sandesh_data_cb
      52           1 :         (boost::bind(&FlowMgmtManager::SetAceSandeshData, this, _1, _2, _3));
      53           1 :     agent_->acl_table()->set_acl_flow_sandesh_data_cb
      54           1 :         (boost::bind(&FlowMgmtManager::SetAclFlowSandeshData, this, _1, _2,
      55             :                      _3));
      56             :     // If BGP service is deleted then flush off all the flows for the VMI.
      57           1 :     agent_->oper_db()->bgp_as_a_service()->RegisterServiceDeleteCb(boost::bind
      58             :                        (&FlowMgmtManager::BgpAsAServiceNotify, this, _1, _2));
      59             :     // If BGP service health check configuration is modified,
      60             :     // update the corresponding flows
      61           1 :     agent_->oper_db()->bgp_as_a_service()->RegisterHealthCheckCb(boost::bind
      62             :                        (&FlowMgmtManager::BgpAsAServiceHealthCheckNotify, this,
      63             :                         _1, _2, _3, _4));
      64             :     // If control node goes off delete all flows frmo its tree.
      65           1 :     agent_->controller()->RegisterControllerChangeCallback(boost::bind
      66             :                           (&FlowMgmtManager::ControllerNotify, this, _1));
      67           1 : }
      68             : 
      69           1 : void FlowMgmtManager::Shutdown() {
      70           1 :     request_queue_.Shutdown();
      71           1 :     db_event_queue_.Shutdown();
      72           1 :     flow_mgmt_dbclient_->Shutdown();
      73           1 : }
      74             : 
      75           1 : void FlowMgmtManager::InitLogQueue(Agent *agent) {
      76           1 :     uint32_t task_id = agent->task_scheduler()->GetTaskId(kTaskFlowLogging);
      77           2 :     log_queue_ = new FlowMgmtQueue(task_id, 0,
      78             :                                    boost::bind(&FlowMgmtManager::LogHandler,
      79           1 :                                                _1));
      80           1 :     log_queue_->set_name("Flow Log Queue");
      81           1 :     log_queue_->SetBounded(true);
      82           1 : }
      83             : 
      84           1 : void FlowMgmtManager::ShutdownLogQueue() {
      85           1 :     log_queue_->Shutdown();
      86           1 :     delete log_queue_;
      87           1 : }
      88             : 
      89             : /////////////////////////////////////////////////////////////////////////////
      90             : // BGP as a service callbacks
      91             : /////////////////////////////////////////////////////////////////////////////
      92           0 : void FlowMgmtManager::BgpAsAServiceNotify(const boost::uuids::uuid &vm_uuid,
      93             :                                           uint32_t source_port) {
      94             :     FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(vm_uuid,
      95           0 :                                                             source_port));
      96           0 :     request_queue_.Enqueue(req);
      97           0 : }
      98             : 
      99           0 : void FlowMgmtManager::BgpAsAServiceHealthCheckNotify(
     100             :                       const boost::uuids::uuid &vm_uuid, uint32_t source_port,
     101             :                       const boost::uuids::uuid &hc_uuid, bool add) {
     102           0 :     BgpAsAServiceFlowMgmtRequest::Type type = add ?
     103             :                         BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_ADD :
     104             :                         BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_DEL;
     105             :     FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(vm_uuid,
     106             :                                                             source_port,
     107           0 :                                                             hc_uuid, type));
     108           0 :     request_queue_.Enqueue(req);
     109           0 : }
     110             : 
     111           2 : void FlowMgmtManager::ControllerNotify(uint8_t index) {
     112           2 :     FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(index));
     113           2 :     request_queue_.Enqueue(req);
     114           2 : }
     115             : 
     116             : /////////////////////////////////////////////////////////////////////////////
     117             : // Introspect routines
     118             : /////////////////////////////////////////////////////////////////////////////
     119           0 : void FlowMgmtManager::SetAceSandeshData(const AclDBEntry *acl,
     120             :                                         AclFlowCountResp &data,
     121             :                                         const std::string &ace_id) {
     122           0 :     AclFlowMgmtKey key(acl, NULL);
     123             :     AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>
     124           0 :         (acl_flow_mgmt_tree_.Find(&key));
     125           0 :     if (entry == NULL) {
     126           0 :         return;
     127             :     }
     128           0 :     entry->FillAceFlowSandeshInfo(acl, data, ace_id);
     129             : 
     130           0 : }
     131             : 
     132           0 : void FlowMgmtManager::SetAclFlowSandeshData(const AclDBEntry *acl,
     133             :                                             AclFlowResp &data,
     134             :                                             const int last_count) {
     135           0 :     AclFlowMgmtKey key(acl, NULL);
     136             :     AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>
     137           0 :         (acl_flow_mgmt_tree_.Find(&key));
     138           0 :     if (entry == NULL) {
     139           0 :         return;
     140             :     }
     141           0 :     entry->FillAclFlowSandeshInfo(acl, data, last_count, agent_);
     142           0 : }
     143             : 
     144             : /////////////////////////////////////////////////////////////////////////////
     145             : // Utility methods to enqueue events into work-queue
     146             : /////////////////////////////////////////////////////////////////////////////
     147         100 : void FlowMgmtManager::AddEvent(FlowEntry *flow) {
     148             :     // Check if there is a flow-mgmt request already pending
     149             :     // Flow mgmt takes care of current state of flow. So, there is no need to
     150             :     // enqueue duplicate requests
     151         100 :     FlowMgmtRequest *req = flow->flow_mgmt_request();
     152         100 :     if (req == NULL) {
     153          50 :         req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
     154          50 :         flow->set_flow_mgmt_request(req);
     155          50 :         request_queue_.Enqueue(FlowMgmtRequestPtr(req));
     156             :     }
     157         100 : }
     158             : 
     159          94 : void FlowMgmtManager::DeleteEvent(FlowEntry *flow,
     160             :                                   const RevFlowDepParams &params) {
     161             :     // Check if there is a flow-mgmt request already pending
     162             :     // Flow mgmt takes care of current state of flow. So, there is no need to
     163             :     // enqueue duplicate requests
     164          94 :     FlowMgmtRequest *req = flow->flow_mgmt_request();
     165          94 :     if (req == NULL) {
     166          94 :         req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
     167          94 :         flow->set_flow_mgmt_request(req);
     168          94 :         request_queue_.Enqueue(FlowMgmtRequestPtr(req));
     169             :     }
     170             : 
     171          94 :     req->set_params(params);
     172          94 : }
     173             : 
     174           0 : void FlowMgmtManager::FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes,
     175             :                                            uint32_t packets,
     176             :                                            uint32_t oflow_bytes,
     177             :                                            const boost::uuids::uuid &u) {
     178           0 :     if (bytes == 0 && packets == 0 && oflow_bytes == 0) {
     179           0 :         return;
     180             :     }
     181             : 
     182             :     /* Ignore StatsUpdate request in TSN mode as we don't export flows */
     183           0 :     if (agent_->tsn_enabled()) {
     184           0 :         return;
     185             :     }
     186             :     FlowMgmtRequestPtr req(new FlowMgmtRequest
     187             :                            (FlowMgmtRequest::UPDATE_FLOW_STATS, flow,
     188           0 :                             bytes, packets, oflow_bytes, u));
     189           0 :     request_queue_.Enqueue(req);
     190           0 : }
     191             : 
     192          24 : void FlowMgmtManager::RetryVrfDeleteEvent(const VrfEntry *vrf) {
     193             :     FlowMgmtRequestPtr req(new FlowMgmtRequest
     194          24 :                            (FlowMgmtRequest::RETRY_DELETE_VRF, vrf, 0));
     195          24 :     request_queue_.Enqueue(req);
     196          24 : }
     197             : 
     198           0 : void FlowMgmtManager::DummyEvent() {
     199           0 :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DUMMY));
     200           0 :     request_queue_.Enqueue(req);
     201           0 : }
     202             : 
     203         408 : void FlowMgmtManager::AddDBEntryEvent(const DBEntry *entry, uint32_t gen_id) {
     204             :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::ADD_DBENTRY,
     205         408 :                                                entry, gen_id));
     206         408 :     db_event_queue_.Enqueue(req);
     207         408 : }
     208             : 
     209          11 : void FlowMgmtManager::ChangeDBEntryEvent(const DBEntry *entry,
     210             :                                          uint32_t gen_id) {
     211             :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::CHANGE_DBENTRY,
     212          11 :                                                entry, gen_id));
     213          11 :     db_event_queue_.Enqueue(req);
     214          11 : }
     215             : 
     216         288 : void FlowMgmtManager::DeleteDBEntryEvent(const DBEntry *entry,
     217             :                                          uint32_t gen_id) {
     218             :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DELETE_DBENTRY,
     219         288 :                                                entry, gen_id));
     220         288 :     db_event_queue_.Enqueue(req);
     221         288 : }
     222             : 
     223           0 : void FlowMgmtManager::RouteNHChangeEvent(const DBEntry *entry,
     224             :                                          uint32_t gen_id) {
     225             :     FlowMgmtRequestPtr req(new FlowMgmtRequest
     226             :                                (FlowMgmtRequest::DELETE_LAYER2_FLOW,
     227           0 :                                 entry, gen_id));
     228           0 :     db_event_queue_.Enqueue(req);
     229           0 : }
     230             : 
     231         426 : void FlowMgmtManager::EnqueueFlowEvent(FlowEvent *event) {
     232         426 :     agent_->pkt()->get_flow_proto()->EnqueueFlowEvent(event);
     233         426 : }
     234             : 
     235           0 : void FlowMgmtManager::NonOperEntryEvent(FlowEvent::Event event,
     236             :                                         FlowEntry *flow) {
     237           0 :     FlowEvent *flow_resp = new FlowEvent(event, flow->key(), true,
     238           0 :                                          FlowTable::kPortNatFlowTableInstance);
     239           0 :     flow_resp->set_flow(flow);
     240           0 :     EnqueueFlowEvent(flow_resp);
     241           0 : }
     242             : 
     243         144 : void FlowMgmtManager::DBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
     244             :                                    FlowEntry *flow) {
     245         144 :     FlowEvent *flow_resp = new FlowEvent(event, NULL, key->db_entry());
     246         144 :     key->KeyToFlowRequest(flow_resp);
     247         144 :     flow_resp->set_flow(flow);
     248         144 :     EnqueueFlowEvent(flow_resp);
     249         144 : }
     250             : 
     251         282 : void FlowMgmtManager::FreeDBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
     252             :                                        uint32_t gen_id) {
     253         282 :     FlowEvent *flow_resp = new FlowEvent(event, table_index_, key->db_entry(),
     254         282 :                                          gen_id);
     255         282 :     EnqueueFlowEvent(flow_resp);
     256         282 : }
     257             : 
     258           0 : void FlowMgmtManager::FlowUpdateQueueDisable(bool disabled) {
     259           0 :     request_queue_.set_disable(disabled);
     260           0 :     db_event_queue_.set_disable(disabled);
     261           0 : }
     262             : 
     263           0 : size_t FlowMgmtManager::FlowUpdateQueueLength() {
     264           0 :     return request_queue_.Length();
     265             : }
     266             : 
     267           0 : size_t FlowMgmtManager::FlowDBQueueLength() {
     268           0 :     return db_event_queue_.Length();
     269             : }
     270             : /////////////////////////////////////////////////////////////////////////////
     271             : // Handlers for events from the work-queue
     272             : /////////////////////////////////////////////////////////////////////////////
     273         707 : bool FlowMgmtManager::ProcessEvent(FlowMgmtRequest *req, FlowMgmtKey *key,
     274             :                                    FlowMgmtTree *tree) {
     275         707 :     InetRouteFlowMgmtTree* itree = dynamic_cast<InetRouteFlowMgmtTree*>(tree);
     276         707 :     switch (req->event()) {
     277         408 :     case FlowMgmtRequest::ADD_DBENTRY:
     278         408 :         tree->OperEntryAdd(req, key);
     279         408 :         break;
     280             : 
     281          11 :     case FlowMgmtRequest::CHANGE_DBENTRY:
     282          11 :         tree->OperEntryChange(req, key);
     283          11 :         break;
     284             : 
     285         288 :     case FlowMgmtRequest::DELETE_DBENTRY:
     286             :     case FlowMgmtRequest::IMPLICIT_ROUTE_DELETE:
     287         288 :         tree->OperEntryDelete(req, key);
     288         288 :         break;
     289             : 
     290           0 :     case FlowMgmtRequest::DELETE_LAYER2_FLOW:
     291           0 :         assert(itree);
     292           0 :         itree->RouteNHChangeEvent(req, key);
     293           0 :         break;
     294             : 
     295           0 :     default:
     296           0 :         assert(0);
     297             :         break;
     298             :     }
     299             : 
     300         707 :     return true;
     301             : }
     302             : 
     303         707 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequest *req,
     304             :                                        const DBEntry *entry) {
     305         707 :     const Interface *intf = dynamic_cast<const Interface *>(entry);
     306         707 :     if (intf) {
     307          68 :         InterfaceFlowMgmtKey key(intf);
     308          68 :         return ProcessEvent(req, &key, &interface_flow_mgmt_tree_);
     309          68 :     }
     310             : 
     311         639 :     const VnEntry *vn = dynamic_cast<const VnEntry *>(entry);
     312         639 :     if (vn) {
     313          12 :         VnFlowMgmtKey key(vn);
     314          12 :         return ProcessEvent(req, &key, &vn_flow_mgmt_tree_);
     315          12 :     }
     316             : 
     317         627 :     const AclDBEntry *acl = dynamic_cast<const AclDBEntry *>(entry);
     318         627 :     if (acl) {
     319          10 :         AclFlowMgmtKey key(acl, NULL);
     320          10 :         return ProcessEvent(req, &key, &acl_flow_mgmt_tree_);
     321          10 :     }
     322             : 
     323         617 :     const NextHop *nh = dynamic_cast<const NextHop *>(entry);
     324         617 :     if (nh) {
     325         260 :         NhFlowMgmtKey key(static_cast<const NextHop *>(req->db_entry()));
     326         260 :         return ProcessEvent(req, &key, &nh_flow_mgmt_tree_);
     327         260 :     }
     328             : 
     329             :     const InetUnicastRouteEntry *inet_uc_rt =
     330         357 :         dynamic_cast<const InetUnicastRouteEntry *>(entry);
     331         357 :     if (inet_uc_rt) {
     332         192 :         InetRouteFlowMgmtKey key(inet_uc_rt);
     333         192 :         if (inet_uc_rt->prefix_address().is_v4()) {
     334         126 :             return ProcessEvent(req, &key, &ip4_route_flow_mgmt_tree_);
     335             :         }
     336          66 :         if (inet_uc_rt->prefix_address().is_v6()) {
     337          66 :             return ProcessEvent(req, &key, &ip6_route_flow_mgmt_tree_);
     338             :         }
     339         192 :     }
     340             : 
     341             :     const BridgeRouteEntry *bridge =
     342         165 :         dynamic_cast<const BridgeRouteEntry *>(entry);
     343         165 :     if (bridge) {
     344         143 :         BridgeRouteFlowMgmtKey key(bridge);
     345         143 :         return ProcessEvent(req, &key, &bridge_route_flow_mgmt_tree_);
     346         143 :     }
     347             : 
     348          22 :     const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(entry);
     349          22 :     if (vrf) {
     350          22 :         VrfFlowMgmtKey key(vrf);
     351          22 :         return ProcessEvent(req, &key, &vrf_flow_mgmt_tree_);
     352          22 :     }
     353             : 
     354           0 :     assert(0);
     355             :     return true;
     356             : }
     357             : 
     358             : bool
     359           2 : FlowMgmtManager::BgpAsAServiceRequestHandler(FlowMgmtRequest *req) {
     360             : 
     361             :     BgpAsAServiceFlowMgmtRequest *bgp_as_a_service_request =
     362           2 :         dynamic_cast<BgpAsAServiceFlowMgmtRequest *>(req);
     363           2 :     if (bgp_as_a_service_request->type() == BgpAsAServiceFlowMgmtRequest::VMI) {
     364             :         //Delete it for for all CN trees
     365           0 :         for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
     366             :             BgpAsAServiceFlowMgmtKey key(bgp_as_a_service_request->vm_uuid(),
     367             :                                          bgp_as_a_service_request->source_port(),
     368           0 :                                          count, NULL, NULL);
     369           0 :             bgp_as_a_service_flow_mgmt_tree_[count].get()->
     370           0 :                 BgpAsAServiceDelete(key, req);
     371           0 :         }
     372           2 :     } else if (bgp_as_a_service_request->type() ==
     373             :                BgpAsAServiceFlowMgmtRequest::CONTROLLER) {
     374           2 :         bgp_as_a_service_flow_mgmt_tree_[bgp_as_a_service_request->index()].get()->
     375           2 :             DeleteAll();
     376           0 :     } else if (bgp_as_a_service_request->type() ==
     377           0 :                BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_ADD ||
     378           0 :                bgp_as_a_service_request->type() ==
     379             :                BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_DEL) {
     380             :         // Health check added to BGPaaS, check if any flows are impacted
     381           0 :         for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
     382             :             BgpAsAServiceFlowMgmtKey key(bgp_as_a_service_request->vm_uuid(),
     383             :                                          bgp_as_a_service_request->source_port(),
     384           0 :                                          count, NULL, NULL);
     385           0 :             bgp_as_a_service_flow_mgmt_tree_[count].get()->
     386           0 :                 BgpAsAServiceHealthCheckUpdate(agent(), key, bgp_as_a_service_request);
     387           0 :         }
     388             :     }
     389             : 
     390           2 :     return true;
     391             : }
     392             : 
     393         170 : bool FlowMgmtManager::RequestHandler(FlowMgmtRequestPtr req) {
     394         170 :     switch (req->event()) {
     395         144 :     case FlowMgmtRequest::UPDATE_FLOW: {
     396         144 :         FlowEntry *flow = req->flow().get();
     397             :         // Before processing event, set the request pointer in flow to
     398             :         // NULL. This ensures flow-entry enqueues new request from now
     399             :         // onwards
     400         144 :         std::scoped_lock mutex(flow->mutex());
     401         144 :         flow->set_flow_mgmt_request(NULL);
     402             : 
     403             :         // Update flow-mgmt information based on flow-state
     404         144 :         if (flow->deleted() == false) {
     405             :             FlowMgmtRequestPtr log_req(new FlowMgmtRequest
     406             :                                        (FlowMgmtRequest::ADD_FLOW,
     407         100 :                                         req->flow().get()));
     408         100 :             log_queue_->Enqueue(log_req);
     409             : 
     410             :             //Enqueue Add request to flow-stats-collector
     411         100 :             agent_->flow_stats_manager()->AddEvent(req->flow());
     412             : 
     413             :             //Enqueue Add request to UVE module for ACE stats
     414         100 :             EnqueueUveAddEvent(flow);
     415             : 
     416         100 :             AddFlow(req->flow());
     417             : 
     418         100 :         } else {
     419             :             FlowMgmtRequestPtr log_req(new FlowMgmtRequest
     420             :                                        (FlowMgmtRequest::DELETE_FLOW,
     421          44 :                                         req->flow().get(), req->params()));
     422          44 :             log_queue_->Enqueue(log_req);
     423             : 
     424             :             //Enqueue Delete request to flow-stats-collector
     425          44 :             agent_->flow_stats_manager()->DeleteEvent(flow, req->params());
     426             : 
     427             :             //Enqueue Delete request to UVE module for ACE stats
     428          44 :             EnqueueUveDeleteEvent(flow);
     429             : 
     430          44 :             DeleteFlow(req->flow(), req->params());
     431          44 :         }
     432         144 :         break;
     433         144 :     }
     434             : 
     435           0 :     case FlowMgmtRequest::UPDATE_FLOW_STATS: {
     436             :         //Handle Flow stats update for flow-mgmt
     437           0 :         UpdateFlowStats(req->flow(), req->bytes(), req->packets(),
     438           0 :                         req->oflow_bytes(), req->flow_uuid());
     439           0 :         break;
     440             :     }
     441             : 
     442          24 :     case FlowMgmtRequest::RETRY_DELETE_VRF: {
     443          24 :         RetryVrfDelete(req->vrf_id());
     444          24 :         break;
     445             :     }
     446             : 
     447           2 :     case FlowMgmtRequest::DELETE_BGP_AAS_FLOWS: {
     448           2 :         BgpAsAServiceRequestHandler(req.get());
     449           2 :         break;
     450             :     }
     451             : 
     452           0 :     case FlowMgmtRequest::DUMMY:
     453           0 :         break;
     454             : 
     455           0 :     default:
     456           0 :          assert(0);
     457             : 
     458             :     }
     459             : 
     460         170 :     return true;
     461             : }
     462             : 
     463         707 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequestPtr req) {
     464         707 :     switch (req->event()) {
     465         707 :     case FlowMgmtRequest::ADD_DBENTRY:
     466             :     case FlowMgmtRequest::CHANGE_DBENTRY:
     467             :     case FlowMgmtRequest::DELETE_DBENTRY:
     468             :     case FlowMgmtRequest::DELETE_LAYER2_FLOW: {
     469         707 :         DBRequestHandler(req.get(), req->db_entry());
     470         707 :         break;
     471             :     }
     472             : 
     473           0 :     default:
     474           0 :          assert(0);
     475             : 
     476             :     }
     477             : 
     478         707 :     return true;
     479             : }
     480             : 
     481         144 : bool FlowMgmtManager::LogHandler(FlowMgmtRequestPtr req) {
     482         144 :     FlowEntry *flow = req->flow().get();
     483         144 :     FlowEntry *rflow = flow->reverse_flow_entry();
     484             : 
     485         188 :     FLOW_LOCK(flow, rflow, FlowEvent::FLOW_MESSAGE);
     486         144 :     switch (req->event()) {
     487         100 :     case FlowMgmtRequest::ADD_FLOW: {
     488         100 :         LogFlowUnlocked(flow, "ADD");
     489         100 :         break;
     490             :     }
     491             : 
     492          44 :     case FlowMgmtRequest::DELETE_FLOW: {
     493          44 :         LogFlowUnlocked(flow, "DEL");
     494          44 :         break;
     495             :     }
     496             : 
     497           0 :     default:
     498           0 :          assert(0);
     499             : 
     500             :     }
     501             : 
     502         144 :     return true;
     503         144 : }
     504             : 
     505         201 : void FlowMgmtManager::RetryVrfDelete(uint32_t vrf_id) {
     506         201 :     vrf_flow_mgmt_tree_.RetryDelete(vrf_id);
     507         201 : }
     508             : 
     509             : // Extract all the FlowMgmtKey for a flow
     510         144 : void FlowMgmtManager::LogFlowUnlocked(FlowEntry *flow, const std::string &op) {
     511         144 :     if (flow->trace() == false)
     512          70 :         return;
     513          74 :     FlowInfo trace;
     514          74 :     flow->FillFlowInfo(trace);
     515          74 :     FLOW_TRACE(Trace, op, trace);
     516          74 : }
     517             : 
     518             : // Extract all the FlowMgmtKey for a flow
     519         100 : void FlowMgmtManager::MakeFlowMgmtKeyTree(FlowEntry *flow,
     520             :                                           FlowMgmtKeyTree *tree) {
     521         100 :     acl_flow_mgmt_tree_.ExtractKeys(flow, tree);
     522         100 :     interface_flow_mgmt_tree_.ExtractKeys(flow, tree);
     523         100 :     vn_flow_mgmt_tree_.ExtractKeys(flow, tree);
     524         100 :     ip4_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
     525         100 :     ip6_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
     526         100 :     bridge_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
     527         100 :     nh_flow_mgmt_tree_.ExtractKeys(flow, tree);
     528         100 :     if (flow->is_flags_set(FlowEntry::BgpRouterService)) {
     529           0 :         int cn_index = BgpAsAServiceFlowMgmtTree::GetCNIndex(flow);
     530           0 :         if (cn_index != BgpAsAServiceFlowMgmtTree::kInvalidCnIndex) {
     531           0 :             bgp_as_a_service_flow_mgmt_tree_[cn_index].get()->
     532           0 :                 ExtractKeys(flow, tree);
     533             :         }
     534             :     }
     535         100 : }
     536             : 
     537         100 : void FlowMgmtManager::EnqueueUveAddEvent(const FlowEntry *flow) const {
     538         100 :     AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
     539         100 :     if (uve) {
     540         100 :         const Interface *itf = flow->intf_entry();
     541         100 :         const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
     542         100 :         const VnEntry *vn = flow->vn_entry();
     543         100 :         string vn_name = vn? vn->GetName() : "";
     544         100 :         string itf_name = vmi? vmi->cfg_name() : "";
     545         100 :         FlowUveVnAcePolicyInfo vn_ace_info;
     546         100 :         FlowUveFwPolicyInfo fw_policy_info;
     547             : 
     548         100 :         flow->FillUveVnAceInfo(&vn_ace_info);
     549         100 :         if (!itf_name.empty()) {
     550         100 :             flow->FillUveFwStatsInfo(&fw_policy_info, true);
     551             :         }
     552             :         boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
     553         100 :             (FlowUveStatsRequest::ADD_FLOW, flow->uuid(), itf_name,
     554         100 :              flow->sg_rule_uuid(), vn_ace_info, fw_policy_info));
     555             : 
     556         100 :         if (!req->sg_info_valid() && !req->vn_ace_valid() &&
     557           0 :             !req->fw_policy_valid()) {
     558           0 :             return;
     559             :         }
     560             : 
     561         100 :         uve->stats_manager()->EnqueueEvent(req);
     562         100 :     }
     563             : }
     564             : 
     565          44 : void FlowMgmtManager::EnqueueUveDeleteEvent(const FlowEntry *flow) const {
     566          44 :     AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
     567          44 :     if (uve) {
     568          44 :         const Interface *itf = flow->intf_entry();
     569          44 :         const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
     570          44 :         string itf_name = vmi? vmi->cfg_name() : "";
     571          44 :         FlowUveFwPolicyInfo fw_policy_info;
     572          44 :         if (!itf_name.empty()) {
     573           7 :             flow->FillUveFwStatsInfo(&fw_policy_info, false);
     574             :         }
     575             :         boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
     576          44 :             (FlowUveStatsRequest::DELETE_FLOW, flow->uuid(), itf_name,
     577          44 :              fw_policy_info));
     578          44 :         uve->stats_manager()->EnqueueEvent(req);
     579          44 :     }
     580          44 : }
     581             : 
     582         100 : void FlowMgmtManager::AddFlow(FlowEntryPtr &flow) {
     583         100 :     FlowMgmtKeyTree new_tree;
     584         100 :     MakeFlowMgmtKeyTree(flow.get(), &new_tree);
     585             : 
     586             :     // Get old FlowMgmtKeyTree
     587         100 :     FlowEntryInfo *old_info = LocateFlowEntryInfo(flow);
     588         100 :     FlowMgmtKeyTree *old_tree = &old_info->tree_;
     589         100 :     assert(old_tree);
     590         100 :     old_info->count_++;
     591             : 
     592             :     // Apply the difference in old and new key tree
     593         100 :     FlowMgmtKeyTree::iterator new_it = new_tree.begin();
     594         100 :     FlowMgmtKeyTree::iterator old_it = old_tree->begin();
     595             : 
     596         398 :     while (new_it != new_tree.end() && old_it != old_tree->end()) {
     597         298 :         FlowMgmtKey *new_key = new_it->first;
     598         298 :         FlowMgmtKey *old_key = old_it->first;
     599         298 :         if (new_key->IsLess(old_key)) {
     600           6 :             AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
     601           6 :             new_it++;
     602         292 :         } else if (old_key->IsLess(new_key)) {
     603          20 :             FlowMgmtKeyNode *node = old_it->second;
     604          20 :             DeleteFlowMgmtKey(flow.get(), old_info, old_key,
     605             :                               node);
     606          20 :             FlowMgmtKeyTree::iterator tmp = old_it++;
     607          20 :             FlowMgmtKey *key = tmp->first;
     608          20 :             old_tree->erase(tmp);
     609          20 :             delete key;
     610          20 :             delete node;
     611             :         } else {
     612         272 :             AddFlowMgmtKey(flow.get(), old_info, new_key, old_key);
     613         272 :             old_it++;
     614         272 :             new_it++;
     615             :         }
     616             :     }
     617             : 
     618         307 :     while (new_it != new_tree.end()) {
     619         207 :         FlowMgmtKey *new_key = new_it->first;
     620         207 :         AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
     621         207 :         new_it++;
     622             :     }
     623             : 
     624         113 :     while (old_it != old_tree->end()) {
     625          13 :         FlowMgmtKey *old_key = old_it->first;
     626          13 :         FlowMgmtKeyNode *node = old_it->second;
     627          13 :         DeleteFlowMgmtKey(flow.get(), old_info, old_key, node);
     628          13 :         FlowMgmtKeyTree::iterator tmp = old_it++;
     629          13 :         FlowMgmtKey *key = tmp->first;
     630          13 :         old_tree->erase(tmp);
     631          13 :         delete key;
     632          13 :         delete node;
     633             :     }
     634             : 
     635         100 :     new_it = new_tree.begin();
     636         585 :     while (new_it != new_tree.end()) {
     637         485 :         FlowMgmtKeyTree::iterator tmp = new_it++;
     638         485 :         FlowMgmtKey *key = tmp->first;
     639         485 :         FlowMgmtKeyNode *node = tmp->second;
     640         485 :         new_tree.erase(tmp);
     641         485 :         delete key;
     642         485 :         delete node;
     643             :     }
     644         100 : }
     645             : 
     646          44 : void FlowMgmtManager::DeleteFlow(FlowEntryPtr &flow,
     647             :                                  const RevFlowDepParams &params) {
     648             :     // Delete entries for flow from the tree
     649          44 :     FlowEntryInfo *old_info = FindFlowEntryInfo(flow);
     650          44 :     if (old_info == NULL)
     651           0 :         return;
     652             : 
     653          44 :     FlowMgmtKeyTree *old_tree = &old_info->tree_;
     654          44 :     assert(old_tree);
     655          44 :     old_info->count_++;
     656             : 
     657          44 :     FlowMgmtKeyTree::iterator old_it = old_tree->begin();
     658         224 :     while (old_it != old_tree->end()) {
     659         180 :         FlowMgmtKeyNode *node = old_it->second;
     660         180 :         DeleteFlowMgmtKey(flow.get(), old_info, old_it->first, node);
     661         180 :         FlowMgmtKeyTree::iterator tmp = old_it++;
     662         180 :         FlowMgmtKey *key = tmp->first;
     663         180 :         old_tree->erase(tmp);
     664         180 :         delete key;
     665         180 :         delete node;
     666             :     }
     667             : 
     668          44 :     assert(old_tree->size() == 0);
     669          44 :     DeleteFlowEntryInfo(flow);
     670             : }
     671             : 
     672           0 : void FlowMgmtManager::UpdateFlowStats(FlowEntryPtr &flow, uint32_t bytes,
     673             :                                       uint32_t packets, uint32_t oflow_bytes,
     674             :                                       const boost::uuids::uuid &u) {
     675             :     //Enqueue Flow Index Update Event request to flow-stats-collector
     676           0 :     agent_->flow_stats_manager()->UpdateStatsEvent(flow, bytes, packets,
     677             :                                                    oflow_bytes, u);
     678           0 : }
     679             : 
     680           8 : bool FlowMgmtManager::HasVrfFlows(uint32_t vrf_id) {
     681           8 :     if (ip4_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET4_UNICAST)) {
     682           0 :         return true;
     683             :     }
     684             : 
     685           8 :     if (ip6_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET6_UNICAST)) {
     686           0 :         return true;
     687             :     }
     688             : 
     689           8 :     if (bridge_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::BRIDGE)) {
     690           0 :         return true;
     691             :     }
     692             : 
     693           8 :     return false;
     694             : }
     695             : 
     696           0 : void FlowMgmtManager::VnFlowCounters(const VnEntry *vn, uint32_t *ingress_flow_count,
     697             :                                      uint32_t *egress_flow_count) {
     698           0 :     vn_flow_mgmt_tree_.VnFlowCounters(vn, ingress_flow_count,
     699             :                                       egress_flow_count);
     700           0 : }
     701             : 
     702           0 : void FlowMgmtManager::InterfaceFlowCount(const Interface *itf,
     703             :                                          uint64_t *created, uint64_t *aged,
     704             :                                          uint32_t *active_flows) {
     705           0 :     interface_flow_mgmt_tree_.InterfaceFlowCount(itf, created, aged,
     706             :                                                  active_flows);
     707           0 : }
     708             : 
     709             : FlowEntryInfo *
     710         144 : FlowMgmtManager::FindFlowEntryInfo(const FlowEntryPtr &flow) {
     711         144 :     return flow->flow_mgmt_info();
     712             : }
     713             : 
     714             : FlowEntryInfo *
     715         100 : FlowMgmtManager::LocateFlowEntryInfo(FlowEntryPtr &flow) {
     716         100 :     FlowEntryInfo *info = FindFlowEntryInfo(flow);
     717         100 :     if (info != NULL)
     718          56 :         return info;
     719          44 :     info = new FlowEntryInfo(flow.get());
     720          44 :     flow->set_flow_mgmt_info(info);
     721          44 :     return info;
     722             : }
     723             : 
     724             : BgpAsAServiceFlowMgmtKey *
     725           0 : FlowMgmtManager::FindBgpAsAServiceInfo(FlowEntry *flow,
     726             :                                        BgpAsAServiceFlowMgmtKey &key) {
     727           0 :     FlowEntryInfo *flow_info = FindFlowEntryInfo(flow);
     728           0 :     if (flow_info == NULL)
     729           0 :         return NULL;
     730             : 
     731           0 :     FlowMgmtKeyTree::iterator key_it = flow_info->tree_.find(&key);
     732           0 :     if (key_it == flow_info->tree().end())
     733           0 :         return NULL;
     734             : 
     735             :     BgpAsAServiceFlowMgmtKey *bkey =
     736           0 :         static_cast<BgpAsAServiceFlowMgmtKey *>(key_it->first);
     737           0 :     return bkey;
     738             : }
     739             : 
     740          44 : void FlowMgmtManager::DeleteFlowEntryInfo(FlowEntryPtr &flow) {
     741          44 :     FlowEntryInfo *info = flow->flow_mgmt_info();
     742          44 :     if (info == NULL)
     743           0 :         return;
     744             : 
     745          44 :     assert(info->tree_.size() == 0);
     746          44 :     flow->set_flow_mgmt_info(NULL);
     747          44 :     return;
     748             : }
     749             : 
     750             : /////////////////////////////////////////////////////////////////////////////
     751             : // Routines to add/delete Flow and FlowMgmtKey in different trees
     752             : /////////////////////////////////////////////////////////////////////////////
     753             : 
     754             : // Add a FlowMgmtKey into FlowMgmtKeyTree for an object
     755             : // The FlowMgmtKeyTree for object is passed as argument
     756         485 : void FlowMgmtManager::AddFlowMgmtKey(FlowEntry *flow, FlowEntryInfo *info,
     757             :                                      FlowMgmtKey *key, FlowMgmtKey *old_key) {
     758         485 :     FlowMgmtKey *tmp = key->Clone();
     759         485 :     FlowMgmtKeyNode *node = new FlowMgmtKeyNode(flow);
     760             : 
     761         485 :     std::pair<FlowMgmtKeyTree::iterator, bool> ret = info->tree_.insert(
     762         485 :                                                      make_pair(tmp, node));
     763         485 :     if (ret.second == false) {
     764         272 :         delete tmp;
     765         272 :         delete node;
     766         272 :         if (key->type() == FlowMgmtKey::ACL) {
     767             :             /* Copy the ACE Id list to existing key from new Key */
     768          25 :             FlowMgmtKey *existing_key = ret.first->first;
     769          25 :             AclFlowMgmtKey *akey = static_cast<AclFlowMgmtKey *>(existing_key);
     770          25 :             AclFlowMgmtKey *new_key = static_cast<AclFlowMgmtKey *>(key);
     771          25 :             akey->set_ace_id_list(new_key->ace_id_list());
     772             :         }
     773             :     }
     774             : 
     775         485 :     switch (key->type()) {
     776         100 :     case FlowMgmtKey::INTERFACE:
     777         100 :         interface_flow_mgmt_tree_.Add(key, flow,
     778         100 :                                       (ret.second)? node : NULL);
     779         100 :         break;
     780             : 
     781          32 :     case FlowMgmtKey::ACL:
     782          32 :         acl_flow_mgmt_tree_.Add(key, flow, old_key,
     783          32 :                                 (ret.second)? node : NULL);
     784          32 :         break;
     785             : 
     786         100 :     case FlowMgmtKey::VN: {
     787         100 :         bool new_flow = vn_flow_mgmt_tree_.Add(key, flow,
     788         100 :                                                (ret.second)? node : NULL);
     789             :         VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
     790         100 :             (vn_flow_mgmt_tree_.Find(key));
     791         100 :         entry->UpdateCounterOnAdd(flow, new_flow, info->local_flow_,
     792         100 :                                   info->ingress_);
     793         100 :         info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
     794         100 :         info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
     795         100 :         break;
     796             :     }
     797             : 
     798         101 :     case FlowMgmtKey::INET4:
     799         101 :         ip4_route_flow_mgmt_tree_.Add(key, flow,
     800         101 :                                       (ret.second)? node : NULL);
     801         101 :         break;
     802             : 
     803           0 :     case FlowMgmtKey::INET6:
     804           0 :         ip6_route_flow_mgmt_tree_.Add(key, flow,
     805           0 :                                       (ret.second)? node : NULL);
     806           0 :         break;
     807             : 
     808          62 :     case FlowMgmtKey::BRIDGE:
     809          62 :         bridge_route_flow_mgmt_tree_.Add(key, flow,
     810          62 :                                          (ret.second)? node : NULL);
     811          62 :         break;
     812             : 
     813          90 :     case FlowMgmtKey::NH:
     814          90 :         nh_flow_mgmt_tree_.Add(key, flow,
     815          90 :                                (ret.second)? node : NULL);
     816          90 :         break;
     817             : 
     818           0 :     case FlowMgmtKey::BGPASASERVICE: {
     819           0 :         BgpAsAServiceFlowMgmtKey *bgp_service_key =
     820             :             static_cast<BgpAsAServiceFlowMgmtKey *>(key);
     821           0 :         int cn_index = bgp_service_key->cn_index();
     822           0 :         if (cn_index != BgpAsAServiceFlowMgmtTree::kInvalidCnIndex) {
     823           0 :             bgp_as_a_service_flow_mgmt_tree_[cn_index].get()->Add(key, flow,
     824           0 :                                                   (ret.second)? node : NULL);
     825             :             boost::uuids::uuid hc_uuid;
     826           0 :             if (agent()->oper_db()->bgp_as_a_service()->GetBgpHealthCheck(
     827           0 :                 static_cast<const VmInterface *>(flow->intf_entry()), &hc_uuid)) {
     828           0 :                 FlowMgmtKey *inserted_key = ret.first->first;
     829           0 :                 BgpAsAServiceFlowMgmtKey *bkey =
     830             :                     static_cast<BgpAsAServiceFlowMgmtKey *>(inserted_key);
     831           0 :                 bkey->StartHealthCheck(agent(), flow, hc_uuid);
     832             :             }
     833             :         }
     834           0 :         break;
     835             :     }
     836             : 
     837           0 :     default:
     838           0 :         assert(0);
     839             :     }
     840         485 : }
     841             : 
     842             : // Delete a FlowMgmtKey from FlowMgmtKeyTree for an object
     843             : // The FlowMgmtKeyTree for object is passed as argument
     844         213 : void FlowMgmtManager::DeleteFlowMgmtKey(
     845             :     FlowEntry *flow, FlowEntryInfo *info, FlowMgmtKey *key,
     846             :     FlowMgmtKeyNode *node) {
     847             : 
     848         213 :     FlowMgmtKeyTree::iterator it = info->tree_.find(key);
     849         213 :     assert(it != info->tree_.end());
     850             : 
     851         213 :     switch (key->type()) {
     852          44 :     case FlowMgmtKey::INTERFACE:
     853          44 :         interface_flow_mgmt_tree_.Delete(key, flow, node);
     854          44 :         break;
     855             : 
     856           7 :     case FlowMgmtKey::ACL:
     857           7 :         acl_flow_mgmt_tree_.Delete(key, flow, node);
     858           7 :         break;
     859             : 
     860          44 :     case FlowMgmtKey::VN: {
     861          44 :         vn_flow_mgmt_tree_.Delete(key, flow, node);
     862             :         VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
     863          44 :             (vn_flow_mgmt_tree_.Find(key));
     864          44 :         if (entry)
     865          44 :             entry->UpdateCounterOnDel(flow, info->local_flow_, info->ingress_);
     866          44 :         info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
     867          44 :         info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
     868          44 :         break;
     869             :     }
     870             : 
     871          44 :     case FlowMgmtKey::INET4:
     872          44 :         ip4_route_flow_mgmt_tree_.Delete(key, flow, node);
     873          44 :         break;
     874             : 
     875           0 :     case FlowMgmtKey::INET6:
     876           0 :         ip6_route_flow_mgmt_tree_.Delete(key, flow, node);
     877           0 :         break;
     878             : 
     879          28 :     case FlowMgmtKey::BRIDGE:
     880          28 :         bridge_route_flow_mgmt_tree_.Delete(key, flow, node);
     881          28 :         break;
     882             : 
     883          46 :     case FlowMgmtKey::NH:
     884          46 :         nh_flow_mgmt_tree_.Delete(key, flow, node);
     885          46 :         break;
     886             : 
     887           0 :     case FlowMgmtKey::BGPASASERVICE: {
     888             :         BgpAsAServiceFlowMgmtKey *bkey =
     889           0 :             static_cast<BgpAsAServiceFlowMgmtKey *>(it->first);
     890           0 :         bkey->StopHealthCheck(flow);
     891           0 :         BgpAsAServiceFlowMgmtKey *bgp_service_key =
     892             :             static_cast<BgpAsAServiceFlowMgmtKey *>(key);
     893           0 :         uint8_t count = bgp_service_key->cn_index();
     894           0 :         bgp_as_a_service_flow_mgmt_tree_[count].get()->Delete(key, flow, node);
     895           0 :         break;
     896             :     }
     897             : 
     898           0 :     default:
     899           0 :         assert(0);
     900             :     }
     901         213 : }

Generated by: LCOV version 1.14