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

Generated by: LCOV version 1.14