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: 424 556 76.3 %
Date: 2026-08-17 02:09:53 Functions: 36 49 73.5 %
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           4 : FlowMgmtManager::FlowMgmtManager(Agent *agent, uint16_t table_index) :
      22           4 :     agent_(agent),
      23           4 :     table_index_(table_index),
      24           4 :     acl_flow_mgmt_tree_(this),
      25           4 :     interface_flow_mgmt_tree_(this),
      26           4 :     vn_flow_mgmt_tree_(this),
      27           4 :     ip4_route_flow_mgmt_tree_(this),
      28           4 :     ip6_route_flow_mgmt_tree_(this),
      29           4 :     bridge_route_flow_mgmt_tree_(this),
      30           4 :     vrf_flow_mgmt_tree_(this),
      31           4 :     nh_flow_mgmt_tree_(this),
      32           4 :     flow_mgmt_dbclient_(new FlowMgmtDbClient(agent, this)),
      33           4 :     request_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
      34             :                    table_index,
      35             :                    boost::bind(&FlowMgmtManager::RequestHandler, this, _1)),
      36           4 :     db_event_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
      37             :                     table_index,
      38             :                     boost::bind(&FlowMgmtManager::DBRequestHandler, this, _1),
      39          16 :                     db_event_queue_.kMaxSize, 1) {
      40           4 :     request_queue_.set_name("Flow management");
      41           4 :     request_queue_.set_measure_busy_time(agent->MeasureQueueDelay());
      42           4 :     db_event_queue_.set_name("Flow DB Event Queue");
      43          12 :     for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
      44           8 :         bgp_as_a_service_flow_mgmt_tree_[count].reset(
      45           8 :             new BgpAsAServiceFlowMgmtTree(this, count));
      46             :     }
      47           4 : }
      48             : 
      49           4 : void FlowMgmtManager::Init() {
      50           4 :     flow_mgmt_dbclient_->Init();
      51           4 :     agent_->acl_table()->set_ace_flow_sandesh_data_cb
      52           4 :         (boost::bind(&FlowMgmtManager::SetAceSandeshData, this, _1, _2, _3));
      53           4 :     agent_->acl_table()->set_acl_flow_sandesh_data_cb
      54           4 :         (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           4 :     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           4 :     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           4 :     agent_->controller()->RegisterControllerChangeCallback(boost::bind
      66             :                           (&FlowMgmtManager::ControllerNotify, this, _1));
      67           4 : }
      68             : 
      69           4 : void FlowMgmtManager::Shutdown() {
      70           4 :     request_queue_.Shutdown();
      71           4 :     db_event_queue_.Shutdown();
      72           4 :     flow_mgmt_dbclient_->Shutdown();
      73           4 : }
      74             : 
      75           4 : void FlowMgmtManager::InitLogQueue(Agent *agent) {
      76           4 :     uint32_t task_id = agent->task_scheduler()->GetTaskId(kTaskFlowLogging);
      77           8 :     log_queue_ = new FlowMgmtQueue(task_id, 0,
      78             :                                    boost::bind(&FlowMgmtManager::LogHandler,
      79           4 :                                                _1));
      80           4 :     log_queue_->set_name("Flow Log Queue");
      81           4 :     log_queue_->SetBounded(true);
      82           4 : }
      83             : 
      84           4 : void FlowMgmtManager::ShutdownLogQueue() {
      85           4 :     log_queue_->Shutdown();
      86           4 :     delete log_queue_;
      87           4 : }
      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         142 : void FlowMgmtManager::ControllerNotify(uint8_t index) {
     112         142 :     FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(index));
     113         142 :     request_queue_.Enqueue(req);
     114         142 : }
     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         214 : 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         214 :     FlowMgmtRequest *req = flow->flow_mgmt_request();
     152         214 :     if (req == NULL) {
     153         153 :         req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
     154         153 :         flow->set_flow_mgmt_request(req);
     155         153 :         request_queue_.Enqueue(FlowMgmtRequestPtr(req));
     156             :     }
     157         214 : }
     158             : 
     159         208 : 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         208 :     FlowMgmtRequest *req = flow->flow_mgmt_request();
     165         208 :     if (req == NULL) {
     166         206 :         req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
     167         206 :         flow->set_flow_mgmt_request(req);
     168         206 :         request_queue_.Enqueue(FlowMgmtRequestPtr(req));
     169             :     }
     170             : 
     171         208 :     req->set_params(params);
     172         208 : }
     173             : 
     174          30 : void FlowMgmtManager::FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes,
     175             :                                            uint32_t packets,
     176             :                                            uint32_t oflow_bytes,
     177             :                                            const boost::uuids::uuid &u) {
     178          30 :     if (bytes == 0 && packets == 0 && oflow_bytes == 0) {
     179          30 :         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         528 : void FlowMgmtManager::RetryVrfDeleteEvent(const VrfEntry *vrf) {
     193             :     FlowMgmtRequestPtr req(new FlowMgmtRequest
     194         528 :                            (FlowMgmtRequest::RETRY_DELETE_VRF, vrf, 0));
     195         528 :     request_queue_.Enqueue(req);
     196         528 : }
     197             : 
     198           0 : void FlowMgmtManager::DummyEvent() {
     199           0 :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DUMMY));
     200           0 :     request_queue_.Enqueue(req);
     201           0 : }
     202             : 
     203       19966 : void FlowMgmtManager::AddDBEntryEvent(const DBEntry *entry, uint32_t gen_id) {
     204             :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::ADD_DBENTRY,
     205       19966 :                                                entry, gen_id));
     206       19966 :     db_event_queue_.Enqueue(req);
     207       19966 : }
     208             : 
     209          10 : void FlowMgmtManager::ChangeDBEntryEvent(const DBEntry *entry,
     210             :                                          uint32_t gen_id) {
     211             :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::CHANGE_DBENTRY,
     212          10 :                                                entry, gen_id));
     213          10 :     db_event_queue_.Enqueue(req);
     214          10 : }
     215             : 
     216       15800 : void FlowMgmtManager::DeleteDBEntryEvent(const DBEntry *entry,
     217             :                                          uint32_t gen_id) {
     218             :     FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DELETE_DBENTRY,
     219       15800 :                                                entry, gen_id));
     220       15800 :     db_event_queue_.Enqueue(req);
     221       15800 : }
     222             : 
     223          20 : void FlowMgmtManager::RouteNHChangeEvent(const DBEntry *entry,
     224             :                                          uint32_t gen_id) {
     225             :     FlowMgmtRequestPtr req(new FlowMgmtRequest
     226             :                                (FlowMgmtRequest::DELETE_LAYER2_FLOW,
     227          20 :                                 entry, gen_id));
     228          20 :     db_event_queue_.Enqueue(req);
     229          20 : }
     230             : 
     231       15787 : void FlowMgmtManager::EnqueueFlowEvent(FlowEvent *event) {
     232       15787 :     agent_->pkt()->get_flow_proto()->EnqueueFlowEvent(event);
     233       15787 : }
     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         155 : void FlowMgmtManager::DBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
     244             :                                    FlowEntry *flow) {
     245         155 :     FlowEvent *flow_resp = new FlowEvent(event, NULL, key->db_entry());
     246         155 :     key->KeyToFlowRequest(flow_resp);
     247         155 :     flow_resp->set_flow(flow);
     248         155 :     EnqueueFlowEvent(flow_resp);
     249         155 : }
     250             : 
     251       15632 : void FlowMgmtManager::FreeDBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
     252             :                                        uint32_t gen_id) {
     253       15632 :     FlowEvent *flow_resp = new FlowEvent(event, table_index_, key->db_entry(),
     254       15632 :                                          gen_id);
     255       15632 :     EnqueueFlowEvent(flow_resp);
     256       15632 : }
     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       35796 : bool FlowMgmtManager::ProcessEvent(FlowMgmtRequest *req, FlowMgmtKey *key,
     274             :                                    FlowMgmtTree *tree) {
     275       35796 :     InetRouteFlowMgmtTree* itree = dynamic_cast<InetRouteFlowMgmtTree*>(tree);
     276       35796 :     switch (req->event()) {
     277       19966 :     case FlowMgmtRequest::ADD_DBENTRY:
     278       19966 :         tree->OperEntryAdd(req, key);
     279       19966 :         break;
     280             : 
     281          10 :     case FlowMgmtRequest::CHANGE_DBENTRY:
     282          10 :         tree->OperEntryChange(req, key);
     283          10 :         break;
     284             : 
     285       15800 :     case FlowMgmtRequest::DELETE_DBENTRY:
     286             :     case FlowMgmtRequest::IMPLICIT_ROUTE_DELETE:
     287       15800 :         tree->OperEntryDelete(req, key);
     288       15800 :         break;
     289             : 
     290          20 :     case FlowMgmtRequest::DELETE_LAYER2_FLOW:
     291          20 :         assert(itree);
     292          20 :         itree->RouteNHChangeEvent(req, key);
     293          20 :         break;
     294             : 
     295           0 :     default:
     296           0 :         assert(0);
     297             :         break;
     298             :     }
     299             : 
     300       35796 :     return true;
     301             : }
     302             : 
     303       35796 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequest *req,
     304             :                                        const DBEntry *entry) {
     305       35796 :     const Interface *intf = dynamic_cast<const Interface *>(entry);
     306       35796 :     if (intf) {
     307        1046 :         InterfaceFlowMgmtKey key(intf);
     308        1046 :         return ProcessEvent(req, &key, &interface_flow_mgmt_tree_);
     309        1046 :     }
     310             : 
     311       34750 :     const VnEntry *vn = dynamic_cast<const VnEntry *>(entry);
     312       34750 :     if (vn) {
     313         174 :         VnFlowMgmtKey key(vn);
     314         174 :         return ProcessEvent(req, &key, &vn_flow_mgmt_tree_);
     315         174 :     }
     316             : 
     317       34576 :     const AclDBEntry *acl = dynamic_cast<const AclDBEntry *>(entry);
     318       34576 :     if (acl) {
     319          14 :         AclFlowMgmtKey key(acl, NULL);
     320          14 :         return ProcessEvent(req, &key, &acl_flow_mgmt_tree_);
     321          14 :     }
     322             : 
     323       34562 :     const NextHop *nh = dynamic_cast<const NextHop *>(entry);
     324       34562 :     if (nh) {
     325       21474 :         NhFlowMgmtKey key(static_cast<const NextHop *>(req->db_entry()));
     326       21474 :         return ProcessEvent(req, &key, &nh_flow_mgmt_tree_);
     327       21474 :     }
     328             : 
     329             :     const InetUnicastRouteEntry *inet_uc_rt =
     330       13088 :         dynamic_cast<const InetUnicastRouteEntry *>(entry);
     331       13088 :     if (inet_uc_rt) {
     332        9615 :         InetRouteFlowMgmtKey key(inet_uc_rt);
     333        9615 :         if (inet_uc_rt->prefix_address().is_v4()) {
     334        8670 :             return ProcessEvent(req, &key, &ip4_route_flow_mgmt_tree_);
     335             :         }
     336         945 :         if (inet_uc_rt->prefix_address().is_v6()) {
     337         945 :             return ProcessEvent(req, &key, &ip6_route_flow_mgmt_tree_);
     338             :         }
     339        9615 :     }
     340             : 
     341             :     const BridgeRouteEntry *bridge =
     342        3473 :         dynamic_cast<const BridgeRouteEntry *>(entry);
     343        3473 :     if (bridge) {
     344        2953 :         BridgeRouteFlowMgmtKey key(bridge);
     345        2953 :         return ProcessEvent(req, &key, &bridge_route_flow_mgmt_tree_);
     346        2953 :     }
     347             : 
     348         520 :     const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(entry);
     349         520 :     if (vrf) {
     350         520 :         VrfFlowMgmtKey key(vrf);
     351         520 :         return ProcessEvent(req, &key, &vrf_flow_mgmt_tree_);
     352         520 :     }
     353             : 
     354           0 :     assert(0);
     355             :     return true;
     356             : }
     357             : 
     358             : bool
     359         142 : FlowMgmtManager::BgpAsAServiceRequestHandler(FlowMgmtRequest *req) {
     360             : 
     361             :     BgpAsAServiceFlowMgmtRequest *bgp_as_a_service_request =
     362         142 :         dynamic_cast<BgpAsAServiceFlowMgmtRequest *>(req);
     363         142 :     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         142 :     } else if (bgp_as_a_service_request->type() ==
     373             :                BgpAsAServiceFlowMgmtRequest::CONTROLLER) {
     374         142 :         bgp_as_a_service_flow_mgmt_tree_[bgp_as_a_service_request->index()].get()->
     375         142 :             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         142 :     return true;
     391             : }
     392             : 
     393        1029 : bool FlowMgmtManager::RequestHandler(FlowMgmtRequestPtr req) {
     394        1029 :     switch (req->event()) {
     395         359 :     case FlowMgmtRequest::UPDATE_FLOW: {
     396         359 :         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         359 :         std::scoped_lock mutex(flow->mutex());
     401         359 :         flow->set_flow_mgmt_request(NULL);
     402             : 
     403             :         // Update flow-mgmt information based on flow-state
     404         359 :         if (flow->deleted() == false) {
     405             :             FlowMgmtRequestPtr log_req(new FlowMgmtRequest
     406             :                                        (FlowMgmtRequest::ADD_FLOW,
     407         212 :                                         req->flow().get()));
     408         212 :             log_queue_->Enqueue(log_req);
     409             : 
     410             :             //Enqueue Add request to flow-stats-collector
     411         212 :             agent_->flow_stats_manager()->AddEvent(req->flow());
     412             : 
     413             :             //Enqueue Add request to UVE module for ACE stats
     414         212 :             EnqueueUveAddEvent(flow);
     415             : 
     416         212 :             AddFlow(req->flow());
     417             : 
     418         212 :         } else {
     419             :             FlowMgmtRequestPtr log_req(new FlowMgmtRequest
     420             :                                        (FlowMgmtRequest::DELETE_FLOW,
     421         147 :                                         req->flow().get(), req->params()));
     422         147 :             log_queue_->Enqueue(log_req);
     423             : 
     424             :             //Enqueue Delete request to flow-stats-collector
     425         147 :             agent_->flow_stats_manager()->DeleteEvent(flow, req->params());
     426             : 
     427             :             //Enqueue Delete request to UVE module for ACE stats
     428         147 :             EnqueueUveDeleteEvent(flow);
     429             : 
     430         147 :             DeleteFlow(req->flow(), req->params());
     431         147 :         }
     432         359 :         break;
     433         359 :     }
     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         528 :     case FlowMgmtRequest::RETRY_DELETE_VRF: {
     443         528 :         RetryVrfDelete(req->vrf_id());
     444         528 :         break;
     445             :     }
     446             : 
     447         142 :     case FlowMgmtRequest::DELETE_BGP_AAS_FLOWS: {
     448         142 :         BgpAsAServiceRequestHandler(req.get());
     449         142 :         break;
     450             :     }
     451             : 
     452           0 :     case FlowMgmtRequest::DUMMY:
     453           0 :         break;
     454             : 
     455           0 :     default:
     456           0 :          assert(0);
     457             : 
     458             :     }
     459             : 
     460        1029 :     return true;
     461             : }
     462             : 
     463       35796 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequestPtr req) {
     464       35796 :     switch (req->event()) {
     465       35796 :     case FlowMgmtRequest::ADD_DBENTRY:
     466             :     case FlowMgmtRequest::CHANGE_DBENTRY:
     467             :     case FlowMgmtRequest::DELETE_DBENTRY:
     468             :     case FlowMgmtRequest::DELETE_LAYER2_FLOW: {
     469       35796 :         DBRequestHandler(req.get(), req->db_entry());
     470       35796 :         break;
     471             :     }
     472             : 
     473           0 :     default:
     474           0 :          assert(0);
     475             : 
     476             :     }
     477             : 
     478       35796 :     return true;
     479             : }
     480             : 
     481         359 : bool FlowMgmtManager::LogHandler(FlowMgmtRequestPtr req) {
     482         359 :     FlowEntry *flow = req->flow().get();
     483         359 :     FlowEntry *rflow = flow->reverse_flow_entry();
     484             : 
     485         506 :     FLOW_LOCK(flow, rflow, FlowEvent::FLOW_MESSAGE);
     486         359 :     switch (req->event()) {
     487         212 :     case FlowMgmtRequest::ADD_FLOW: {
     488         212 :         LogFlowUnlocked(flow, "ADD");
     489         212 :         break;
     490             :     }
     491             : 
     492         147 :     case FlowMgmtRequest::DELETE_FLOW: {
     493         147 :         LogFlowUnlocked(flow, "DEL");
     494         147 :         break;
     495             :     }
     496             : 
     497           0 :     default:
     498           0 :          assert(0);
     499             : 
     500             :     }
     501             : 
     502         359 :     return true;
     503         359 : }
     504             : 
     505        4919 : void FlowMgmtManager::RetryVrfDelete(uint32_t vrf_id) {
     506        4919 :     vrf_flow_mgmt_tree_.RetryDelete(vrf_id);
     507        4919 : }
     508             : 
     509             : // Extract all the FlowMgmtKey for a flow
     510         359 : void FlowMgmtManager::LogFlowUnlocked(FlowEntry *flow, const std::string &op) {
     511         359 :     if (flow->trace() == false)
     512          89 :         return;
     513         270 :     FlowInfo trace;
     514         270 :     flow->FillFlowInfo(trace);
     515         270 :     FLOW_TRACE(Trace, op, trace);
     516         270 : }
     517             : 
     518             : // Extract all the FlowMgmtKey for a flow
     519         212 : void FlowMgmtManager::MakeFlowMgmtKeyTree(FlowEntry *flow,
     520             :                                           FlowMgmtKeyTree *tree) {
     521         212 :     acl_flow_mgmt_tree_.ExtractKeys(flow, tree);
     522         212 :     interface_flow_mgmt_tree_.ExtractKeys(flow, tree);
     523         212 :     vn_flow_mgmt_tree_.ExtractKeys(flow, tree);
     524         212 :     ip4_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
     525         212 :     ip6_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
     526         212 :     bridge_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
     527         212 :     nh_flow_mgmt_tree_.ExtractKeys(flow, tree);
     528         212 :     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         212 : }
     536             : 
     537         212 : void FlowMgmtManager::EnqueueUveAddEvent(const FlowEntry *flow) const {
     538         212 :     AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
     539         212 :     if (uve) {
     540         212 :         const Interface *itf = flow->intf_entry();
     541         212 :         const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
     542         212 :         const VnEntry *vn = flow->vn_entry();
     543         212 :         string vn_name = vn? vn->GetName() : "";
     544         212 :         string itf_name = vmi? vmi->cfg_name() : "";
     545         212 :         FlowUveVnAcePolicyInfo vn_ace_info;
     546         212 :         FlowUveFwPolicyInfo fw_policy_info;
     547             : 
     548         212 :         flow->FillUveVnAceInfo(&vn_ace_info);
     549         212 :         if (!itf_name.empty()) {
     550         211 :             flow->FillUveFwStatsInfo(&fw_policy_info, true);
     551             :         }
     552             :         boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
     553         212 :             (FlowUveStatsRequest::ADD_FLOW, flow->uuid(), itf_name,
     554         212 :              flow->sg_rule_uuid(), vn_ace_info, fw_policy_info));
     555             : 
     556         212 :         if (!req->sg_info_valid() && !req->vn_ace_valid() &&
     557           0 :             !req->fw_policy_valid()) {
     558           0 :             return;
     559             :         }
     560             : 
     561         212 :         uve->stats_manager()->EnqueueEvent(req);
     562         212 :     }
     563             : }
     564             : 
     565         147 : void FlowMgmtManager::EnqueueUveDeleteEvent(const FlowEntry *flow) const {
     566         147 :     AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
     567         147 :     if (uve) {
     568         147 :         const Interface *itf = flow->intf_entry();
     569         147 :         const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
     570         147 :         string itf_name = vmi? vmi->cfg_name() : "";
     571         147 :         FlowUveFwPolicyInfo fw_policy_info;
     572         147 :         if (!itf_name.empty()) {
     573         106 :             flow->FillUveFwStatsInfo(&fw_policy_info, false);
     574             :         }
     575             :         boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
     576         147 :             (FlowUveStatsRequest::DELETE_FLOW, flow->uuid(), itf_name,
     577         147 :              fw_policy_info));
     578         147 :         uve->stats_manager()->EnqueueEvent(req);
     579         147 :     }
     580         147 : }
     581             : 
     582         212 : void FlowMgmtManager::AddFlow(FlowEntryPtr &flow) {
     583         212 :     FlowMgmtKeyTree new_tree;
     584         212 :     MakeFlowMgmtKeyTree(flow.get(), &new_tree);
     585             : 
     586             :     // Get old FlowMgmtKeyTree
     587         212 :     FlowEntryInfo *old_info = LocateFlowEntryInfo(flow);
     588         212 :     FlowMgmtKeyTree *old_tree = &old_info->tree_;
     589         212 :     assert(old_tree);
     590         212 :     old_info->count_++;
     591             : 
     592             :     // Apply the difference in old and new key tree
     593         212 :     FlowMgmtKeyTree::iterator new_it = new_tree.begin();
     594         212 :     FlowMgmtKeyTree::iterator old_it = old_tree->begin();
     595             : 
     596         556 :     while (new_it != new_tree.end() && old_it != old_tree->end()) {
     597         344 :         FlowMgmtKey *new_key = new_it->first;
     598         344 :         FlowMgmtKey *old_key = old_it->first;
     599         344 :         if (new_key->IsLess(old_key)) {
     600           9 :             AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
     601           9 :             new_it++;
     602         335 :         } else if (old_key->IsLess(new_key)) {
     603          16 :             FlowMgmtKeyNode *node = old_it->second;
     604          16 :             DeleteFlowMgmtKey(flow.get(), old_info, old_key,
     605             :                               node);
     606          16 :             FlowMgmtKeyTree::iterator tmp = old_it++;
     607          16 :             FlowMgmtKey *key = tmp->first;
     608          16 :             old_tree->erase(tmp);
     609          16 :             delete key;
     610          16 :             delete node;
     611             :         } else {
     612         319 :             AddFlowMgmtKey(flow.get(), old_info, new_key, old_key);
     613         319 :             old_it++;
     614         319 :             new_it++;
     615             :         }
     616             :     }
     617             : 
     618         933 :     while (new_it != new_tree.end()) {
     619         721 :         FlowMgmtKey *new_key = new_it->first;
     620         721 :         AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
     621         721 :         new_it++;
     622             :     }
     623             : 
     624         226 :     while (old_it != old_tree->end()) {
     625          14 :         FlowMgmtKey *old_key = old_it->first;
     626          14 :         FlowMgmtKeyNode *node = old_it->second;
     627          14 :         DeleteFlowMgmtKey(flow.get(), old_info, old_key, node);
     628          14 :         FlowMgmtKeyTree::iterator tmp = old_it++;
     629          14 :         FlowMgmtKey *key = tmp->first;
     630          14 :         old_tree->erase(tmp);
     631          14 :         delete key;
     632          14 :         delete node;
     633             :     }
     634             : 
     635         212 :     new_it = new_tree.begin();
     636        1261 :     while (new_it != new_tree.end()) {
     637        1049 :         FlowMgmtKeyTree::iterator tmp = new_it++;
     638        1049 :         FlowMgmtKey *key = tmp->first;
     639        1049 :         FlowMgmtKeyNode *node = tmp->second;
     640        1049 :         new_tree.erase(tmp);
     641        1049 :         delete key;
     642        1049 :         delete node;
     643             :     }
     644         212 : }
     645             : 
     646         147 : void FlowMgmtManager::DeleteFlow(FlowEntryPtr &flow,
     647             :                                  const RevFlowDepParams &params) {
     648             :     // Delete entries for flow from the tree
     649         147 :     FlowEntryInfo *old_info = FindFlowEntryInfo(flow);
     650         147 :     if (old_info == NULL)
     651           0 :         return;
     652             : 
     653         147 :     FlowMgmtKeyTree *old_tree = &old_info->tree_;
     654         147 :     assert(old_tree);
     655         147 :     old_info->count_++;
     656             : 
     657         147 :     FlowMgmtKeyTree::iterator old_it = old_tree->begin();
     658         847 :     while (old_it != old_tree->end()) {
     659         700 :         FlowMgmtKeyNode *node = old_it->second;
     660         700 :         DeleteFlowMgmtKey(flow.get(), old_info, old_it->first, node);
     661         700 :         FlowMgmtKeyTree::iterator tmp = old_it++;
     662         700 :         FlowMgmtKey *key = tmp->first;
     663         700 :         old_tree->erase(tmp);
     664         700 :         delete key;
     665         700 :         delete node;
     666             :     }
     667             : 
     668         147 :     assert(old_tree->size() == 0);
     669         147 :     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         181 : bool FlowMgmtManager::HasVrfFlows(uint32_t vrf_id) {
     681         181 :     if (ip4_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET4_UNICAST)) {
     682           5 :         return true;
     683             :     }
     684             : 
     685         176 :     if (ip6_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET6_UNICAST)) {
     686           0 :         return true;
     687             :     }
     688             : 
     689         176 :     if (bridge_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::BRIDGE)) {
     690           0 :         return true;
     691             :     }
     692             : 
     693         176 :     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         359 : FlowMgmtManager::FindFlowEntryInfo(const FlowEntryPtr &flow) {
     711         359 :     return flow->flow_mgmt_info();
     712             : }
     713             : 
     714             : FlowEntryInfo *
     715         212 : FlowMgmtManager::LocateFlowEntryInfo(FlowEntryPtr &flow) {
     716         212 :     FlowEntryInfo *info = FindFlowEntryInfo(flow);
     717         212 :     if (info != NULL)
     718          65 :         return info;
     719         147 :     info = new FlowEntryInfo(flow.get());
     720         147 :     flow->set_flow_mgmt_info(info);
     721         147 :     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         147 : void FlowMgmtManager::DeleteFlowEntryInfo(FlowEntryPtr &flow) {
     741         147 :     FlowEntryInfo *info = flow->flow_mgmt_info();
     742         147 :     if (info == NULL)
     743           0 :         return;
     744             : 
     745         147 :     assert(info->tree_.size() == 0);
     746         147 :     flow->set_flow_mgmt_info(NULL);
     747         147 :     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        1049 : void FlowMgmtManager::AddFlowMgmtKey(FlowEntry *flow, FlowEntryInfo *info,
     757             :                                      FlowMgmtKey *key, FlowMgmtKey *old_key) {
     758        1049 :     FlowMgmtKey *tmp = key->Clone();
     759        1049 :     FlowMgmtKeyNode *node = new FlowMgmtKeyNode(flow);
     760             : 
     761        1049 :     std::pair<FlowMgmtKeyTree::iterator, bool> ret = info->tree_.insert(
     762        1049 :                                                      make_pair(tmp, node));
     763        1049 :     if (ret.second == false) {
     764         319 :         delete tmp;
     765         319 :         delete node;
     766         319 :         if (key->type() == FlowMgmtKey::ACL) {
     767             :             /* Copy the ACE Id list to existing key from new Key */
     768          23 :             FlowMgmtKey *existing_key = ret.first->first;
     769          23 :             AclFlowMgmtKey *akey = static_cast<AclFlowMgmtKey *>(existing_key);
     770          23 :             AclFlowMgmtKey *new_key = static_cast<AclFlowMgmtKey *>(key);
     771          23 :             akey->set_ace_id_list(new_key->ace_id_list());
     772             :         }
     773             :     }
     774             : 
     775        1049 :     switch (key->type()) {
     776         212 :     case FlowMgmtKey::INTERFACE:
     777         212 :         interface_flow_mgmt_tree_.Add(key, flow,
     778         212 :                                       (ret.second)? node : NULL);
     779         212 :         break;
     780             : 
     781          30 :     case FlowMgmtKey::ACL:
     782          30 :         acl_flow_mgmt_tree_.Add(key, flow, old_key,
     783          30 :                                 (ret.second)? node : NULL);
     784          30 :         break;
     785             : 
     786         212 :     case FlowMgmtKey::VN: {
     787         212 :         bool new_flow = vn_flow_mgmt_tree_.Add(key, flow,
     788         212 :                                                (ret.second)? node : NULL);
     789             :         VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
     790         212 :             (vn_flow_mgmt_tree_.Find(key));
     791         212 :         entry->UpdateCounterOnAdd(flow, new_flow, info->local_flow_,
     792         212 :                                   info->ingress_);
     793         212 :         info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
     794         212 :         info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
     795         212 :         break;
     796             :     }
     797             : 
     798         332 :     case FlowMgmtKey::INET4:
     799         332 :         ip4_route_flow_mgmt_tree_.Add(key, flow,
     800         332 :                                       (ret.second)? node : NULL);
     801         332 :         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          60 :     case FlowMgmtKey::BRIDGE:
     809          60 :         bridge_route_flow_mgmt_tree_.Add(key, flow,
     810          60 :                                          (ret.second)? node : NULL);
     811          60 :         break;
     812             : 
     813         203 :     case FlowMgmtKey::NH:
     814         203 :         nh_flow_mgmt_tree_.Add(key, flow,
     815         203 :                                (ret.second)? node : NULL);
     816         203 :         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        1049 : }
     841             : 
     842             : // Delete a FlowMgmtKey from FlowMgmtKeyTree for an object
     843             : // The FlowMgmtKeyTree for object is passed as argument
     844         730 : void FlowMgmtManager::DeleteFlowMgmtKey(
     845             :     FlowEntry *flow, FlowEntryInfo *info, FlowMgmtKey *key,
     846             :     FlowMgmtKeyNode *node) {
     847             : 
     848         730 :     FlowMgmtKeyTree::iterator it = info->tree_.find(key);
     849         730 :     assert(it != info->tree_.end());
     850             : 
     851         730 :     switch (key->type()) {
     852         147 :     case FlowMgmtKey::INTERFACE:
     853         147 :         interface_flow_mgmt_tree_.Delete(key, flow, node);
     854         147 :         break;
     855             : 
     856           7 :     case FlowMgmtKey::ACL:
     857           7 :         acl_flow_mgmt_tree_.Delete(key, flow, node);
     858           7 :         break;
     859             : 
     860         147 :     case FlowMgmtKey::VN: {
     861         147 :         vn_flow_mgmt_tree_.Delete(key, flow, node);
     862             :         VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
     863         147 :             (vn_flow_mgmt_tree_.Find(key));
     864         147 :         if (entry)
     865         147 :             entry->UpdateCounterOnDel(flow, info->local_flow_, info->ingress_);
     866         147 :         info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
     867         147 :         info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
     868         147 :         break;
     869             :     }
     870             : 
     871         252 :     case FlowMgmtKey::INET4:
     872         252 :         ip4_route_flow_mgmt_tree_.Delete(key, flow, node);
     873         252 :         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         149 :     case FlowMgmtKey::NH:
     884         149 :         nh_flow_mgmt_tree_.Delete(key, flow, node);
     885         149 :         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         730 : }

Generated by: LCOV version 1.14