LCOV - code coverage report
Current view: top level - vnsw/agent/oper - mirror_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 64 432 14.8 %
Date: 2026-08-03 02:19:58 Functions: 13 45 28.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/bind/bind.hpp>
       6             : #include <base/logging.h>
       7             : #include <db/db.h>
       8             : #include <db/db_entry.h>
       9             : #include <db/db_table.h>
      10             : 
      11             : #include <cmn/agent_cmn.h>
      12             : #include <init/agent_param.h>
      13             : #include "oper/route_common.h"
      14             : #include "oper/nexthop.h"
      15             : #include "oper/tunnel_nh.h"
      16             : #include "oper/vrf.h"
      17             : #include "oper/mirror_table.h"
      18             : #include "oper/agent_sandesh.h"
      19             : #include <resource_manager/mirror_index.h>
      20             : using namespace std;
      21             : using namespace boost::asio;
      22             : using namespace boost::placeholders;
      23             : MirrorTable *MirrorTable::mirror_table_;
      24             : 
      25           6 : MirrorTable::~MirrorTable() {
      26           3 :     boost::system::error_code err;
      27           3 :     if (udp_sock_.get()) {
      28           3 :         udp_sock_->close(err);
      29             :     }
      30           6 : }
      31             : 
      32           0 : bool MirrorEntry::IsLess(const DBEntry &rhs) const {
      33           0 :     const MirrorEntry &a = static_cast<const MirrorEntry &>(rhs);
      34           0 :     return (analyzer_name_ < a.GetAnalyzerName());
      35             : }
      36             : 
      37           0 : DBEntryBase::KeyPtr MirrorEntry::GetDBRequestKey() const {
      38           0 :     MirrorEntryKey *key = new MirrorEntryKey(analyzer_name_);
      39           0 :     return DBEntryBase::KeyPtr(key);
      40             : }
      41             : 
      42           0 : void MirrorEntry::SetKey(const DBRequestKey *k) {
      43           0 :     const MirrorEntryKey *key = static_cast<const MirrorEntryKey *>(k);
      44           0 :     analyzer_name_ = key->analyzer_name_;
      45           0 : }
      46             : 
      47          60 : std::unique_ptr<DBEntry> MirrorTable::AllocEntry(const DBRequestKey *k) const {
      48          60 :     const MirrorEntryKey *key = static_cast<const MirrorEntryKey *>(k);
      49          60 :     MirrorEntry *mirror_entry = new MirrorEntry(key->analyzer_name_);
      50          60 :     return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(mirror_entry));
      51             : }
      52             : 
      53           0 : DBEntry *MirrorTable::Add(const DBRequest *req) {
      54           0 :     const MirrorEntryKey *key = static_cast<const MirrorEntryKey *>(req->key.get());
      55           0 :     MirrorEntry *mirror_entry = new MirrorEntry(key->analyzer_name_);
      56             :     ResourceManager::KeyPtr rkey(new MirrorIndexResourceKey
      57           0 :                                  (agent()->resource_manager(),
      58           0 :                                  key->analyzer_name_));
      59             :     uint32_t index = static_cast<IndexResourceData *>
      60           0 :         (agent()->resource_manager()->Allocate(rkey).get())->index();
      61           0 :     mirror_entry->set_mirror_index(index);
      62             :     //Get Mirror NH
      63           0 :     OnChange(mirror_entry, req);
      64           0 :     return mirror_entry;
      65           0 : }
      66             : 
      67           0 : bool MirrorTable::OnChange(MirrorEntry *mirror_entry) {
      68           0 :     bool ret = false;
      69           0 :     NextHop *nh = NULL;
      70           0 :     bool valid_nh = false;
      71           0 :     if (mirror_entry->mirror_flags_ ==
      72             :         MirrorEntryData::DynamicNH_Without_JuniperHdr) {
      73           0 :         VrfEntry *vrf = agent()->vrf_table()->FindVrfFromName(mirror_entry->vrf_name_);
      74             :         // mirror vrf should have been created
      75           0 :         if(vrf != NULL) {
      76           0 :             BridgeRouteKey key(agent()->evpn_peer(), mirror_entry->vrf_name_,
      77           0 :                                mirror_entry->mac_);
      78             :             BridgeRouteEntry *rt =  static_cast<BridgeRouteEntry *>
      79             :                 (static_cast<BridgeAgentRouteTable *>
      80           0 :                  (vrf->GetBridgeRouteTable())->FindActiveEntry(&key));
      81             : 
      82             :             // if route entry is preset assign the active nexthop to mirror entry
      83             :             // if route entry & active apath is not preset create discard nh
      84             :             //  and add it unresolved entry
      85           0 :             if (rt != NULL) {
      86           0 :                 const AgentPath *path = rt->GetActivePath();
      87           0 :                 nh = path->nexthop();
      88           0 :                 if (nh != NULL) {
      89           0 :                     mirror_entry->vni_ = rt->GetActiveLabel();
      90           0 :                     AddResolvedVrfMirrorEntry(mirror_entry);
      91           0 :                     valid_nh = true;
      92             :                 }
      93             :             }
      94           0 :         }
      95             :     } else { //StaticNH Without Juniper Hdr
      96             :         InetUnicastRouteEntry *rt =
      97           0 :             agent()->fabric_inet4_unicast_table()->FindLPM(mirror_entry->dip_);
      98             :         //if route entry is preset add the active next hop else add discard nh
      99           0 :         if (rt != NULL) {
     100           0 :             DBRequest nh_req;
     101           0 :             nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     102             :             // Do this only for v4, until we add support for v6
     103             :             // Typecast on v6 would cause an exception and would
     104             :             // assert in task.cc.
     105           0 :             if (mirror_entry->sip_.is_v4() && mirror_entry->dip_.is_v4()) {
     106             :                 TunnelNHKey *nh_key =
     107           0 :                 new TunnelNHKey(agent()->fabric_vrf_name(),
     108           0 :                                 mirror_entry->sip_.to_v4(),
     109           0 :                                 mirror_entry->dip_.to_v4(),
     110           0 :                                 false, TunnelType::VXLAN);
     111           0 :                 nh_req.key.reset(nh_key);
     112           0 :                 nh_req.data.reset(NULL);
     113           0 :                 agent()->nexthop_table()->Process(nh_req);
     114           0 :                 nh = static_cast<NextHop *>
     115           0 :                     (agent()->nexthop_table()->FindActiveEntry(nh_key));
     116           0 :                 if (nh != NULL) {
     117           0 :                     valid_nh = true;
     118           0 :                     AddResolvedVrfMirrorEntry(mirror_entry);
     119             :                 }
     120             :            }
     121           0 :         }
     122             :     }
     123             : 
     124             :     // if there is no Valid nh point it to discard nh
     125           0 :     if (!valid_nh) {
     126           0 :         DiscardNH key;
     127           0 :         nh = static_cast<NextHop *>
     128           0 :             (agent()->nexthop_table()->FindActiveEntry(&key));
     129           0 :             AddUnresolved(mirror_entry);
     130           0 :     }
     131             : 
     132           0 :     if (mirror_entry->nh_ != nh) {
     133           0 :         ret = true;
     134           0 :         mirror_entry->nh_ = nh;
     135             :     }
     136           0 :     return ret;
     137             : }
     138             : 
     139           0 : bool MirrorTable::OnChange(DBEntry *entry, const DBRequest *req) {
     140           0 :     bool ret = false;
     141           0 :     bool vrf_changed = false;
     142           0 :     MirrorEntry *mirror_entry = static_cast<MirrorEntry *>(entry);
     143           0 :     MirrorEntryData *data = static_cast<MirrorEntryData *>(req->data.get());
     144             : 
     145             :     // Check for nic assisted supported ignore creating NH.
     146             :     // if there is any change from  non nic to nic assited mirroring.
     147             :     // delete if there are any previously allocated resources for mirror entry.
     148           0 :     if (data->nic_assisted_mirroring_ !=
     149           0 :         mirror_entry->nic_assisted_mirroring_) {
     150           0 :         if (!mirror_entry->nic_assisted_mirroring_) {
     151           0 :             DeleteMirrorVrf(mirror_entry, true);
     152           0 :             mirror_entry->nh_ = NULL;
     153           0 :             mirror_entry->vrf_ = NULL;
     154             :         }
     155           0 :         mirror_entry->nic_assisted_mirroring_ =
     156           0 :             data->nic_assisted_mirroring_;
     157           0 :         mirror_entry->nic_assisted_mirroring_vlan_ =
     158           0 :             data->nic_assisted_mirroring_vlan_;
     159           0 :         if (mirror_entry->nic_assisted_mirroring_)
     160           0 :             return true;
     161           0 :     } else if (data->nic_assisted_mirroring_){
     162           0 :         mirror_entry->nic_assisted_mirroring_vlan_ =
     163           0 :             data->nic_assisted_mirroring_vlan_;
     164           0 :         return true;
     165             :     }
     166             : 
     167           0 :     if (mirror_entry->vrf_name_ != data->vrf_name_) {
     168           0 :         vrf_changed = true;
     169             :     }
     170           0 :     if (vrf_changed || (mirror_entry->mirror_flags_ != data->mirror_flags_)) {
     171           0 :         DeleteMirrorVrf(mirror_entry, vrf_changed);
     172           0 :         mirror_entry->vrf_name_ = data->vrf_name_;
     173             :     }
     174             : 
     175           0 :     mirror_entry->sip_ = data->sip_;
     176           0 :     mirror_entry->sport_ = data->sport_;
     177           0 :     mirror_entry->dip_ = data->dip_;
     178           0 :     mirror_entry->dport_ = data->dport_;
     179           0 :     mirror_entry->mirror_flags_ = data->mirror_flags_;
     180             :     // Check for any Vxlan changes.
     181           0 :     if (mirror_entry->vni_ != data->vni_) {
     182           0 :         mirror_entry->vni_ = data->vni_;
     183           0 :         ret = true;
     184             :     }
     185           0 :     mirror_entry->mac_ = data->mac_;
     186           0 :     if (!mirror_entry->createdvrf_) {
     187           0 :         mirror_entry->createdvrf_ = data->createdvrf_;
     188             :     }
     189           0 :     if (mirror_entry->mirror_flags_ == MirrorEntryData::DynamicNH_Without_JuniperHdr ||
     190           0 :         mirror_entry->mirror_flags_ == MirrorEntryData::StaticNH_Without_JuniperHdr)
     191             :     {
     192           0 :         ret |= OnChange(mirror_entry);
     193           0 :         return ret;
     194             :     }
     195             : 
     196           0 :     DBRequest nh_req;
     197           0 :     nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     198           0 :     MirrorNHKey *nh_key = new MirrorNHKey(data->vrf_name_, data->sip_,
     199           0 :                                   data->sport_, data->dip_, data->dport_);
     200           0 :     nh_req.key.reset(nh_key);
     201           0 :     nh_req.data.reset(NULL);
     202           0 :     agent()->nexthop_table()->Process(nh_req);
     203             : 
     204             :     /* For service-chain based mirroring, vrf will always be empty. In this
     205             :      * case we should create MirrorNH even when VRF is NULL */
     206           0 :     bool check_for_vrf = false;
     207           0 :     VrfEntry *vrf = NULL;
     208           0 :     if (!data->vrf_name_.empty()) {
     209           0 :         VrfKey key(data->vrf_name_);
     210           0 :         vrf = static_cast<VrfEntry *>(agent()->vrf_table()->
     211           0 :                                       FindActiveEntry(&key));
     212           0 :         check_for_vrf = true;
     213           0 :     }
     214             : 
     215           0 :     NextHop *nh = static_cast<NextHop *>
     216           0 :                   (agent()->nexthop_table()->FindActiveEntry(nh_key));
     217           0 :     if (nh == NULL || (check_for_vrf && vrf == NULL)) {
     218             :         //Make the mirror NH point to discard
     219             :         //and change the nexthop once the VRF is
     220             :         //available
     221           0 :         AddUnresolved(mirror_entry);
     222           0 :         DiscardNH key;
     223           0 :         nh = static_cast<NextHop *>
     224           0 :             (agent()->nexthop_table()->FindActiveEntry(&key));
     225           0 :     } else {
     226           0 :         AddResolvedVrfMirrorEntry(mirror_entry);
     227             :     }
     228             : 
     229           0 :     if (mirror_entry->nh_ != nh) {
     230           0 :         mirror_entry->nh_ = nh;
     231             :         mirror_entry->vrf_ =
     232           0 :             agent()->vrf_table()->FindVrfFromName(data->vrf_name_);
     233           0 :         ret = true;
     234             :     }
     235           0 :     return ret;
     236           0 : }
     237             : 
     238           0 : bool MirrorTable::Delete(DBEntry *entry, const DBRequest *request) {
     239           0 :     MirrorEntry *mirror_entry = static_cast<MirrorEntry *>(entry);
     240           0 :     agent()->resource_manager()->Release(Resource::MIRROR_INDEX,
     241             :                                          mirror_entry->mirror_index());
     242           0 :     DeleteMirrorVrf(mirror_entry, true);
     243           0 :     return true;
     244             : }
     245             : 
     246           0 : void MirrorTable::DeleteMirrorVrf(MirrorEntry *entry, bool del_from_vrf_list) {
     247           0 :     if (del_from_vrf_list) {
     248           0 :         RemoveUnresolved(entry);
     249           0 :         DeleteResolvedVrfMirrorEntry(entry);
     250             :     }
     251           0 :     if (entry->mirror_flags_ == MirrorEntryData::DynamicNH_Without_JuniperHdr) {
     252             :         VrfEntry *vrf =
     253           0 :             agent()->vrf_table()->FindVrfFromName(entry->vrf_name_);
     254           0 :         if (vrf) {
     255           0 :             bool confvrf = vrf->flags() & VrfData::ConfigVrf;
     256           0 :             bool gwvrf = vrf->flags() & VrfData::GwVrf;
     257           0 :             if (entry->createdvrf_ && !confvrf && !gwvrf)
     258           0 :                 agent()->vrf_table()->DeleteVrfReq(entry->vrf_name_,
     259             :                                                    VrfData::MirrorVrf);
     260             :         }
     261             :     }
     262           0 : }
     263             : 
     264           0 : void MirrorTable::Add(VrfMirrorEntryList &vrf_entry_map, MirrorEntry *entry) {
     265           0 :     VrfMirrorEntryList::iterator it = vrf_entry_map.find(entry->vrf_name_);
     266             : 
     267           0 :     if (it != vrf_entry_map.end()) {
     268           0 :         MirrorEntryList::const_iterator list_it = it->second.begin();
     269           0 :         for (; list_it != it->second.end(); list_it++) {
     270           0 :             if (*list_it == entry) {
     271             :                 //Entry already present
     272           0 :                 return;
     273             :             }
     274             :         }
     275           0 :         it->second.push_back(entry);
     276           0 :         return;
     277             :     }
     278             : 
     279           0 :     MirrorEntryList list;
     280           0 :     list.push_back(entry);
     281           0 :     vrf_entry_map.insert(VrfMirrorEntry(entry->vrf_name_, list));
     282           0 : }
     283             : 
     284           0 : void MirrorTable::Delete(VrfMirrorEntryList &list, MirrorEntry *entry) {
     285           0 :     VrfMirrorEntryList::iterator it = list.find(entry->vrf_name_);
     286           0 :     if (it == list.end()) {
     287           0 :         return;
     288             :     }
     289             : 
     290           0 :     MirrorEntryList::iterator list_it = it->second.begin();
     291           0 :     for(;list_it != it->second.end(); list_it++) {
     292           0 :         if (*list_it == entry) {
     293           0 :             it->second.erase(list_it);
     294           0 :             break;
     295             :         }
     296             :     }
     297             : }
     298             : 
     299         106 : void MirrorTable::ResyncMirrorEntry(VrfMirrorEntryList &list,
     300             :                                     const VrfEntry *vrf) {
     301         106 :     VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
     302         106 :     if (it == list.end()) {
     303         106 :         return;
     304             :     }
     305             : 
     306           0 :     MirrorEntryList::iterator list_it = it->second.begin();
     307           0 :     for(;list_it != it->second.end(); list_it++) {
     308           0 :         DBRequest req;
     309           0 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     310             : 
     311           0 :         MirrorEntryKey *key = new MirrorEntryKey((*list_it)->GetAnalyzerName());
     312           0 :         key->sub_op_ = AgentKey::RESYNC;
     313           0 :         MirrorEntryData *data = new MirrorEntryData((*list_it)->vrf_name(),
     314           0 :                 *((*list_it)->GetSip()),
     315           0 :                 (*list_it)->GetSPort(),
     316           0 :                 *((*list_it)->GetDip()),
     317           0 :                 (*list_it)->GetDPort(), (*list_it)->GetMirrorFlag(),
     318           0 :                  (*list_it)->GetVni(), *((*list_it)->GetMac()),
     319           0 :                  (*list_it)->GetCreatedVrf());
     320           0 :         req.key.reset(key);
     321           0 :         req.data.reset(data);
     322           0 :         Enqueue(&req);
     323           0 :     }
     324           0 :     list.erase(it);
     325             : }
     326             : 
     327           0 : void MirrorTable::AddUnresolved(MirrorEntry *entry) {
     328           0 :     Add(unresolved_entry_list_, entry);
     329           0 : }
     330             : 
     331           0 : void MirrorTable::RemoveUnresolved(MirrorEntry *entry) {
     332           0 :     Delete(unresolved_entry_list_, entry);
     333           0 : }
     334             : 
     335           0 : void MirrorTable::AddResolvedVrfMirrorEntry(MirrorEntry *entry) {
     336           0 :     Add(resolved_entry_list_, entry);
     337           0 : }
     338             : 
     339           0 : void MirrorTable::DeleteResolvedVrfMirrorEntry(MirrorEntry *entry) {
     340           0 :     Delete(resolved_entry_list_, entry);
     341           0 : }
     342             : 
     343          88 : void MirrorTable::ResyncResolvedMirrorEntry(const VrfEntry *vrf) {
     344          88 :     ResyncMirrorEntry(resolved_entry_list_, vrf);
     345          88 : }
     346             : 
     347          18 : void MirrorTable::ResyncUnresolvedMirrorEntry(const VrfEntry *vrf) {
     348          18 :     ResyncMirrorEntry(unresolved_entry_list_, vrf);
     349          18 : }
     350             : 
     351             : 
     352           0 : void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
     353             :                                        const std::string &vrf_name,
     354             :                                        const IpAddress &sip, uint16_t sport,
     355             :                                        const IpAddress &dip, uint16_t dport,
     356             :                                        uint32_t vni, uint8_t mirror_flag,
     357             :                                        const MacAddress &mac) {
     358           0 :     Agent *agent = Agent::GetInstance();
     359           0 :     bool createdvrf = false;
     360           0 :     DBRequest req;
     361             : 
     362           0 :     if (dip.is_v6() && vrf_name == mirror_table_->agent()->fabric_vrf_name()) {
     363           0 :         LOG(ERROR, "Ipv6 as destination not supported on Fabric VRF: " <<
     364             :             dip.to_string());
     365           0 :         return;
     366             :     }
     367             :     // if Mirror VRF is not preset create the vrf.
     368             :     // creatation of VRF ensures all the routes will be dowloaded from control node.
     369           0 :     if (mirror_flag == MirrorEntryData::DynamicNH_Without_JuniperHdr) {
     370           0 :         VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name);
     371           0 :         if (vrf == NULL) {
     372           0 :             agent->vrf_table()->CreateVrfReq(vrf_name, VrfData::MirrorVrf);
     373           0 :             createdvrf = true;
     374             :         }
     375             :     }
     376           0 :     MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
     377             :     MirrorEntryData *data = new MirrorEntryData(vrf_name, sip, sport, dip,
     378             :                                                 dport, mirror_flag, vni, mac,
     379           0 :                                                 createdvrf);
     380           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     381           0 :     req.key.reset(key);
     382           0 :     req.data.reset(data);
     383           0 :     mirror_table_->Enqueue(&req);
     384           0 : }
     385             : 
     386           0 : void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
     387             :                                  const std::string &vrf_name,
     388             :                                  const IpAddress &sip, uint16_t sport,
     389             :                                  const IpAddress &dip, uint16_t dport) {
     390             : 
     391           0 :     DBRequest req;
     392             : 
     393           0 :     if (dip.is_v6() && vrf_name == mirror_table_->agent()->fabric_vrf_name()) {
     394           0 :         LOG(ERROR, "Ipv6 as destination not supported on Fabric VRF: " <<
     395             :             dip.to_string());
     396           0 :         return;
     397             :     }
     398             :     // First enqueue request to add Mirror NH
     399           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     400             : 
     401           0 :     MirrorNHKey *nh_key = new MirrorNHKey(vrf_name, sip, sport, dip, dport);
     402           0 :     req.key.reset(nh_key);
     403           0 :     req.data.reset(NULL);
     404           0 :     mirror_table_->agent()->nexthop_table()->Enqueue(&req);
     405             : 
     406           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     407           0 :     MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
     408             :     MirrorEntryData *data = new MirrorEntryData(vrf_name, sip,
     409             :                                                 sport, dip, dport, 1, 0 ,
     410           0 :                                                 MacAddress::ZeroMac(), false);
     411           0 :     req.key.reset(key);
     412           0 :     req.data.reset(data);
     413           0 :     mirror_table_->Enqueue(&req);
     414           0 : }
     415             : 
     416           0 : void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
     417             :                                  uint32_t nic_assisted_mirroring_vlan) {
     418           0 :     DBRequest req;
     419           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     420           0 :     MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
     421           0 :     MirrorEntryData *data = new MirrorEntryData(true, nic_assisted_mirroring_vlan);
     422           0 :     req.key.reset(key);
     423           0 :     req.data.reset(data);
     424           0 :     mirror_table_->Enqueue(&req);
     425           0 : }
     426             : 
     427             : 
     428           0 : void MirrorTable::DelMirrorEntry(const std::string &analyzer_name) {
     429           0 :     DBRequest req;
     430           0 :     req.oper = DBRequest::DB_ENTRY_DELETE;
     431           0 :     MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
     432           0 :     req.key.reset(key);
     433           0 :     req.data.reset(NULL);
     434           0 :     mirror_table_->Enqueue(&req);
     435           0 : }
     436             : 
     437           0 : void MirrorTable::OnZeroRefcount(AgentDBEntry *e) {
     438           0 :     const MirrorEntry *mirr_entry = static_cast<const MirrorEntry *>(e);
     439           0 :     DelMirrorEntry(mirr_entry->GetAnalyzerName());
     440           0 : }
     441             : 
     442           3 : DBTableBase *MirrorTable::CreateTable(DB *db, const std::string &name) {
     443           3 :     mirror_table_ = new MirrorTable(db, name);
     444           3 :     mirror_table_->Init();
     445           3 :     return mirror_table_;
     446             : };
     447             : 
     448           3 : void MirrorTable::Initialize() {
     449           3 :     VrfListenerInit();
     450           3 : }
     451             : 
     452           3 : void MirrorTable::VrfListenerInit() {
     453           3 :     vrf_listener_id_ = agent()->vrf_table()->
     454           3 :                            Register(boost::bind(&MirrorTable::VrfNotify,
     455             :                                     this, _1, _2));
     456           3 : }
     457             : 
     458         106 : void MirrorTable::VrfNotify(DBTablePartBase *base, DBEntryBase *entry) {
     459         106 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
     460             :     MirrorVrfState *state = static_cast<MirrorVrfState *>
     461         106 :         (vrf->GetState(base->parent(), vrf_listener_id_));
     462         106 :     if (vrf->IsDeleted()) {
     463          88 :         if (state) {
     464           0 :             UnRegisterBridgeRouteTableListener(vrf, state);
     465           0 :             vrf->ClearState(base->parent(), vrf_listener_id_);
     466           0 :             delete state;
     467             :         }
     468             :         //VRF is getting deleted remove all the mirror nexthop
     469          88 :         ResyncResolvedMirrorEntry(vrf);
     470          88 :         return;
     471             :     }
     472             : 
     473             :    // This will be for dynamic witout juniper header, to resolve the
     474             :    // bridge entry lookup
     475          18 :     bool miror_vrf = UnresolvedMirrorVrf(vrf, unresolved_entry_list_);
     476          18 :     if (state == NULL && miror_vrf) {
     477           0 :         state = new MirrorVrfState();
     478           0 :         state->seen_ = true;
     479           0 :         vrf->SetState(base->parent(), vrf_listener_id_, state);
     480           0 :         if (state->bridge_rt_table_listener_id_ == DBTableBase::kInvalidId) {
     481             :             BridgeAgentRouteTable *bridge_table =
     482             :                                             static_cast<BridgeAgentRouteTable *>
     483           0 :                                             (vrf->GetBridgeRouteTable());
     484           0 :             state->bridge_rt_table_listener_id_ =
     485           0 :             bridge_table->Register(boost::bind(&MirrorTable::BridgeRouteTableNotify,
     486             :                                                this, _1, _2));
     487             :         }
     488             :     }
     489          18 :     ResyncUnresolvedMirrorEntry(vrf);
     490             : }
     491             : 
     492          18 : bool MirrorTable::UnresolvedMirrorVrf(const VrfEntry *vrf,
     493             :                                       VrfMirrorEntryList &list){
     494          18 :     VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
     495          18 :     if (it == list.end()) {
     496          18 :         return false;
     497             :     }
     498             :     // Need to check if there are any entries with DynamicNH_Without_JuniperHdr
     499           0 :     MirrorEntryList::iterator list_it = it->second.begin();
     500           0 :     for(;list_it != it->second.end(); list_it++) {
     501           0 :         if ((*list_it)->GetMirrorFlag() ==
     502             :             MirrorEntryData::DynamicNH_Without_JuniperHdr) {
     503           0 :             return true;
     504             :         }
     505             :     }
     506           0 :     return false;
     507             : }
     508             : // if the Unresolved remote mac is present it will return the entry
     509             : MirrorEntry*
     510           0 : MirrorTable::GetMirrorEntry(VrfEntry *vrf, const MacAddress & mac,
     511             :                                    VrfMirrorEntryList &list) {
     512           0 :     VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
     513           0 :     if (it == list.end()) {
     514           0 :         return NULL;
     515             :     }
     516           0 :     MirrorEntryList::iterator list_it = it->second.begin();
     517           0 :     for(;list_it != it->second.end(); list_it++) {
     518           0 :         const MacAddress &remote_vm_mac = *((*list_it)->GetMac());
     519           0 :         if (remote_vm_mac == mac) {
     520           0 :             return (*list_it);
     521             :         }
     522             :     }
     523           0 :     return NULL;
     524             : }
     525             : 
     526             : 
     527           0 : void MirrorTable::BridgeRouteTableNotify(DBTablePartBase *partition,
     528             :                                        DBEntryBase *entry) {
     529           0 :     const BridgeRouteEntry *bridge_rt = static_cast<const BridgeRouteEntry *>(entry);
     530           0 :     if (bridge_rt->IsDeleted()) {
     531           0 :         ResyncResolvedMirrorEntry(bridge_rt->vrf());
     532             :     } else {
     533           0 :         MirrorEntry *unresolved_mirror_entry = GetMirrorEntry(bridge_rt->vrf(),
     534           0 :                                                               bridge_rt->prefix_address(),
     535           0 :                                                               unresolved_entry_list_);
     536           0 :         MirrorEntry *resolved_mirror_entry = GetMirrorEntry(bridge_rt->vrf(),
     537           0 :                                                             bridge_rt->prefix_address(),
     538           0 :                                                             resolved_entry_list_);
     539             :         // Check for Both resolved and unresolved list for Change in route
     540           0 :         if (unresolved_mirror_entry &&
     541           0 :             unresolved_mirror_entry->mirror_flags_ ==
     542             :             MirrorEntryData::DynamicNH_Without_JuniperHdr) {
     543           0 :             ResyncUnresolvedMirrorEntry(bridge_rt->vrf());
     544           0 :         } else if (resolved_mirror_entry &&
     545           0 :                    ((resolved_mirror_entry->vni_ != bridge_rt->GetActiveLabel()) ||
     546           0 :                    (resolved_mirror_entry->nh_ !=
     547             :                     bridge_rt->GetActivePath()->nexthop()))) {
     548           0 :             ResyncResolvedMirrorEntry(bridge_rt->vrf());
     549             :         }
     550             :     }
     551           0 : }
     552             : 
     553           0 : void MirrorTable::UnRegisterBridgeRouteTableListener(const VrfEntry *vrf,
     554             :                                                      MirrorVrfState *state) {
     555           0 :     if (state->bridge_rt_table_listener_id_ == DBTableBase::kInvalidId)
     556           0 :         return;
     557             :     BridgeAgentRouteTable *bridge_table = static_cast<BridgeAgentRouteTable *>
     558           0 :         (vrf->GetBridgeRouteTable());
     559           0 :     bridge_table->Unregister(state->bridge_rt_table_listener_id_);
     560           0 :     state->bridge_rt_table_listener_id_ = DBTableBase::kInvalidId;
     561             : }
     562             : 
     563           0 : void MirrorTable::ReadHandler(const boost::system::error_code &ec,
     564             :                               size_t bytes_transferred) {
     565             : 
     566           0 :     if (ec) {
     567           0 :         LOG(ERROR, "Error reading from Mirror sock. Error : " <<
     568             :             boost::system::system_error(ec).what());
     569           0 :         return;
     570             :     }
     571             : 
     572           0 :     udp_sock_->async_receive(boost::asio::buffer(rx_buff_, sizeof(rx_buff_)),
     573           0 :                            boost::bind(&MirrorTable::ReadHandler, this,
     574             :                                        boost::asio::placeholders::error,
     575             :                                        boost::asio::placeholders::bytes_transferred));
     576             : }
     577             : 
     578           3 : void MirrorTable::MirrorSockInit(void) {
     579             :     EventManager *event_mgr;
     580             : 
     581           3 :     event_mgr = agent()->event_manager();
     582           3 :     boost::asio::io_service &io = *event_mgr->io_service();
     583           6 :     ip::udp::endpoint ep(ip::udp::v4(),
     584           3 :                          agent()->params()->mirror_client_port());
     585             : 
     586           3 :     udp_sock_.reset(new ip::udp::socket(io));
     587             : 
     588           3 :     boost::system::error_code ec;
     589           3 :     udp_sock_->open(ip::udp::v4(), ec);
     590           3 :     assert(ec.value() == 0);
     591             : 
     592           3 :     udp_sock_->bind(ep, ec);
     593           3 :     if (ec.value() != 0) {
     594           0 :         ep.port(0);
     595           0 :         udp_sock_->bind(ep, ec);
     596           0 :         assert(ec.value() == 0);
     597             :     }
     598             : 
     599           3 :     ip::udp::endpoint sock_ep = udp_sock_->local_endpoint(ec);
     600           3 :     assert(ec.value() == 0);
     601           3 :     agent()->set_mirror_port(sock_ep.port());
     602             : 
     603           6 :     udp_sock_->async_receive(boost::asio::buffer(rx_buff_, sizeof(rx_buff_)),
     604           3 :                              boost::bind(&MirrorTable::ReadHandler, this,
     605             :                                          boost::asio::placeholders::error,
     606             :                                          boost::asio::placeholders::bytes_transferred));
     607           3 : }
     608             : 
     609           0 : VrfEntry *MirrorTable::FindVrfEntry(const string &vrf_name) const {
     610           0 :     return agent()->vrf_table()->FindVrfFromName(vrf_name);
     611             : }
     612             : 
     613           3 : void MirrorTable::Shutdown() {
     614           3 :     agent()->vrf_table()->Unregister(vrf_listener_id_);
     615           3 : }
     616             : 
     617           0 : bool MirrorTable::IsConfigured() {
     618           0 :     VrfMirrorEntryList::iterator it;
     619           0 :     for (it = resolved_entry_list_.begin(); it != resolved_entry_list_.end(); ++it) {
     620           0 :         if (it->second.size() > 0) {
     621           0 :             return true;
     622             :         }
     623             :     }
     624           0 :     return false;
     625             : }
     626             : 
     627           0 : uint32_t MirrorEntry::vrf_id() const {
     628           0 :     return vrf_ ? vrf_->vrf_id() : uint32_t(-1);
     629             : }
     630             : 
     631           0 : const VrfEntry *MirrorEntry::GetVrf() const {
     632           0 :     return vrf_ ? vrf_.get() : NULL;
     633             : }
     634             : 
     635           0 : void MirrorEntry::set_mirror_entrySandeshData(MirrorEntrySandeshData &data) const {
     636           0 :     data.set_analyzer_name(GetAnalyzerName());
     637           0 :     data.set_sip(GetSip()->to_string());
     638           0 :     data.set_dip(GetDip()->to_string());
     639           0 :     data.set_vrf(GetVrf() ? GetVrf()->GetName() : "");
     640           0 :     data.set_sport(GetSPort());
     641           0 :     data.set_dport(GetDPort());
     642           0 :     data.set_ref_count(GetRefCount());
     643           0 :     if (nh_) {
     644           0 :         nh_->SetNHSandeshData(data.nh);
     645             :     }
     646           0 : }
     647             : 
     648           0 : bool MirrorEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
     649           0 :     MirrorEntryResp *resp = static_cast<MirrorEntryResp *>(sresp);
     650             : 
     651           0 :     MirrorEntrySandeshData data;
     652           0 :     set_mirror_entrySandeshData(data);
     653             :     std::vector<MirrorEntrySandeshData> &list =
     654             :         const_cast<std::vector<MirrorEntrySandeshData>&>
     655           0 :         (resp->get_mirror_entry_list());
     656           0 :     list.push_back(data);
     657             : 
     658           0 :     return true;
     659           0 : }
     660             : 
     661           0 : void MirrorEntryReq::HandleRequest() const {
     662           0 :     AgentSandeshPtr sand(new AgentMirrorSandesh(context(), get_analyzer_name()));
     663           0 :     sand->DoSandesh(sand);
     664           0 : }
     665             : 
     666           0 : AgentSandeshPtr MirrorTable::GetAgentSandesh(const AgentSandeshArguments *args,
     667             :                                              const std::string &context) {
     668             :     return AgentSandeshPtr(new AgentMirrorSandesh(context,
     669           0 :                                             args->GetString("analyzer_name")));
     670             : }
     671             : 
     672             : MirrorEntryData::MirrorEntryFlags
     673           0 : MirrorTable::DecodeMirrorFlag (const std::string &nh_mode, bool juniper_header) {
     674           0 :     std::string str = "static";
     675           0 :     if (juniper_header) {
     676           0 :         if (boost::iequals(nh_mode, str))
     677           0 :             return MirrorEntryData::StaticNH_With_JuniperHdr;
     678           0 :         return MirrorEntryData::DynamicNH_With_JuniperHdr;
     679             :     } else {
     680           0 :         if (boost::iequals(nh_mode, str))
     681           0 :             return MirrorEntryData::StaticNH_Without_JuniperHdr;
     682           0 :         return MirrorEntryData::DynamicNH_Without_JuniperHdr;
     683             :     }
     684           0 : }

Generated by: LCOV version 1.14