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

Generated by: LCOV version 1.14