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

Generated by: LCOV version 1.14