LCOV - code coverage report
Current view: top level - vnsw/agent/pkt/flow_mgmt - flow_mgmt_dbclient.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 398 470 84.7 %
Date: 2026-09-28 02:13:17 Functions: 26 28 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "pkt/flow_mgmt/flow_mgmt_dbclient.h"
       2             : #include "pkt/flow_mgmt.h"
       3             : #include "oper/ecmp_load_balance.h"
       4             : #include "oper/ecmp.h"
       5             : #include <oper/tunnel_nh.h>
       6             : 
       7           1 : void FlowMgmtDbClient::Init() {
       8           1 :     acl_listener_id_ = agent_->acl_table()->Register
       9           1 :         (boost::bind(&FlowMgmtDbClient::AclNotify, this, _1, _2));
      10             : 
      11           1 :     interface_listener_id_ = agent_->interface_table()->Register
      12           1 :         (boost::bind(&FlowMgmtDbClient::InterfaceNotify, this, _1, _2));
      13             : 
      14           1 :     vn_listener_id_ = agent_->vn_table()->Register
      15           1 :         (boost::bind(&FlowMgmtDbClient::VnNotify, this, _1, _2));
      16             : 
      17           1 :     vrf_listener_id_ = agent_->vrf_table()->Register
      18           1 :             (boost::bind(&FlowMgmtDbClient::VrfNotify, this, _1, _2));
      19             : 
      20           1 :     nh_listener_id_ = agent_->nexthop_table()->Register
      21           1 :             (boost::bind(&FlowMgmtDbClient::NhNotify, this, _1, _2));
      22           1 :     return;
      23             : }
      24             : 
      25           1 : void FlowMgmtDbClient::Shutdown() {
      26           1 :     agent_->acl_table()->Unregister(acl_listener_id_);
      27           1 :     agent_->interface_table()->Unregister(interface_listener_id_);
      28           1 :     agent_->vn_table()->Unregister(vn_listener_id_);
      29           1 :     agent_->vm_table()->Unregister(vm_listener_id_);
      30           1 :     agent_->vrf_table()->Unregister(vrf_listener_id_);
      31           1 :     agent_->nexthop_table()->Unregister(nh_listener_id_);
      32           1 : }
      33             : 
      34           1 : FlowMgmtDbClient::FlowMgmtDbClient(Agent *agent, FlowMgmtManager *mgr) :
      35           1 :     agent_(agent),
      36           1 :     mgr_(mgr),
      37           1 :     acl_listener_id_(),
      38           1 :     interface_listener_id_(),
      39           1 :     vn_listener_id_(),
      40           1 :     vm_listener_id_(),
      41           1 :     vrf_listener_id_(),
      42           1 :     nh_listener_id_() {
      43           1 : }
      44             : 
      45           2 : FlowMgmtDbClient::~FlowMgmtDbClient() {
      46           2 : }
      47             : 
      48         160 : void FlowMgmtDbClient::AddEvent(const DBEntry *entry, FlowMgmtState *state) {
      49         160 :     mgr_->AddDBEntryEvent(entry, state->gen_id_);
      50         160 : }
      51             : 
      52         111 : void FlowMgmtDbClient::DeleteEvent(const DBEntry *entry, FlowMgmtState *state) {
      53         111 :     state->gen_id_++;
      54         111 :     state->deleted_ = true;
      55         111 :     mgr_->DeleteDBEntryEvent(entry, state->gen_id_);
      56         111 : }
      57             : 
      58           4 : void FlowMgmtDbClient::DeleteAllFlow(const DBEntry *entry,
      59             :                                      FlowMgmtState *state) {
      60           4 :     mgr_->DeleteDBEntryEvent(entry, state->gen_id_);
      61           4 : }
      62             : 
      63           0 : void FlowMgmtDbClient::ChangeEvent(const DBEntry *entry, FlowMgmtState *state) {
      64           0 :     mgr_->ChangeDBEntryEvent(entry, state->gen_id_);
      65           0 : }
      66             : 
      67           0 : void FlowMgmtDbClient::RouteNHChangeEvent(const DBEntry *entry,
      68             :                                           FlowMgmtState *state) {
      69           0 :     mgr_->RouteNHChangeEvent(entry, state->gen_id_);
      70           0 : }
      71             : 
      72             : ////////////////////////////////////////////////////////////////////////////
      73             : // Interface notification handler
      74             : ////////////////////////////////////////////////////////////////////////////
      75         113 : static DBState *ValidateGenId(DBTableBase *table, DBEntry *entry,
      76             :                               DBTableBase::ListenerId id, uint32_t gen_id) {
      77             :     FlowMgmtDbClient::FlowMgmtState *state =
      78         113 :         static_cast<FlowMgmtDbClient::FlowMgmtState *>(entry->GetState(table,
      79             :                                                                       id));
      80         113 :     if (state == NULL)
      81           0 :         return NULL;
      82             : 
      83             :     // If DBEntry is re-added in meanwhile, we do not want to free DBState
      84         113 :     if (state->deleted_ == false)
      85           4 :         return NULL;
      86             : 
      87         109 :     if (state->gen_id_ > gen_id)
      88           0 :         return NULL;
      89             : 
      90         109 :     return state;
      91             : }
      92             : 
      93           9 : void FlowMgmtDbClient::FreeInterfaceState(Interface *intf, uint32_t gen_id) {
      94           9 :     VmInterface *vm_port = dynamic_cast<VmInterface *>(intf);
      95           9 :     if (vm_port == NULL)
      96           0 :         return;
      97             : 
      98           9 :     DBState *state = ValidateGenId(intf->get_table(), intf,
      99             :                                    interface_listener_id_, gen_id);
     100           9 :     if (state == NULL)
     101           4 :         return;
     102             : 
     103           5 :     intf->ClearState(intf->get_table(), interface_listener_id_);
     104           5 :     delete state;
     105             : }
     106             : 
     107          33 : void FlowMgmtDbClient::InterfaceNotify(DBTablePartBase *part, DBEntryBase *e) {
     108          33 :     Interface *intf = static_cast<Interface *>(e);
     109          33 :     if (intf->type() != Interface::VM_INTERFACE) {
     110           4 :         return;
     111             :     }
     112             : 
     113          29 :     VmInterface *vm_port = static_cast<VmInterface *>(intf);
     114          29 :     if (vm_port->device_type() == VmInterface::VMI_ON_LR)
     115           0 :         return;
     116             : 
     117          29 :     const VnEntry *new_vn = vm_port->vn();
     118             : 
     119             :     VmIntfFlowHandlerState *state = static_cast<VmIntfFlowHandlerState *>
     120          29 :         (e->GetState(part->parent(), interface_listener_id_));
     121          29 :     if (intf->IsDeleted()) {
     122           5 :         if (state) {
     123           5 :             DeleteEvent(vm_port, state);
     124             :         }
     125           5 :         return;
     126             :     }
     127             : 
     128          24 :     const VmInterface::SecurityGroupEntryList &new_sg_l = vm_port->sg_list();
     129          24 :     bool changed = false;
     130             : 
     131          24 :     if (state == NULL) {
     132           5 :         state = new VmIntfFlowHandlerState(NULL);
     133           5 :         e->SetState(part->parent(), interface_listener_id_, state);
     134             :         // Force change for first time
     135           5 :         state->policy_ = vm_port->policy_enabled();
     136           5 :         state->sg_l_ = new_sg_l;
     137           5 :         state->vn_ = new_vn;
     138           5 :         state->vrf_assign_acl_ = vm_port->vrf_assign_acl();
     139           5 :         state->is_vn_qos_config_ = vm_port->is_vn_qos_config();
     140           5 :         state->qos_config_ = vm_port->qos_config();
     141           5 :         state->fw_policy_list_ = vm_port->fw_policy_list();
     142           5 :         state->fwaas_fw_policy_list_ = vm_port->fwaas_fw_policy_list();
     143           5 :         if (vm_port->forwarding_vrf()) {
     144           1 :             state->forwarding_vrf_id_ = vm_port->forwarding_vrf()->vrf_id();
     145             :         }
     146           5 :         changed = true;
     147             :     } else {
     148          19 :         if (state->deleted_) {
     149           0 :             state->deleted_ = false;
     150           0 :             changed = true;
     151             :         }
     152             : 
     153          19 :         if (state->vn_.get() != new_vn) {
     154           4 :             changed = true;
     155           4 :             state->vn_ = new_vn;
     156             :         }
     157          19 :         if (state->policy_ != vm_port->policy_enabled()) {
     158           4 :             changed = true;
     159           4 :             state->policy_ = vm_port->policy_enabled();
     160             :         }
     161          19 :         if (state->sg_l_.list_ != new_sg_l.list_) {
     162           0 :             changed = true;
     163           0 :             state->sg_l_ = new_sg_l;
     164             :         }
     165          19 :         if (state->vrf_assign_acl_.get() != vm_port->vrf_assign_acl()) {
     166           0 :             changed = true;
     167           0 :             state->vrf_assign_acl_ = vm_port->vrf_assign_acl();
     168             :         }
     169          19 :         if (state->is_vn_qos_config_ != vm_port->is_vn_qos_config()) {
     170           0 :             state->is_vn_qos_config_ = vm_port->is_vn_qos_config();
     171           0 :             changed = true;
     172             :         }
     173          19 :         if (state->qos_config_.get() != vm_port->qos_config()) {
     174           0 :             state->qos_config_ = vm_port->qos_config();
     175           0 :             changed = true;
     176             :         }
     177             : 
     178          19 :         if (state->fw_policy_list_ != vm_port->fw_policy_list()) {
     179           0 :             state->fw_policy_list_ = vm_port->fw_policy_list();
     180           0 :             changed = true;
     181             :         }
     182             : 
     183          19 :         if (state->fwaas_fw_policy_list_ != vm_port->fwaas_fw_policy_list()) {
     184           0 :             state->fwaas_fw_policy_list_ = vm_port->fwaas_fw_policy_list();
     185           0 :             changed = true;
     186             :         }
     187             : 
     188          19 :         uint32_t forwarding_vrf_id = VrfEntry::kInvalidIndex;
     189          19 :         if (vm_port->forwarding_vrf()) {
     190          15 :             forwarding_vrf_id = vm_port->forwarding_vrf()->vrf_id();
     191             :         }
     192             : 
     193          19 :         if (state->forwarding_vrf_id_ != forwarding_vrf_id) {
     194           4 :             state->forwarding_vrf_id_ = forwarding_vrf_id;
     195           4 :             DeleteAllFlow(vm_port, state);
     196           4 :             changed = true;
     197             :         }
     198             :     }
     199             : 
     200          24 :     if (changed) {
     201           9 :         AddEvent(vm_port, state);
     202             :     }
     203             : }
     204             : 
     205             : ////////////////////////////////////////////////////////////////////////////
     206             : // VN notification handler
     207             : ////////////////////////////////////////////////////////////////////////////
     208           2 : void FlowMgmtDbClient::FreeVnState(VnEntry *vn, uint32_t gen_id) {
     209           2 :     DBState *state = ValidateGenId(vn->get_table(), vn, vn_listener_id_,
     210             :                                    gen_id);
     211           2 :     if (state == NULL)
     212           0 :         return;
     213             : 
     214           2 :     vn->ClearState(vn->get_table(), vn_listener_id_);
     215           2 :     delete state;
     216             : }
     217             : 
     218          10 : void FlowMgmtDbClient::VnNotify(DBTablePartBase *part, DBEntryBase *e) {
     219             :     // Add/Delete Acl:
     220             :     // Resync all Vn flows with new VN network policies
     221          10 :     VnEntry *vn = static_cast<VnEntry *>(e);
     222             :     VnFlowHandlerState *state = static_cast<VnFlowHandlerState *>
     223          10 :         (e->GetState(part->parent(), vn_listener_id_));
     224          10 :     AclDBEntryConstRef acl = NULL;
     225          10 :     AclDBEntryConstRef macl = NULL;
     226          10 :     AclDBEntryConstRef mcacl = NULL;
     227          10 :     bool enable_rpf = true;
     228          10 :     bool flood_unknown_unicast = false;
     229             : 
     230          10 :     if (vn->IsDeleted()) {
     231           2 :         if (state) {
     232           2 :             DeleteEvent(vn, state);
     233             :         }
     234           2 :         return;
     235             :     }
     236             : 
     237           8 :     bool changed = false;
     238           8 :     if (state != NULL) {
     239           6 :         acl = state->acl_;
     240           6 :         macl = state->macl_;
     241           6 :         mcacl = state->mcacl_;
     242           6 :         enable_rpf = state->enable_rpf_;
     243           6 :         flood_unknown_unicast = state->flood_unknown_unicast_;
     244             :     }
     245             : 
     246           8 :     const AclDBEntry *new_acl = vn->GetAcl();
     247           8 :     const AclDBEntry *new_macl = vn->GetMirrorAcl();
     248           8 :     const AclDBEntry *new_mcacl = vn->GetMirrorCfgAcl();
     249           8 :     bool new_enable_rpf = vn->enable_rpf();
     250           8 :     bool new_flood_unknown_unicast = vn->flood_unknown_unicast();
     251             : 
     252           8 :     if (state == NULL) {
     253           2 :         state = new VnFlowHandlerState(new_acl, new_macl, new_mcacl,
     254             :                                        new_enable_rpf,
     255           2 :                                        new_flood_unknown_unicast);
     256           2 :         e->SetState(part->parent(), vn_listener_id_, state);
     257           2 :         changed = true;
     258             :     }
     259             : 
     260          14 :     if (acl != new_acl || macl != new_macl || mcacl !=new_mcacl ||
     261          14 :         enable_rpf != new_enable_rpf ||
     262             :         flood_unknown_unicast != new_flood_unknown_unicast) {
     263           2 :         state->acl_ = new_acl;
     264           2 :         state->macl_ = new_macl;
     265           2 :         state->mcacl_ = new_mcacl;
     266           2 :         state->enable_rpf_ = new_enable_rpf;
     267           2 :         state->flood_unknown_unicast_ = new_flood_unknown_unicast;
     268           2 :         changed = true;
     269             :     }
     270             : 
     271           8 :     if (state->deleted_) {
     272           0 :         state->deleted_ = false;
     273           0 :         changed = true;
     274             :     }
     275             : 
     276           8 :     if (changed) {
     277           4 :         AddEvent(vn, state);
     278             :     }
     279          14 : }
     280             : 
     281             : ////////////////////////////////////////////////////////////////////////////
     282             : // ACL notification handler
     283             : ////////////////////////////////////////////////////////////////////////////
     284           2 : void FlowMgmtDbClient::FreeAclState(AclDBEntry *acl, uint32_t gen_id) {
     285           2 :     DBState *state = ValidateGenId(acl->get_table(), acl, acl_listener_id_,
     286             :                                    gen_id);
     287           2 :     if (state == NULL)
     288           0 :         return;
     289             : 
     290           2 :     acl->ClearState(acl->get_table(), acl_listener_id_);
     291           2 :     delete state;
     292             : }
     293             : 
     294           4 : void FlowMgmtDbClient::AclNotify(DBTablePartBase *part, DBEntryBase *e) {
     295           4 :     AclDBEntry *acl = static_cast<AclDBEntry *>(e);
     296             :     AclFlowHandlerState *state =
     297           4 :         static_cast<AclFlowHandlerState *>(e->GetState(part->parent(),
     298             :                                                        acl_listener_id_));
     299           4 :     if (e->IsDeleted()) {
     300           2 :         if (state) {
     301           2 :             DeleteEvent(acl, state);
     302             :         }
     303           2 :         return;
     304             :     }
     305             : 
     306           2 :     if (!state) {
     307           2 :         state = new AclFlowHandlerState();
     308           2 :         e->SetState(part->parent(), acl_listener_id_, state);
     309             :     }
     310           2 :     state->deleted_ = false;
     311           2 :     AddEvent(acl, state);
     312             : }
     313             : 
     314             : ////////////////////////////////////////////////////////////////////////////
     315             : // NH notification handler
     316             : ////////////////////////////////////////////////////////////////////////////
     317          52 : void FlowMgmtDbClient::FreeNhState(NextHop *nh, uint32_t gen_id) {
     318          52 :     DBState *state = ValidateGenId(nh->get_table(), nh, nh_listener_id_,
     319             :                                    gen_id);
     320          52 :     if (state == NULL)
     321           0 :         return;
     322             : 
     323          52 :     nh->ClearState(nh->get_table(), nh_listener_id_);
     324          52 :     delete state;
     325             : }
     326             : 
     327         104 : void FlowMgmtDbClient::NhNotify(DBTablePartBase *part, DBEntryBase *e) {
     328         104 :     NextHop *nh = static_cast<NextHop *>(e);
     329             :     NhFlowHandlerState *state =
     330         104 :         static_cast<NhFlowHandlerState *>(e->GetState(part->parent(),
     331             :                                                       nh_listener_id_));
     332         104 :     bool is_tunnel_nh = false;
     333         104 :     bool changed = false;
     334         104 :     uint8_t curr_valid_encap_size = 0;
     335         104 :     uint8_t new_valid_encap_size = 0;
     336         104 :     if (nh->GetType() == NextHop::TUNNEL && agent_->is_l3mh()) {
     337             :         const TunnelNH *tunnel_nh =
     338           0 :             dynamic_cast<const TunnelNH *>(nh);
     339           0 :         if (tunnel_nh) {
     340           0 :             is_tunnel_nh = true;
     341           0 :             TunnelNH::EncapDataList encap_list = tunnel_nh->GetEncapDataList();
     342           0 :             for (uint8_t i = 0; i < tunnel_nh->GetEncapDataList().size(); i++) {
     343           0 :                 if (encap_list[i].get()->valid_)
     344           0 :                   new_valid_encap_size++;
     345             :             }
     346           0 :         }
     347             :     }
     348             : 
     349         104 :     if (nh->IsDeleted()) {
     350          52 :         if (state) {
     351          52 :             DeleteEvent(nh, state);
     352             :         }
     353          52 :         return;
     354             :     }
     355             : 
     356          52 :     if (state != NULL && is_tunnel_nh && agent_->is_l3mh() ) {
     357           0 :         curr_valid_encap_size = state->valid_encap_size_;
     358             :     }
     359             : 
     360          52 :     if (!state) {
     361          52 :         state = new NhFlowHandlerState(new_valid_encap_size);
     362          52 :         nh->SetState(part->parent(), nh_listener_id_, state);
     363          52 :         changed = true;
     364             :     }
     365             : 
     366          52 :     if (is_tunnel_nh && agent_->is_l3mh() && new_valid_encap_size != curr_valid_encap_size ) {
     367           0 :         state->valid_encap_size_ = new_valid_encap_size;
     368           0 :         changed = true;
     369             :     }
     370             : 
     371          52 :     if (state->deleted_) {
     372           0 :         state->deleted_ = false;
     373           0 :         changed = true;
     374             :     }
     375             : 
     376          52 :     if (changed) {
     377          52 :         AddEvent(nh, state);
     378             :     }
     379             : }
     380             : 
     381             : ////////////////////////////////////////////////////////////////////////////
     382             : // VRF Notification handlers
     383             : ////////////////////////////////////////////////////////////////////////////
     384           4 : void FlowMgmtDbClient::FreeVrfState(VrfEntry *vrf, uint32_t gen_id) {
     385           4 :     if (vrf->IsDeleted() == false)
     386           0 :         return;
     387             : 
     388             :     VrfFlowHandlerState *state = static_cast<VrfFlowHandlerState *>
     389           4 :         (ValidateGenId(vrf->get_table(), vrf, vrf_listener_id_, gen_id));
     390           4 :     if (state == NULL)
     391           0 :         return;
     392           4 :     if (state->Unregister(vrf)) {
     393           4 :         vrf->ClearState(vrf->get_table(), vrf_listener_id_);
     394           4 :         delete state;
     395             :     }
     396             : }
     397             : 
     398           4 : bool FlowMgmtDbClient::VrfFlowHandlerState::Unregister(VrfEntry *vrf) {
     399             :     // Register to the Inet4 Unicast Table
     400             :     InetUnicastAgentRouteTable *inet_table =
     401             :         static_cast<InetUnicastAgentRouteTable *>
     402           4 :         (vrf->GetInet4UnicastRouteTable());
     403           4 :     if (inet_table) {
     404           4 :         if (inet_table->Size() != 0)
     405           0 :             return false;
     406           4 :         if (inet_listener_id_ != DBTableBase::kInvalidId) {
     407           4 :             inet_table->Unregister(inet_listener_id_);
     408           4 :             FLOW_TRACE(RouteTableListener,
     409             :                        "ROUTE-TABLE-UNREGISTER",
     410             :                        vrf->GetName(),
     411             :                        inet_table->GetTableName(),
     412             :                        inet_listener_id_);
     413           4 :             inet_listener_id_ = DBTableBase::kInvalidId;
     414             :         }
     415             :     }
     416             : 
     417             :     inet_table = static_cast<InetUnicastAgentRouteTable *>
     418           4 :         (vrf->GetInet6UnicastRouteTable());
     419           4 :     if (inet_table) {
     420           4 :         if (inet_table->Size() != 0)
     421           0 :             return false;
     422           4 :         if (inet6_listener_id_ != DBTableBase::kInvalidId) {
     423           4 :             inet_table->Unregister(inet6_listener_id_);
     424           4 :             FLOW_TRACE(RouteTableListener,
     425             :                        "ROUTE-TABLE-UNREGISTER",
     426             :                        vrf->GetName(),
     427             :                        inet_table->GetTableName(),
     428             :                        inet6_listener_id_);
     429           4 :             inet6_listener_id_ = DBTableBase::kInvalidId;
     430             :         }
     431             :     }
     432             : 
     433             :     // Register to the Bridge Unicast Table
     434             :     BridgeAgentRouteTable *bridge_table =
     435             :         static_cast<BridgeAgentRouteTable *>
     436           4 :         (vrf->GetBridgeRouteTable());
     437           4 :     if (bridge_table) {
     438           4 :         if (bridge_table->Size() != 0)
     439           0 :             return false;
     440           4 :         if (bridge_listener_id_ != DBTableBase::kInvalidId) {
     441           4 :             bridge_table->Unregister(bridge_listener_id_);
     442           4 :             FLOW_TRACE(RouteTableListener,
     443             :                        "ROUTE-TABLE-UNREGISTER",
     444             :                        vrf->GetName(),
     445             :                        bridge_table->GetTableName(),
     446             :                        bridge_listener_id_);
     447           4 :             bridge_listener_id_ = DBTableBase::kInvalidId;
     448             :         }
     449             :     }
     450             : 
     451           4 :     return true;
     452             : }
     453             : 
     454           4 : void FlowMgmtDbClient::VrfFlowHandlerState::Register(FlowMgmtDbClient *client,
     455             :                                                      VrfEntry *vrf) {
     456             :     // Register to the Inet4 Unicast Table
     457             :     InetUnicastAgentRouteTable *inet_table =
     458             :         static_cast<InetUnicastAgentRouteTable *>
     459           4 :         (vrf->GetInet4UnicastRouteTable());
     460             : 
     461           4 :     inet_listener_id_ =
     462           4 :         inet_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify, client,
     463             :                                          this, Agent::INET4_UNICAST, _1, _2));
     464           4 :     FLOW_TRACE(RouteTableListener,
     465             :                "ROUTE-TABLE-REGISTER",
     466             :                vrf->GetName(),
     467             :                inet_table->GetTableName(),
     468             :                inet_listener_id_);
     469             : 
     470             :     inet_table = static_cast<InetUnicastAgentRouteTable *>
     471           4 :         (vrf->GetInet6UnicastRouteTable());
     472           4 :     inet6_listener_id_ =
     473           4 :         inet_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify, client,
     474             :                                          this, Agent::INET6_UNICAST, _1, _2));
     475           4 :     FLOW_TRACE(RouteTableListener,
     476             :                "ROUTE-TABLE-REGISTER",
     477             :                vrf->GetName(),
     478             :                inet_table->GetTableName(),
     479             :                inet6_listener_id_);
     480             : 
     481             :     // Register to the Bridge Unicast Table
     482             :     BridgeAgentRouteTable *bridge_table =
     483             :         static_cast<BridgeAgentRouteTable *>
     484           4 :         (vrf->GetBridgeRouteTable());
     485           4 :     bridge_listener_id_ =
     486           4 :         bridge_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify,
     487             :                                            client, this, Agent::BRIDGE, _1,
     488             :                                            _2));
     489           4 :     FLOW_TRACE(RouteTableListener,
     490             :                "ROUTE-TABLE-REGISTER",
     491             :                vrf->GetName(),
     492             :                bridge_table->GetTableName(),
     493             :                bridge_listener_id_);
     494           4 : }
     495             : 
     496          37 : void FlowMgmtDbClient::VrfNotify(DBTablePartBase *part, DBEntryBase *e) {
     497          37 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
     498             :     VrfFlowHandlerState *state = static_cast<VrfFlowHandlerState *>
     499          37 :         (e->GetState(part->parent(), vrf_listener_id_));
     500          37 :     if (vrf->IsDeleted()) {
     501          31 :         if (state ) {
     502           6 :             state->deleted_ = true;
     503           6 :             DeleteEvent(vrf, state);
     504             :         }
     505          31 :         return;
     506             :     }
     507           6 :     if (state == NULL) {
     508           4 :         state = new VrfFlowHandlerState();
     509           4 :         state->Register(this, vrf);
     510           4 :         vrf->SetState(part->parent(), vrf_listener_id_, state);
     511           4 :         AddEvent(vrf, state);
     512             :     }
     513           6 :     state->deleted_ = false;
     514           6 :     return;
     515             : }
     516             : 
     517             : /////////////////////////////////////////////////////////////////////////////
     518             : // FlowTableRequest handlers for Routes
     519             : /////////////////////////////////////////////////////////////////////////////
     520         142 : void FlowMgmtDbClient::TraceMsg(AgentRoute *entry, const AgentPath *path,
     521             :                          const SecurityGroupList &sg_list, bool deleted) {
     522         142 :     std::vector<std::string> vn_list;
     523         142 :     if (path) {
     524          96 :         path->GetDestinationVnList(&vn_list);
     525             :     }
     526         142 :     InetUnicastRouteEntry *inet = dynamic_cast<InetUnicastRouteEntry *>(entry);
     527         142 :     if (inet) {
     528          74 :         FLOW_TRACE(RouteUpdate,
     529             :                    inet->vrf()->GetName(),
     530             :                    inet->prefix_address().to_string(),
     531             :                    inet->prefix_length(),
     532             :                    vn_list,
     533             :                    inet->IsDeleted(),
     534             :                    deleted,
     535             :                    sg_list.size(),
     536             :                    sg_list);
     537             :     }
     538             : 
     539         142 :     BridgeRouteEntry *bridge = dynamic_cast<BridgeRouteEntry *>(entry);
     540         142 :     if (bridge) {
     541          68 :         FLOW_TRACE(RouteUpdate,
     542             :                    bridge->vrf()->GetName(),
     543             :                    bridge->prefix_address().ToString(),
     544             :                    bridge->prefix_length(),
     545             :                    vn_list,
     546             :                    bridge->IsDeleted(),
     547             :                    deleted,
     548             :                    sg_list.size(),
     549             :                    sg_list);
     550             :     }
     551         142 : }
     552             : 
     553          44 : void FlowMgmtDbClient::FreeRouteState(AgentRoute *route, uint32_t gen_id) {
     554          44 :     if (route->IsDeleted() == false)
     555           0 :         return;
     556             : 
     557          44 :     VrfEntry *vrf = route->vrf();
     558             :     VrfFlowHandlerState *vrf_state = static_cast<VrfFlowHandlerState *>
     559          44 :         (vrf->GetState(vrf->get_table(), vrf_listener_id_));
     560          44 :     if (vrf_state == NULL)
     561           0 :         return;
     562             : 
     563             :     DBTableBase::ListenerId id;
     564          44 :     if (dynamic_cast<InetUnicastRouteEntry *>(route)) {
     565          28 :         if (route->GetTableType() == Agent::INET4_UNICAST)
     566          23 :             id = vrf_state->inet_listener_id_;
     567             :         else
     568           5 :             id = vrf_state->inet6_listener_id_;
     569          16 :     } else if (dynamic_cast<BridgeRouteEntry *>(route)) {
     570          16 :         id = vrf_state->bridge_listener_id_;
     571             :     } else {
     572           0 :         return;
     573             :     }
     574             : 
     575          44 :     DBState *state = ValidateGenId(route->get_table(), route, id, gen_id);
     576          44 :     if (state == NULL)
     577           0 :         return;
     578             : 
     579          44 :     route->ClearState(route->get_table(), id);
     580          44 :     delete state;
     581             : }
     582             : 
     583          75 : bool FlowMgmtDbClient::HandleTrackingIpChange(const AgentRoute *rt,
     584             :                                               RouteFlowHandlerState *state) {
     585          75 :     bool ret = false;
     586          75 :     RouteFlowHandlerState::FixedIpMap new_map;
     587             : 
     588             :     //Maintain a list of interface to fixed-ip mapping for
     589             :     //a given route, we need this map because there can be
     590             :     //multiple path from different local vm path peer.
     591             :     //If the route has fixed-ip change then all the the flows
     592             :     //dependent on this route will be reevaluated.
     593         184 :     for(Route::PathList::const_iterator it = rt->GetPathList().begin();
     594         368 :             it != rt->GetPathList().end(); it++) {
     595         109 :         const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
     596         109 :         const Peer *peer = path->peer();
     597         109 :         if (peer && peer->GetType() != Peer::LOCAL_VM_PORT_PEER) {
     598         109 :             continue;
     599             :         }
     600             : 
     601          36 :         if (path->nexthop() == NULL ||
     602          18 :             path->nexthop()->GetType() != NextHop::INTERFACE) {
     603           1 :             continue;
     604             :         }
     605             : 
     606          17 :         const InterfaceNH *nh = static_cast<InterfaceNH *>(path->nexthop());
     607          17 :         InterfaceConstRef intf = nh->GetInterface();
     608             : 
     609          17 :         IpAddress new_fixed_ip = path->GetFixedIp();
     610          17 :         if (new_fixed_ip == Ip4Address(0)) {
     611          17 :             continue;
     612             :         }
     613             : 
     614           0 :         new_map.insert(RouteFlowHandlerState::FixedIpEntry(intf, new_fixed_ip));
     615             : 
     616             :         RouteFlowHandlerState::FixedIpMap::const_iterator old_it =
     617           0 :             state->fixed_ip_map_.find(intf);
     618           0 :         if (old_it != state->fixed_ip_map_.end()) {
     619           0 :             if (new_fixed_ip != old_it->second) {
     620           0 :                 ret = true;
     621             :             }
     622             :         }
     623          17 :     }
     624             : 
     625             :     //Check if any path has been deleted
     626             :     RouteFlowHandlerState::FixedIpMap::const_iterator old_it =
     627          75 :         state->fixed_ip_map_.begin();
     628          75 :     for (;old_it != state->fixed_ip_map_.end(); old_it++) {
     629           0 :         if (new_map.find(old_it->first) == new_map.end()) {
     630           0 :             ret = true;
     631           0 :             break;
     632             :         }
     633             :     }
     634             : 
     635          75 :     state->fixed_ip_map_ = new_map;
     636          75 :     return ret;
     637          75 : }
     638             : 
     639         142 : void FlowMgmtDbClient::RouteNotify(VrfFlowHandlerState *vrf_state,
     640             :                                    Agent::RouteTableType type,
     641             :                                    DBTablePartBase *partition, DBEntryBase *e) {
     642         142 :     DBTableBase::ListenerId id = vrf_state->GetListenerId(type);
     643             :     RouteFlowHandlerState *state =
     644         142 :         static_cast<RouteFlowHandlerState *>(e->GetState(partition->parent(),
     645             :                                                          id));
     646         142 :     AgentRoute *route = static_cast<AgentRoute *>(e);
     647         142 :     const AgentPath *path = route->GetActivePath();
     648         142 :     SecurityGroupList new_sg_l;
     649             :     // Get new sg-list. Sort, the sg-list to aid in comparison
     650         142 :     if (path) {
     651          96 :         new_sg_l = route->GetActivePath()->sg_list();
     652          96 :         sort(new_sg_l.begin(), new_sg_l.end());
     653             :     }
     654         142 :     TraceMsg(route, path, new_sg_l, vrf_state->deleted_);
     655             : 
     656         142 :     if (route->IsDeleted()) {
     657          46 :         if (state) {
     658          44 :             DeleteEvent(route, state);
     659             :         }
     660          46 :         return;
     661             :     }
     662             : 
     663          96 :     if (vrf_state->deleted_) {
     664             :         // ignore route add/change for delete notified VRF.
     665           2 :         return;
     666             :     }
     667             : 
     668          94 :     if (route->is_multicast()) {
     669          19 :         return;
     670             :     }
     671             : 
     672          75 :     bool new_route = false;
     673          75 :     if (state == NULL) {
     674          44 :         state  = new RouteFlowHandlerState();
     675          44 :         route->SetState(partition->parent(), id, state);
     676          44 :         AddEvent(route, state);
     677          44 :         new_route = true;
     678             :     } else {
     679          31 :         if (state->deleted_) {
     680           0 :             state->deleted_ = false;
     681           0 :             new_route = true;
     682             :         }
     683             :     }
     684             : 
     685          75 :     bool changed = false;
     686          75 :     bool inet_rt_nh_changed = false;
     687             :     // Handle SG change
     688          75 :     if (state->sg_l_ != new_sg_l) {
     689           0 :         state->sg_l_ = new_sg_l;
     690           0 :         changed = true;
     691             :     }
     692             : 
     693             :     InetUnicastRouteEntry *inet_route =
     694          75 :         dynamic_cast<InetUnicastRouteEntry *>(route);
     695             :     //Trigger RPF NH sync, if active nexthop changes
     696          75 :     const NextHop *active_nh = route->GetActiveNextHop();
     697          75 :     const NextHop *local_nh = NULL;
     698          75 :     if (active_nh && (active_nh->GetType() == NextHop::COMPOSITE)) {
     699             :         //If destination is ecmp, all remote flow would
     700             :         //have RPF NH set to that local component NH
     701           0 :         local_nh = EcmpData::GetLocalNextHop(route);
     702             :     }
     703             : 
     704          75 :     if ((state->active_nh_ != active_nh) || (state->local_nh_ != local_nh)) {
     705          45 :         state->active_nh_ = active_nh;
     706          45 :         state->local_nh_ = local_nh;
     707             :         /* NH change can result in change of DMAC for the following routes, if
     708             :          * they point to L2 flows.So we need to delete these L2 flows to trigger
     709             :          * packet to be trapped again for flows which will have the new DMAC.
     710             :          * The InetRoutes whose NH change has to be tracked are
     711             :          * Ipv4 InetRoutes which have prefix < 32
     712             :          * Ipv6 InetRoutes which have prefix < 128
     713             :          */
     714          45 :         if (inet_route) {
     715          28 :             uint8_t plen = inet_route->prefix_length();
     716          55 :             if ((inet_route->prefix_address().is_v4() && plen < 32) ||
     717          27 :                 (inet_route->prefix_address().is_v6() && plen < 128)) {
     718           7 :                 inet_rt_nh_changed = true;
     719             :             } else {
     720          21 :                 new_route = true;
     721             :             }
     722             :         } else {
     723          17 :             new_route = true;
     724             :         }
     725             :     }
     726             : 
     727          75 :     if (HandleTrackingIpChange(route, state)) {
     728             :         //Tracking IP change can result in flow change
     729             :         //i.e in case of NAT new reverse flow might be
     730             :         //created, hence enqueue a ADD event so that flow will
     731             :         //be reevaluated.
     732           0 :         new_route = true;
     733             :     }
     734             : 
     735          75 :     if (state->ecmp_load_balance_ != path->ecmp_load_balance()) {
     736           0 :         state->ecmp_load_balance_ = path->ecmp_load_balance();
     737           0 :         changed = true;
     738             :     }
     739             : 
     740          75 :     if (state->tags_l_ != path->tag_list()) {
     741           0 :         state->tags_l_ = path->tag_list();
     742           0 :         changed = true;
     743             :     }
     744             : 
     745          75 :     if (state->tunnel_bmap_ != path->tunnel_bmap()) {
     746          43 :         state->tunnel_bmap_ = path->tunnel_bmap();
     747          43 :         changed = true;
     748             :     }
     749             : 
     750          75 :     if (new_route == true) {
     751          45 :         AddEvent(route, state);
     752          30 :     } else if (inet_rt_nh_changed == true) {
     753           0 :         RouteNHChangeEvent(route, state);
     754          30 :     } else if (changed == true) {
     755           0 :         ChangeEvent(route, state);
     756             :     }
     757         142 : }
     758             : 
     759             : /////////////////////////////////////////////////////////////////////////////
     760             : // FlowTableRequest message handler
     761             : /////////////////////////////////////////////////////////////////////////////
     762         113 : bool FlowMgmtDbClient::FreeDBState(const DBEntry *entry, uint32_t gen_id) {
     763         113 :     if (dynamic_cast<const Interface *>(entry)) {
     764           9 :         DBTable *table = agent_->interface_table();
     765           9 :         Interface *intf = static_cast<Interface *>(table->Find(entry));
     766           9 :         FreeInterfaceState(intf, gen_id);
     767           9 :         return true;
     768             :     }
     769             : 
     770         104 :     if (dynamic_cast<const VnEntry *>(entry)) {
     771           2 :         DBTable *table = agent_->vn_table();
     772           2 :         VnEntry *vn = static_cast<VnEntry *>(table->Find(entry));
     773           2 :         FreeVnState(vn, gen_id);
     774           2 :         return true;
     775             :     }
     776             : 
     777         102 :     if (dynamic_cast<const AclDBEntry *>(entry)) {
     778           2 :         DBTable *table = agent_->acl_table();
     779           2 :         AclDBEntry *acl = static_cast<AclDBEntry *> (table->Find(entry));
     780           2 :         FreeAclState(acl, gen_id);
     781           2 :         return true;
     782             :     }
     783             : 
     784         100 :     if (dynamic_cast<const NextHop *>(entry)) {
     785          52 :         DBTable *table = agent_->nexthop_table();
     786          52 :         NextHop *nh = static_cast<NextHop *> (table->Find(entry));
     787          52 :         FreeNhState(nh, gen_id);
     788          52 :         return true;
     789             :     }
     790             : 
     791          48 :     if (dynamic_cast<const VrfEntry *>(entry)) {
     792           4 :         DBTable *table = agent_->vrf_table();
     793           4 :         VrfEntry *vrf = static_cast<VrfEntry *> (table->Find(entry));
     794           4 :         FreeVrfState(vrf, gen_id);
     795           4 :         return true;
     796             :     }
     797             : 
     798          44 :     if (dynamic_cast<const AgentRoute *>(entry)) {
     799          44 :         VrfEntry *vrf = (static_cast<const AgentRoute *>(entry))->vrf();
     800          44 :         AgentRoute *rt = NULL;
     801          44 :         if (dynamic_cast<const InetUnicastRouteEntry *>(entry)) {
     802          28 :             DBTable *table = NULL;
     803          28 :             if ((dynamic_cast<const AgentRoute *>(entry))->GetTableType()
     804          28 :                 == Agent::INET4_UNICAST)
     805          23 :                 table = vrf->GetInet4UnicastRouteTable();
     806             :             else
     807           5 :                 table = vrf->GetInet6UnicastRouteTable();
     808          28 :             rt = static_cast<AgentRoute *>(table->Find(entry));
     809             :         } else {
     810          16 :             DBTable *table = vrf->GetBridgeRouteTable();
     811          16 :             rt = static_cast<AgentRoute *>(table->Find(entry));
     812             :         }
     813          44 :         FreeRouteState(rt, gen_id);
     814          44 :         return true;
     815             :     }
     816             : 
     817           0 :     assert(0);
     818             :     return true;
     819             : }

Generated by: LCOV version 1.14