LCOV - code coverage report
Current view: top level - vnsw/agent/oper - multicast.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 332 981 33.8 %
Date: 2026-11-09 02:10:49 Functions: 30 67 44.8 %
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/uuid/uuid_io.hpp>
       7             : #include <cmn/agent_cmn.h>
       8             : #include <init/agent_param.h>
       9             : 
      10             : #include <base/logging.h>
      11             : #include <oper/operdb_init.h>
      12             : #include <oper/route_common.h>
      13             : #include <oper/interface_common.h>
      14             : #include <oper/nexthop.h>
      15             : #include <oper/tunnel_nh.h>
      16             : #include <oper/vrf.h>
      17             : #include <oper/agent_sandesh.h>
      18             : #include <oper/multicast.h>
      19             : #include <oper/mirror_table.h>
      20             : #include <oper/mpls.h>
      21             : #include <oper/bridge_domain.h>
      22             : #include <oper/inet4_multicast_route.h>
      23             : #include <oper/physical_device.h>
      24             : #include <oper/agent_route_walker.h>
      25             : #include <oper/tsn_elector.h>
      26             : #include <xmpp/xmpp_channel.h>
      27             : #include <controller/controller_init.h>
      28             : #include <controller/controller_peer.h>
      29             : #include <controller/controller_route_path.h>
      30             : 
      31             : #include <sandesh/sandesh_types.h>
      32             : #include <sandesh/sandesh_constants.h>
      33             : #include <sandesh/sandesh.h>
      34             : #include <sandesh/sandesh_trace.h>
      35             : 
      36             : using namespace std;
      37             : using namespace boost::uuids;
      38             : 
      39             : #define INVALID_PEER_IDENTIFIER ControllerPeerPath::kInvalidPeerIdentifier
      40             : 
      41             : MulticastHandler *MulticastHandler::obj_;
      42             : SandeshTraceBufferPtr MulticastTraceBuf(SandeshTraceBufferCreate("Multicast",
      43             :                                                                      1000));
      44             : const Ip4Address MulticastHandler::kBroadcast = Ip4Address(0xFFFFFFFF);
      45             : /*
      46             :  * Registeration for notification
      47             :  * VM - Looking for local VM added
      48             :  * VN - Looking for subnet information from VN
      49             :  * Enable trace print messages
      50             :  */
      51           2 : void MulticastHandler::Register() {
      52           2 :     vn_listener_id_ = agent_->vn_table()->Register(
      53             :         boost::bind(&MulticastHandler::ModifyVN, this, _1, _2));
      54           2 :     vrf_listener_id_ = agent_->vrf_table()->Register(
      55             :         boost::bind(&MulticastHandler::ModifyVRF, this, _1, _2));
      56           2 :     interface_listener_id_ = agent_->interface_table()->Register(
      57             :         boost::bind(&MulticastHandler::ModifyVmInterface, this, _1, _2));
      58           2 :     bridge_domain_id_ = agent_->bridge_domain_table()->Register(
      59             :             boost::bind(&MulticastHandler::AddBridgeDomain, this, _1, _2));
      60           2 :     physical_device_listener_id_ = DBTable::kInvalidId;
      61           2 :     if (agent_->tsn_no_forwarding_enabled()) {
      62           0 :         physical_device_listener_id_ = agent_->physical_device_table()->
      63           0 :             Register(boost::bind(&MulticastHandler::NotifyPhysicalDevice,
      64             :                                  this, _1, _2));
      65           0 :         agent_->oper_db()->agent_route_walk_manager()->
      66           0 :             RegisterWalker(static_cast<AgentRouteWalker *>(te_walker_.get()));
      67             :     }
      68             : 
      69           2 :     GetMulticastObjList().clear();
      70           2 : }
      71             : 
      72           2 : void MulticastHandler::Terminate() {
      73           2 :     agent_->vn_table()->Unregister(vn_listener_id_);
      74           2 :     agent_->interface_table()->Unregister(interface_listener_id_);
      75           2 :     agent_->vrf_table()->Unregister(vrf_listener_id_);
      76           2 :     agent_->bridge_domain_table()->Unregister(bridge_domain_id_);
      77           2 :     if (physical_device_listener_id_ != DBTable::kInvalidId) {
      78           0 :         agent_->physical_device_table()->
      79           0 :             Unregister(physical_device_listener_id_);
      80             :     }
      81           2 :     if (te_walker_.get()) {
      82           0 :         agent_->oper_db()->agent_route_walk_manager()->
      83           0 :             ReleaseWalker(te_walker_.get());
      84           0 :         te_walker_.reset();
      85             :     }
      86           2 : }
      87             : 
      88         124 : void MulticastHandler::AddL2BroadcastRoute(MulticastGroupObject *obj,
      89             :                                            const string &vrf_name,
      90             :                                            const string &vn_name,
      91             :                                            const Ip4Address &addr,
      92             :                                            uint32_t label,
      93             :                                            int vxlan_id,
      94             :                                            uint32_t ethernet_tag)
      95             : {
      96         124 :     if (obj->pbb_vrf() && obj->dependent_mg() == NULL) {
      97          47 :         return;
      98             :     }
      99             : 
     100         124 :     boost::system::error_code ec;
     101         124 :     MCTRACE(Log, "add L2 bcast route ", vrf_name, addr.to_string(), 0);
     102             :     //Add Bridge FF:FF:FF:FF:FF:FF
     103             :     ComponentNHKeyList component_nh_key_list =
     104         124 :         GetInterfaceComponentNHKeyList(obj, InterfaceNHFlags::BRIDGE);
     105         124 :     if (component_nh_key_list.size() == 0)
     106          47 :         return;
     107          77 :     uint32_t route_tunnel_bmap = TunnelType::AllType();
     108             :     AgentRouteData *data =
     109          77 :         BridgeAgentRouteTable::BuildNonBgpPeerData(vrf_name,
     110             :                                                    vn_name,
     111             :                                                    label,
     112             :                                                    vxlan_id,
     113             :                                                    route_tunnel_bmap,
     114             :                                                    Composite::L2INTERFACE,
     115             :                                                    component_nh_key_list,
     116          77 :                                                    obj->pbb_vrf(),
     117          77 :                                                    obj->learning_enabled());
     118          77 :     BridgeAgentRouteTable::AddBridgeBroadcastRoute(agent_->local_vm_peer(),
     119             :                                                    vrf_name,
     120             :                                                    ethernet_tag,
     121             :                                                    data);
     122         124 : }
     123             : 
     124             : /*
     125             :  * Route address 255.255.255.255 deletion from last VM in VN del
     126             :  */
     127         119 : void MulticastHandler::DeleteBroadcast(const Peer *peer,
     128             :                                        const std::string &vrf_name,
     129             :                                        uint32_t ethernet_tag,
     130             :                                        COMPOSITETYPE type)
     131             : {
     132         119 :     boost::system::error_code ec;
     133         119 :     MCTRACE(Log, "delete bcast route ", vrf_name, "255.255.255.255", 0);
     134         119 :     BridgeAgentRouteTable::DeleteBroadcastReq(peer, vrf_name, ethernet_tag,
     135             :                                               type);
     136         119 :     ComponentNHKeyList component_nh_key_list; //dummy list
     137         119 : }
     138             : 
     139           0 : void MulticastHandler::HandleVxLanChange(const VnEntry *vn) {
     140           0 :     if (vn->IsDeleted() || !vn->GetVrf())
     141           0 :         return;
     142             : 
     143             :     MulticastGroupObject *obj =
     144           0 :         FindFloodGroupObject(vn->GetVrf()->GetName());
     145           0 :     if (!obj || obj->IsDeleted())
     146           0 :         return;
     147             : 
     148           0 :     uint32_t new_vxlan_id = vn->GetVxLanId();
     149             : 
     150           0 :     if (new_vxlan_id != obj->vxlan_id()) {
     151           0 :         boost::system::error_code ec;
     152           0 :         Ip4Address broadcast =  IpAddress::from_string("255.255.255.255",
     153           0 :                                                        ec).to_v4();
     154           0 :         obj->set_vxlan_id(new_vxlan_id);
     155             :         //Rebake new vxlan id in mcast route
     156           0 :         AddL2BroadcastRoute(obj, vn->GetVrf()->GetName(), vn->GetName(),
     157             :                             broadcast, MplsTable::kInvalidLabel, new_vxlan_id, 0);
     158             :     }
     159             : }
     160             : 
     161         269 : void MulticastHandler::HandleVnParametersChange(DBTablePartBase *partition,
     162             :                                              DBEntryBase *e) {
     163         269 :     VnEntry *vn = static_cast<VnEntry *>(e);
     164         269 :     bool deleted = false;
     165             : 
     166             :     //Extract paramters from VN.
     167         269 :     const VrfEntry *vrf = vn->GetVrf();
     168         269 :     uint32_t vn_vxlan_id = vn->GetVxLanId();
     169             : 
     170             :     MulticastDBState *state = static_cast<MulticastDBState *>
     171         269 :         (vn->GetState(partition->parent(), vn_listener_id_));
     172             : 
     173         269 :     deleted = vn->IsDeleted() || !(vrf);
     174             :     //Extract old parameters from state
     175         269 :     uint32_t old_vxlan_id = state ? state->vxlan_id_ : 0;
     176             : 
     177         269 :     boost::system::error_code ec;
     178         269 :     Ip4Address broadcast =  IpAddress::from_string("255.255.255.255",
     179         269 :                                                    ec).to_v4();
     180             :     //Add operation
     181         269 :     if (!deleted) {
     182             :         MulticastGroupObject *all_broadcast =
     183         124 :             FindFloodGroupObject(vn->GetVrf()->GetName());
     184             : 
     185         124 :         if (!state) {
     186          66 :             state = new MulticastDBState(vn->GetVrf()->GetName(),
     187          66 :                                          vn_vxlan_id);
     188          66 :             vn->SetState(partition->parent(), vn_listener_id_, state);
     189             :             //Also create multicast object
     190          66 :             if (all_broadcast == NULL) {
     191          42 :                 all_broadcast = CreateMulticastGroupObject(state->vrf_name_,
     192          84 :                                         vn->GetName(), Ip4Address(), broadcast,
     193             :                                         state->vxlan_id_);
     194             :             }
     195          66 :             all_broadcast->set_vn(vn);
     196             :         } else {
     197          58 :             if (old_vxlan_id != vn_vxlan_id) {
     198           1 :                 state->vxlan_id_ = vn_vxlan_id;
     199           1 :                 if (all_broadcast) {
     200           1 :                     all_broadcast->set_vxlan_id(state->vxlan_id_);
     201             :                 }
     202             :             }
     203             :         }
     204         124 :         ComponentNHKeyList component_nh_key_list;
     205             :         AgentRouteData *data =
     206         248 :             BridgeAgentRouteTable::BuildNonBgpPeerData(state->vrf_name_,
     207             :                                                        vn->GetName(),
     208             :                                                        0,
     209         124 :                                                        state->vxlan_id_,
     210             :                                                        TunnelType::VxlanType(),
     211             :                                                        Composite::L2COMP,
     212             :                                                        component_nh_key_list,
     213         124 :                                                        all_broadcast->pbb_vrf(),
     214             :                                                        all_broadcast->
     215         124 :                                                        learning_enabled());
     216         124 :         BridgeAgentRouteTable::AddBridgeBroadcastRoute(agent_->local_peer(),
     217         124 :                                                        state->vrf_name_,
     218             :                                                        state->vxlan_id_,
     219             :                                                        data);
     220         124 :         Ip4Address broadcast =  IpAddress::from_string("255.255.255.255",
     221         124 :                                                        ec).to_v4();
     222         124 :         AddL2BroadcastRoute(all_broadcast, state->vrf_name_, vn->GetName(),
     223             :                             broadcast, MplsTable::kInvalidLabel,
     224         124 :                             state->vxlan_id_, 0);
     225         124 :     }
     226             : 
     227             :     //Delete or withdraw old vxlan id
     228         269 :     if (deleted) {
     229         145 :         if (!state)
     230          79 :             return;
     231             : 
     232             :         MulticastGroupObject *all_broadcast =
     233          66 :             FindFloodGroupObject(state->vrf_name_);
     234          66 :         if (all_broadcast) {
     235          66 :             all_broadcast->reset_vn();
     236             :         }
     237             : 
     238          66 :         DeleteMulticastObject(state->vrf_name_, Ip4Address(), broadcast);
     239          66 :         BridgeAgentRouteTable::DeleteBroadcastReq(agent_->local_peer(),
     240          66 :                                                   state->vrf_name_,
     241             :                                                   old_vxlan_id,
     242             :                                                   Composite::L2COMP);
     243             : 
     244          66 :         vn->ClearState(partition->parent(), vn_listener_id_);
     245          66 :         delete state;
     246             :     }
     247             : }
     248             : 
     249             : /* Regsitered call for VN */
     250         269 : void MulticastHandler::ModifyVN(DBTablePartBase *partition, DBEntryBase *e)
     251             : {
     252         269 :     const VnEntry *vn = static_cast<const VnEntry *>(e);
     253             : 
     254         269 :     HandleIpam(vn);
     255         269 :     HandleVnParametersChange(partition, e);
     256         269 : }
     257             : 
     258           0 : void MulticastHandler::McastTableNotify(DBTablePartBase *partition,
     259             :                                     DBEntryBase *e) {
     260             : 
     261           0 :     AgentRoute *route = static_cast<AgentRoute *>(e);
     262           0 :     if (route->GetTableType() != Agent::INET4_MULTICAST) {
     263           0 :         return;
     264             :     }
     265           0 :     Inet4MulticastRouteEntry *mc_entry =
     266             :                         static_cast<Inet4MulticastRouteEntry*>(route);
     267           0 :     VrfEntry *vrf = mc_entry->vrf();
     268           0 :     Ip4Address src = mc_entry->src_ip_addr();
     269           0 :     Ip4Address grp = mc_entry->dest_ip_addr();
     270             : 
     271           0 :     MulticastGroupObject *sg_object = NULL;
     272           0 :     sg_object = FindGroupObject(vrf->GetName(), src, grp);
     273           0 :     if (!sg_object) {
     274           0 :         return;
     275             :     }
     276             : 
     277           0 :     bool add = false;
     278           0 :     const AgentPath *path = NULL;
     279           0 :     AgentXmppChannel *channel = NULL;
     280           0 :     for (uint32_t i = 0; i < MAX_XMPP_SERVERS; i++) {
     281           0 :         channel = agent_->controller_xmpp_channel(i);
     282           0 :         if (channel && channel->bgp_peer_id() != NULL) {
     283           0 :             path = route->FindPath(channel->bgp_peer_id());
     284           0 :             if (path) {
     285           0 :                 add = true;
     286           0 :                 break;
     287             :             }
     288             :         }
     289             :     }
     290             : 
     291           0 :     if (sg_object->mvpn_registered() == add) {
     292           0 :         return;
     293             :     }
     294             : 
     295           0 :     if (sg_object->GetLocalListSize() == 0) {
     296           0 :         return;
     297             :     }
     298             : 
     299           0 :     MulticastGroupObject *target_object = NULL;
     300           0 :     target_object = FindGroupObject(agent_->fabric_policy_vrf_name(),
     301             :                                     sg_object->GetSourceAddress(),
     302             :                                     sg_object->GetGroupAddress());
     303           0 :     if (!target_object) {
     304           0 :         return;
     305             :     }
     306             : 
     307           0 :     std::map<uuid, MacAddress>::const_iterator it;
     308           0 :     for (it = sg_object->GetLocalList().begin();
     309           0 :                     it != sg_object->GetLocalList().end(); it++) {
     310           0 :         if (add) {
     311           0 :             if (target_object->AddLocalMember(it->first, it->second) == true) {
     312           0 :                 AddVmToMulticastObjMap(it->first, target_object);
     313             :             }
     314             :         } else {
     315           0 :             if (target_object->DeleteLocalMember(it->first) == true) {
     316           0 :                 DeleteVmToMulticastObjMap(it->first, target_object);
     317             :             }
     318             :         }
     319             :     }
     320             : 
     321           0 :     if (target_object->GetLocalListSize() == 0) {
     322           0 :         Composite::Type comp_type = Composite::L3INTERFACE;
     323           0 :         DeleteMulticastRoute(agent_->local_vm_peer(), target_object->vrf_name(),
     324             :                                     target_object->GetSourceAddress(),
     325             :                                     target_object->GetGroupAddress(),
     326             :                                     0, comp_type);
     327           0 :         DeleteMulticastObject(target_object->vrf_name(),
     328             :                                     target_object->GetSourceAddress(),
     329             :                                     target_object->GetGroupAddress());
     330             :     } else {
     331           0 :         TriggerLocalRouteChange(target_object, agent_->local_vm_peer());
     332             :     }
     333             : 
     334           0 :     sg_object->set_mvpn_registered(add);
     335             : 
     336           0 :     return;
     337             : }
     338             : 
     339         683 : void MulticastHandler::ModifyVRF(DBTablePartBase *partition, DBEntryBase *e) {
     340             : 
     341         683 :     if (!agent_->params()->mvpn_ipv4_enable()) {
     342         683 :         return;
     343             :     }
     344             : 
     345           0 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
     346             :     MulticastVrfDBState *state = static_cast<MulticastVrfDBState *>
     347           0 :         (vrf->GetState(partition->parent(), vrf_listener_id_));
     348           0 :     if (!vrf) {
     349           0 :         return;
     350             :     }
     351             : 
     352             :     //Add operation
     353           0 :     if (!vrf->IsDeleted()) {
     354           0 :         if (!state) {
     355           0 :             state = new MulticastVrfDBState();
     356             :             AgentRouteTable *table = static_cast<AgentRouteTable *>
     357           0 :                             (vrf->GetRouteTable(Agent::INET4_MULTICAST));
     358           0 :             state->id_ = table->Register(
     359             :                             boost::bind(&MulticastHandler::McastTableNotify,
     360             :                             this, _1, _2));
     361           0 :             vrf->SetState(partition->parent(), vrf_listener_id_, state);
     362             :         }
     363           0 :         state->vrf_name_ = vrf->GetName();
     364             :     } else {
     365           0 :         if (!state) {
     366           0 :             return;
     367             :         }
     368             :         AgentRouteTable *table = static_cast<AgentRouteTable *>
     369           0 :                             (vrf->GetRouteTable(Agent::INET4_MULTICAST));
     370           0 :         table->Unregister(state->id_);
     371           0 :         vrf->ClearState(partition->parent(), vrf_listener_id_);
     372           0 :         delete state;
     373             :     }
     374             : }
     375             : 
     376             : MulticastDBState*
     377           0 : MulticastHandler::CreateBridgeDomainMG(DBTablePartBase *partition,
     378             :                                             BridgeDomainEntry *bd) {
     379           0 :     MulticastDBState *state = new MulticastDBState(bd->vrf()->GetName(),
     380           0 :                                                    bd->isid());
     381             : 
     382           0 :     MulticastGroupObject *obj = FindFloodGroupObject(bd->vrf()->GetName());
     383           0 :     if (obj == NULL) {
     384           0 :         obj = CreateMulticastGroupObject(state->vrf_name_, bd->vn()->GetName(),
     385           0 :                                         Ip4Address(), kBroadcast,
     386             :                                         state->vxlan_id_);
     387             :         //Add a mutlicast route point to empty composite list
     388           0 :         AddL2BroadcastRoute(obj, state->vrf_name_,
     389             :                             bd->vn()->GetName(), kBroadcast,
     390             :                             MplsTable::kInvalidLabel, 0,
     391             :                             state->vxlan_id_);
     392             :     }
     393             : 
     394           0 :     obj->set_bridge_domain(bd);
     395           0 :     obj->set_vxlan_id(bd->isid());
     396           0 :     bd->SetState(partition->parent(), bridge_domain_id_, state);
     397           0 :     return state;
     398             : }
     399             : 
     400           0 : void MulticastHandler::AddBridgeDomain(DBTablePartBase *partition,
     401             :                                        DBEntryBase *e) {
     402           0 :     BridgeDomainEntry *bd = static_cast<BridgeDomainEntry *>(e);
     403             : 
     404             :     MulticastDBState *state = static_cast<MulticastDBState *>(
     405           0 :         bd->GetState(partition->parent(), bridge_domain_id_));
     406             : 
     407           0 :     if (e->IsDeleted() || bd->vrf() == NULL || bd->vn() == NULL) {
     408           0 :         if (state) {
     409             :             MulticastGroupObject *obj =
     410           0 :                 FindFloodGroupObject(state->vrf_name_);
     411           0 :             assert(obj);
     412           0 :             obj->reset_bridge_domain();
     413           0 :             bd->ClearState(partition->parent(), bridge_domain_id_);
     414           0 :             DeleteBroadcast(agent_->local_vm_peer(),
     415           0 :                             state->vrf_name_, 0, Composite::L2INTERFACE);
     416           0 :             DeleteMulticastObject(state->vrf_name_, Ip4Address(), kBroadcast);
     417           0 :             delete state;
     418             :         }
     419           0 :         return;
     420             :     }
     421             : 
     422           0 :     if (state == NULL) {
     423           0 :         state = CreateBridgeDomainMG(partition, bd);
     424             :     }
     425             : 
     426           0 :     MulticastGroupObject *obj = FindFloodGroupObject(bd->vrf()->GetName());
     427           0 :     if (obj == NULL) {
     428           0 :         obj = CreateMulticastGroupObject(state->vrf_name_, bd->vn()->GetName(),
     429           0 :                                         Ip4Address(), kBroadcast,
     430             :                                         state->vxlan_id_);
     431             :     }
     432             : 
     433           0 :     if (state->vxlan_id_ != bd->isid()) {
     434           0 :         DeleteEvpnPath(obj);
     435           0 :         state->vxlan_id_ = bd->isid();
     436           0 :         obj->set_vxlan_id(state->vxlan_id_);
     437           0 :         Resync(obj);
     438             :     }
     439             : 
     440           0 :     if (state->learning_enabled_ != bd->learning_enabled()) {
     441           0 :         state->learning_enabled_ = bd->learning_enabled();
     442           0 :         ChangeLearningMode(obj, state->learning_enabled_);
     443             :     }
     444             : 
     445           0 :     if (state->pbb_etree_enabled_ != bd->pbb_etree_enabled()) {
     446           0 :         state->pbb_etree_enabled_ = bd->pbb_etree_enabled();
     447           0 :         ChangePbbEtreeMode(obj, state->pbb_etree_enabled_);
     448             :     }
     449             : 
     450           0 :     if (state->layer2_control_word_ != bd->layer2_control_word()) {
     451           0 :         state->layer2_control_word_ = bd->layer2_control_word();
     452           0 :         Resync(obj);
     453             :     }
     454             : }
     455             : 
     456           0 : void MulticastHandler::ChangeLearningMode(MulticastGroupObject *obj,
     457             :                                           bool learning_enabled) {
     458           0 :     if (obj->learning_enabled_ == learning_enabled) {
     459           0 :         return;
     460             :     }
     461             : 
     462           0 :     obj->set_learning_enabled(learning_enabled);
     463           0 :     Resync(obj);
     464             : }
     465             : 
     466           0 : void MulticastHandler::ChangePbbEtreeMode(MulticastGroupObject *obj,
     467             :                                           bool pbb_etree_enabled) {
     468           0 :     if (obj->pbb_etree_enabled_ == pbb_etree_enabled) {
     469           0 :         return;
     470             :     }
     471             : 
     472           0 :     obj->set_pbb_etree_enabled(pbb_etree_enabled);
     473           0 :     Resync(obj);
     474             : }
     475             : 
     476         131 : bool MulticastGroupObject::CanBeDeleted() const {
     477         200 :     if ((local_olist_.size() == 0) && (vn_.get() == NULL) &&
     478          69 :          bridge_domain_.get() == NULL)
     479          69 :         return true;
     480          62 :     return false;
     481             : }
     482             : 
     483             : MulticastGroupObject*
     484           0 : MulticastGroupObject::GetDependentMG(uint32_t isid) {
     485           0 :     for (MGList::iterator it = mg_list_.begin();
     486           0 :         it != mg_list_.end(); it++) {
     487           0 :         if (it->vxlan_id_ == isid) {
     488           0 :             return it.operator->();
     489             :         }
     490             :     }
     491           0 :     return NULL;
     492             : }
     493             : 
     494             : MulticastGroupObject*
     495          69 : MulticastHandler::CreateMulticastGroupObject(const string &vrf_name,
     496             :                                              const string &vn_name,
     497             :                                              const Ip4Address &src_addr,
     498             :                                              const Ip4Address &grp_addr,
     499             :                                              uint32_t vxlan_id) {
     500             :     MulticastGroupObject *obj =
     501          69 :         new MulticastGroupObject(vrf_name, vn_name, grp_addr, src_addr);
     502          69 :     AddToMulticastObjList(obj);
     503          69 :     obj->set_vxlan_id(vxlan_id);
     504             : 
     505          69 :     boost::system::error_code ec;
     506             :     Ip4Address bcast_addr =
     507          69 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
     508          69 :     if (obj->GetGroupAddress() == bcast_addr) {
     509          69 :         UpdateReference(obj);
     510             :     }
     511          69 :     return obj;
     512             : }
     513             : 
     514         269 : void MulticastHandler::HandleIpam(const VnEntry *vn) {
     515         269 :     const uuid &vn_uuid = vn->GetUuid();
     516         269 :     const std::vector<VnIpam> &ipam = vn->GetVnIpam();
     517         269 :     bool delete_ipam = false;
     518         269 :     std::map<uuid, string>::iterator it;
     519         269 :     string vrf_name;
     520             : 
     521         345 :     if (!(vn->layer3_forwarding()) || vn->IsDeleted() || (ipam.size() == 0) ||
     522          76 :         (vn->GetVrf() == NULL)) {
     523         204 :         delete_ipam = true;
     524             :     }
     525             : 
     526         269 :     it = vn_vrf_mapping_.find(vn_uuid);
     527         269 :     if (it != vn_vrf_mapping_.end()) {
     528          65 :         vrf_name = it->second;
     529          65 :         vrf_ipam_mapping_.erase(vrf_name);
     530          65 :         if (delete_ipam) {
     531          62 :             vn_vrf_mapping_.erase(vn_uuid);
     532          62 :             return;
     533             :         }
     534             :     } else {
     535         204 :         if (delete_ipam == false) {
     536          62 :             vrf_name = vn->GetVrf()->GetName();
     537          62 :             vn_vrf_mapping_.insert(std::pair<uuid, string>(vn_uuid, vrf_name));
     538             :         }
     539             :     }
     540             : 
     541         207 :     if (delete_ipam)
     542         142 :         return;
     543             : 
     544          65 :     vrf_ipam_mapping_.insert(std::pair<string, std::vector<VnIpam> >(vrf_name,
     545             :                                                                      ipam));
     546         269 : }
     547             : 
     548           0 : void MulticastHandler::NotifyPhysicalDevice(DBTablePartBase *partition,
     549             :                                             DBEntryBase *e)
     550             : {
     551           0 :     PhysicalDevice *dev = static_cast<PhysicalDevice *>(e);
     552           0 :     IpAddress dev_ip = dev->ip();
     553             :     ManagedPhysicalDevicesList::iterator pd_it =
     554           0 :         std::find(physical_devices_.begin(), physical_devices_.end(),
     555           0 :                   dev_ip.to_string());
     556           0 :     if (dev->IsDeleted()) {
     557           0 :         if (pd_it == physical_devices_.end())
     558           0 :             return;
     559           0 :         physical_devices_.erase(pd_it);
     560             :     } else {
     561           0 :         if (pd_it != physical_devices_.end())
     562           0 :             return;
     563           0 :         physical_devices_.push_back(dev_ip.to_string());
     564             :     }
     565           0 :     std::sort(physical_devices_.begin(), physical_devices_.end());
     566             :     //Start walk to update evpn nh
     567           0 :     if (te_walker_.get()) {
     568           0 :         te_walker_.get()->StartVrfWalk();
     569             :     }
     570             : }
     571             : 
     572        1400 : bool MulticastHandler::FilterVmi(const VmInterface *vm_itf) {
     573        1400 :     if (vm_itf->device_type() == VmInterface::TOR) {
     574             :         //Ignore TOR VMI, they are not active VMI.
     575           6 :         return true;
     576             :     }
     577             : 
     578        1394 :     if (vm_itf->vmi_type() == VmInterface::VHOST) {
     579           2 :         return true;
     580             :     }
     581             : 
     582        1392 :     if (vm_itf->device_type() == VmInterface::VMI_ON_LR) {
     583           0 :         return true;
     584             :     }
     585             : 
     586        1392 :     if (vm_itf->device_type() == VmInterface::VM_SRIOV) {
     587           0 :         return true;
     588             :     }
     589             : 
     590        1392 :     return false;
     591             : }
     592             : 
     593             : /* Registered call for VM */
     594        1421 : void MulticastHandler::ModifyVmInterface(DBTablePartBase *partition,
     595             :                                          DBEntryBase *e)
     596             : {
     597        1421 :     Interface *intf = static_cast<Interface *>(e);
     598             :     VmInterface *vm_itf;
     599             : 
     600        1421 :     if (intf->type() != Interface::VM_INTERFACE) {
     601          21 :         return;
     602             :     }
     603             : 
     604        1400 :     vm_itf = static_cast<VmInterface *>(intf);
     605        1400 :     if (FilterVmi(vm_itf)) {
     606           8 :         return;
     607             :     }
     608             : 
     609             :     MulticastIntfDBState *state = static_cast<MulticastIntfDBState *>(
     610        1392 :         vm_itf->GetState(partition->parent(), interface_listener_id_));
     611             : 
     612        1644 :     if (intf->IsDeleted() || ((vm_itf->l2_active() == false) &&
     613         252 :                               (vm_itf->ipv4_active() == false) &&
     614         252 :                               (vm_itf->ipv6_active() == false))) {
     615         419 :         if (state) {
     616         165 :             DeleteVmInterface(vm_itf, state);
     617         165 :             if (intf->IsDeleted()) {
     618         165 :                 vm_itf->ClearState(partition->parent(), interface_listener_id_);
     619         165 :                 delete state;
     620             :             }
     621             :         }
     622         419 :         return;
     623             :     }
     624         973 :     assert(vm_itf->vn() != NULL);
     625             : 
     626         973 :     if (state == NULL) {
     627         165 :         state = new MulticastIntfDBState();
     628         165 :         vm_itf->SetState(partition->parent(), interface_listener_id_, state);
     629             :     }
     630             : 
     631             :     //Build all the VRF group interface belong to
     632         973 :     AddVmInterfaceInFloodGroup(vm_itf, state);
     633         973 :     return;
     634             : }
     635             : 
     636         973 : void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_intf,
     637             :                                                   MulticastIntfDBState *state) {
     638         973 :     std::set<std::string> new_vrf_list;
     639         973 :     new_vrf_list.insert(vm_intf->vrf()->GetName());
     640             : 
     641             :     //Build all PBB VRF
     642             :     VmInterface::BridgeDomainEntrySet::const_iterator it =
     643         973 :         vm_intf->bridge_domain_list().list_.begin();
     644         973 :     for (;it != vm_intf->bridge_domain_list().list_.end(); it++) {
     645           0 :         if (it->bridge_domain_.get() && it->bridge_domain_->vrf()) {
     646           0 :             new_vrf_list.insert(it->bridge_domain_->vrf()->GetName());
     647             :         }
     648             :     }
     649             : 
     650             :     //Delete interface multicast group, if bridge domain is deleted
     651         973 :     for (std::set<std::string>::const_iterator it = new_vrf_list.begin();
     652        1946 :          it != new_vrf_list.end(); it++) {
     653         973 :         AddVmInterfaceInFloodGroup(vm_intf, *it);
     654         973 :         state->vrf_list_.erase(*it);
     655             :     }
     656             : 
     657         973 :     for (std::set<std::string>::const_iterator it = state->vrf_list_.begin();
     658         973 :          it != state->vrf_list_.end(); it++) {
     659           0 :         DeleteVmInterface(vm_intf, *it);
     660             :     }
     661             : 
     662         973 :     state->vrf_list_ = new_vrf_list;
     663         973 : }
     664             : 
     665         165 : void MulticastHandler::DeleteVmInterface(const VmInterface *intf,
     666             :                                          MulticastIntfDBState *state) {
     667         165 :     for (std::set<std::string>::const_iterator it = state->vrf_list_.begin();
     668         330 :          it != state->vrf_list_.end(); it++) {
     669         165 :         DeleteVmInterface(intf, *it);
     670             :     }
     671         165 : }
     672             : 
     673             : /*
     674             :  * Delete VM interface
     675             :  * Traverse the multicast obj list of which this VM is a member.
     676             :  * Delete the VM from them and check if local VM list size is zero.
     677             :  * If it is zero then delete the route and mpls.
     678             :  */
     679         165 : void MulticastHandler::DeleteVmInterface(const VmInterface *intf,
     680             :                                          const std::string &vrf_name) {
     681             : 
     682         165 :     const VmInterface *vm_itf = static_cast<const VmInterface *>(intf);
     683         165 :     boost::system::error_code ec;
     684             :     Ip4Address bcast_addr =
     685         165 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
     686         165 :     std::set<MulticastGroupObject *> &obj_list = GetVmToMulticastObjMap(
     687             :                                                           vm_itf->GetUuid());
     688         165 :     for (std::set<MulticastGroupObject *>::iterator it = obj_list.begin();
     689         165 :          it != obj_list.end(); it++) {
     690             : 
     691         330 :         if (((*it)->vrf_name() != vrf_name) ||
     692         165 :             ((*it)->GetGroupAddress() != bcast_addr)) {
     693           0 :             continue;
     694             :         }
     695             :         // When IPAM/VN goes off first than VM then it marks mc obj
     696             :         // for deletion. Cleanup of related data structures like vm-mcobj
     697             :         // happens when VM goes off. So dont trigger any notify at same time.
     698             :         // However if all local VMs are gone then route will be deleted only
     699             :         // when VN/IPAM goes off. At that time notify xmpp to unsubscribe
     700             :         //Deletelocalmember removes vm from mc obj
     701         165 :         if (((*it)->DeleteLocalMember(vm_itf->GetUuid()) == true) &&
     702         330 :             ((*it)->IsDeleted() == false) &&
     703         165 :             ((*it)->GetLocalListSize() != 0)) {
     704         100 :             TriggerLocalRouteChange(*it, agent_->local_vm_peer());
     705         100 :             MCTRACE(LogSG, "modify route, vm is deleted ", (*it)->vrf_name(),
     706             :                     (*it)->GetSourceAddress().to_string(),
     707             :                     (*it)->GetGroupAddress().to_string(), 0);
     708             :         }
     709             : 
     710         165 :         if((*it)->GetLocalListSize() == 0) {
     711          65 :             MCTRACE(Info, "Del route for multicast address",
     712             :                     vm_itf->primary_ip_addr().to_string());
     713             :             //Time to delete route(for mcast address) and mpls
     714          65 :             DeleteBroadcast(agent_->local_vm_peer(),
     715          65 :                             (*it)->vrf_name_, 0, Composite::L2INTERFACE);
     716             :             /* delete mcast object */
     717             :             // TODO : delete only when all creators are gone
     718          65 :             DeleteMulticastObject((*it)->vrf_name_, Ip4Address(), bcast_addr);
     719             :         }
     720         165 :         DeleteVmToMulticastObjMap(vm_itf->GetUuid(), *it);
     721         165 :         break;
     722             :     }
     723         165 :     MCTRACE(Info, "Del vm notify done ", vm_itf->primary_ip_addr().to_string());
     724         165 : }
     725             : 
     726             : //Delete multicast object for vrf/S/G
     727         131 : void MulticastHandler::DeleteMulticastObject(const std::string &vrf_name,
     728             :                                              const Ip4Address &src_addr,
     729             :                                              const Ip4Address &grp_addr) {
     730             : 
     731         131 :     for (std::set<MulticastGroupObject *>::iterator it =
     732         131 :         this->GetMulticastObjList().begin();
     733         229 :         it != this->GetMulticastObjList().end(); it++) {
     734             : 
     735         360 :         if (((*it)->vrf_name() == vrf_name) &&
     736         360 :             ((*it)->GetGroupAddress() == grp_addr) &&
     737         131 :             ((*it)->GetSourceAddress() == src_addr)) {
     738             : 
     739         131 :             if (!((*it)->CanBeDeleted())) {
     740          62 :                 return;
     741             :             }
     742             : 
     743          69 :             if ((*it)->dependent_mg() != NULL) {
     744           0 :                 MulticastGroupObject *dp_obj = (*it)->dependent_mg();
     745           0 :                 (*it)->set_dependent_mg(NULL);
     746           0 :                 ModifyFabricMembers(dp_obj->peer(), dp_obj->vrf_name(),
     747             :                                     dp_obj->GetGroupAddress(),
     748             :                                     dp_obj->GetSourceAddress(),
     749             :                                     dp_obj->fabric_label(),
     750             :                                     dp_obj->fabric_olist(),
     751             :                                     dp_obj->peer_identifier());
     752             :             }
     753             : 
     754          69 :             MCTRACE(LogSG, "delete obj  vrf/source/grp/size ", vrf_name,
     755             :                     src_addr.to_string(),
     756             :                     grp_addr.to_string(),
     757             :                     this->GetMulticastObjList().size());
     758          69 :             delete (*it);
     759          69 :             this->GetMulticastObjList().erase(it);
     760          69 :             break;
     761             :         }
     762             :     }
     763             : }
     764             : 
     765         190 : MulticastGroupObject *MulticastHandler::FindFloodGroupObject(const std::string &vrf_name) {
     766         190 :     boost::system::error_code ec;
     767         190 :     Ip4Address broadcast =  IpAddress::from_string("255.255.255.255",
     768         190 :                                                    ec).to_v4();
     769         190 :     return (FindGroupObject(vrf_name, Ip4Address(), broadcast));
     770             : }
     771             : 
     772             : //Helper to find object for VRF/S/G
     773        1163 : MulticastGroupObject *MulticastHandler::FindGroupObject(
     774             :                                     const std::string &vrf_name,
     775             :                                     const Ip4Address &sip,
     776             :                                     const Ip4Address &dip) {
     777        1163 :     for(std::set<MulticastGroupObject *>::iterator it =
     778        1163 :         this->GetMulticastObjList().begin();
     779        2117 :         it != this->GetMulticastObjList().end(); it++) {
     780        3142 :         if (((*it)->vrf_name() == vrf_name) &&
     781        3142 :             ((*it)->GetGroupAddress() == dip) &&
     782        1094 :             ((*it)->GetSourceAddress() == sip)) {
     783        1094 :             return (*it);
     784             :         }
     785             :     }
     786          69 :     MCTRACE(LogSG, "mcast obj size ", vrf_name, sip.to_string(),
     787             :             dip.to_string(), this->GetMulticastObjList().size());
     788          69 :     return NULL;
     789             : }
     790             : 
     791           0 : MulticastGroupObject *MulticastHandler::FindActiveGroupObject(
     792             :                                                     const std::string &vrf_name,
     793             :                                                     const Ip4Address &sip,
     794             :                                                     const Ip4Address &dip) {
     795           0 :     MulticastGroupObject *obj = FindGroupObject(vrf_name, sip, dip);
     796           0 :     if ((obj == NULL) || obj->IsDeleted()) {
     797           0 :         MCTRACE(LogSG, "Multicast object deleted ", vrf_name,
     798             :                 sip.to_string(), dip.to_string(), 0);
     799           0 :         return NULL;
     800             :     }
     801             : 
     802           0 :     return obj;
     803             : }
     804             : 
     805          66 : void MulticastGroupObject::set_vn(const VnEntry *vn) {
     806          66 :     vn_.reset(vn);
     807          66 : }
     808             : 
     809          66 : void MulticastGroupObject::reset_vn() {
     810          66 :     vn_.reset();
     811          66 : }
     812             : 
     813             : ComponentNHKeyList
     814        1224 : MulticastGroupObject::GetInterfaceComponentNHKeyList(uint8_t interface_flags) {
     815             : 
     816        1224 :     ComponentNHKeyList component_nh_key_list;
     817        1224 :     for (std::map<uuid, MacAddress>::iterator it = local_olist_.begin();
     818        4385 :             it != local_olist_.end(); it++) {
     819        3161 :         ComponentNHKeyPtr component_nh_key(new ComponentNHKey(0, it->first,
     820             :                                                         interface_flags,
     821        3161 :                                                         it->second));
     822        3161 :         component_nh_key_list.push_back(component_nh_key);
     823        3161 :     }
     824        1224 :     return component_nh_key_list;
     825           0 : }
     826             : 
     827             : ComponentNHKeyList
     828        1224 : MulticastHandler::GetInterfaceComponentNHKeyList(MulticastGroupObject *obj,
     829             :                                                  uint8_t interface_flags) {
     830             : 
     831             :     ComponentNHKeyList component_nh_key_list =
     832        1224 :                         obj->GetInterfaceComponentNHKeyList(interface_flags);
     833        1224 :     return component_nh_key_list;
     834             : }
     835             : 
     836             : // For MVPN: <S,G> entry is added to the multicast table only.
     837             : // For EVPN-multicast: <*,G> entry is added to the multicast table.
     838             : //      Currently support is for multicast source outside of the contrail
     839             : //      Also, the vrouter does lookup not using the <S,G> of the multicast
     840             : //      data packet, but using the multicast MAC DA.
     841             : //      With this as design choice, route entry corresponding to the
     842             : //      multicast MAC dervied from the G of <*,G> is added as entry to the
     843             : //      bridge table.
     844        1100 : void MulticastHandler::TriggerLocalRouteChange(MulticastGroupObject *obj,
     845             :                                           const Peer *peer) {
     846        1100 :     DBRequest req;
     847        1100 :     ComponentNHKeyList component_nh_key_list;
     848             : 
     849        1100 :     if (obj->pbb_vrf() && obj->dependent_mg() == NULL) {
     850           0 :         return;
     851             :     }
     852             : 
     853        1100 :     uint8_t intf_flags = InterfaceNHFlags::BRIDGE;
     854        1100 :     Composite::Type comp_type = Composite::L2INTERFACE;
     855        1100 :     uint32_t route_tunnel_bmap = TunnelType::AllType();
     856        1100 :     boost::system::error_code ec;
     857             :     Ip4Address bcast_addr =
     858        1100 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
     859        1100 :     if (obj->GetGroupAddress() != bcast_addr) {
     860           0 :         intf_flags = InterfaceNHFlags::INET4 | InterfaceNHFlags::MULTICAST;
     861           0 :         comp_type = Composite::L3INTERFACE;
     862           0 :         route_tunnel_bmap = agent_->params()->mvpn_ipv4_enable() ?
     863           0 :                             TunnelType::AllType() : TunnelType::VxlanType();
     864             :     }
     865             :     component_nh_key_list =
     866        1100 :         GetInterfaceComponentNHKeyList(obj, intf_flags);
     867             : 
     868        1100 :     MCTRACE(LogSG, "enqueue route change with local peer",
     869             :             obj->vrf_name(),
     870             :             obj->GetSourceAddress().to_string(),
     871             :             obj->GetGroupAddress().to_string(),
     872             :             component_nh_key_list.size());
     873             : 
     874             :     AgentRouteData *data =
     875        1100 :         BridgeAgentRouteTable::BuildNonBgpPeerData(obj->vrf_name(),
     876             :                                     obj->GetVnName(), MplsTable::kInvalidLabel,
     877        1100 :                                     obj->vxlan_id(), route_tunnel_bmap,
     878             :                                     comp_type, component_nh_key_list,
     879        1100 :                                     obj->pbb_vrf(),
     880        1100 :                                     obj->learning_enabled());
     881             : 
     882        1100 :     if (obj->GetGroupAddress() != bcast_addr) {
     883           0 :         Inet4MulticastAgentRouteTable::AddMulticastRoute(peer,
     884             :                                     obj->vrf_name(), obj->GetSourceAddress(),
     885             :                                     obj->GetGroupAddress(), 0,
     886             :                                     data);
     887             : 
     888           0 :         if (!agent_->params()->mvpn_ipv4_enable()) {
     889           0 :             intf_flags = InterfaceNHFlags::BRIDGE;
     890           0 :             comp_type = Composite::L2INTERFACE;
     891             :             component_nh_key_list =
     892           0 :                 GetInterfaceComponentNHKeyList(obj, intf_flags);
     893             : 
     894           0 :             MacAddress mac;
     895           0 :             GetMulticastMacFromIp(obj->GetGroupAddress(), mac);
     896             : 
     897             :             AgentRouteData *bridge_data =
     898           0 :                 BridgeAgentRouteTable::BuildNonBgpPeerData(obj->vrf_name(),
     899             :                                     obj->GetVnName(), MplsTable::kInvalidLabel,
     900           0 :                                     obj->vxlan_id(), route_tunnel_bmap,
     901             :                                     comp_type,component_nh_key_list,
     902           0 :                                     obj->pbb_vrf(),
     903           0 :                                     obj->learning_enabled());
     904           0 :             BridgeAgentRouteTable::AddBridgeRoute(peer, obj->vrf_name(), mac,
     905             :                                     0, bridge_data);
     906             :         }
     907             :     } else {
     908             :         //Add Bridge FF:FF:FF:FF:FF:FF, local_vm_peer
     909        1100 :         BridgeAgentRouteTable::AddBridgeBroadcastRoute(peer,
     910             :                                                    obj->vrf_name(),
     911             :                                                    0,
     912             :                                                    data);
     913             :     }
     914        1100 : }
     915             : 
     916           0 : void MulticastHandler::AddMulticastRoute(MulticastGroupObject *obj,
     917             :                                     const Peer *peer,
     918             :                                     uint32_t ethernet_tag,
     919             :                                     AgentRouteData *data,
     920             :                                     AgentRouteData *bridge_data) {
     921             : 
     922           0 :     boost::system::error_code ec;
     923             :     Ip4Address bcast_addr =
     924           0 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
     925             : 
     926           0 :     if (obj->GetGroupAddress() != bcast_addr) {
     927           0 :         Inet4MulticastAgentRouteTable::AddMulticastRoute(peer,
     928             :                                     obj->vrf_name(), obj->GetSourceAddress(),
     929             :                                     obj->GetGroupAddress(), ethernet_tag, data);
     930             : 
     931           0 :         if (!agent_->params()->mvpn_ipv4_enable()) {
     932           0 :             MacAddress mac;
     933           0 :             GetMulticastMacFromIp(obj->GetGroupAddress(), mac);
     934             : 
     935           0 :             BridgeAgentRouteTable::AddBridgeRoute(peer, obj->vrf_name(), mac,
     936             :                                     ethernet_tag, bridge_data);
     937             :         }
     938             :     } else {
     939           0 :         BridgeAgentRouteTable::AddBridgeBroadcastRoute(peer,
     940             :                                     obj->vrf_name(), ethernet_tag, data);
     941             :     }
     942           0 : }
     943             : 
     944           0 : void MulticastHandler::DeleteMulticastRoute(const Peer *peer,
     945             :                                     const string &vrf_name,
     946             :                                     const Ip4Address &src,
     947             :                                     const Ip4Address &grp,
     948             :                                     uint32_t ethernet_tag,
     949             :                                     COMPOSITETYPE comp_type) {
     950             : 
     951           0 :     boost::system::error_code ec;
     952             :     Ip4Address bcast_addr =
     953           0 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
     954             : 
     955           0 :     if (grp != bcast_addr) {
     956           0 :         Inet4MulticastAgentRouteTable::DeleteMulticastRoute(peer, vrf_name,
     957             :                                     src, grp, ethernet_tag, comp_type);
     958             : 
     959           0 :         if (!agent_->params()->mvpn_ipv4_enable()) {
     960           0 :             MacAddress mac;
     961           0 :             GetMulticastMacFromIp(grp, mac);
     962             : 
     963             :             COMPOSITETYPE l2_comp_type;
     964           0 :             if (comp_type == Composite::L3FABRIC) {
     965           0 :                 l2_comp_type = Composite::FABRIC;
     966             :             } else {
     967           0 :                 l2_comp_type = Composite::L2INTERFACE;
     968             :             }
     969           0 :             BridgeAgentRouteTable::DeleteBridgeRoute(peer, vrf_name, mac,
     970             :                                     ethernet_tag, l2_comp_type);
     971             :         }
     972             :     } else {
     973           0 :         BridgeAgentRouteTable::DeleteBroadcastReq(peer, vrf_name, ethernet_tag,
     974             :                                     comp_type);
     975             :     }
     976           0 : }
     977             : 
     978           0 : void MulticastHandler::TriggerRemoteRouteChange(MulticastGroupObject *obj,
     979             :                                                 const Peer *peer,
     980             :                                                 const string &vrf_name,
     981             :                                                 const Ip4Address &src,
     982             :                                                 const Ip4Address &grp,
     983             :                                                 const TunnelOlist &olist,
     984             :                                                 uint64_t peer_identifier,
     985             :                                                 bool delete_op,
     986             :                                                 COMPOSITETYPE comp_type,
     987             :                                                 uint32_t label,
     988             :                                                 bool fabric,
     989             :                                                 uint32_t ethernet_tag) {
     990           0 :     uint64_t obj_peer_identifier = obj ? obj->peer_identifier()
     991           0 :         : ControllerPeerPath::kInvalidPeerIdentifier;
     992             : 
     993             :     // Peer identifier cases
     994             :     // if its a delete operation -
     995             :     // 1) Internal delete (invalid peer identifier), dont update peer identifier
     996             :     // as it is a forced removal.
     997             :     // 2) Control node removing stales i.e. delete if local peer identifier is
     998             :     // less than global peer identifier.
     999             :     //
    1000             :     // if its not a delete operation -
    1001             :     // 1) Update only if local peer identifier is less than or equal to sent
    1002             :     // global peer identifier.
    1003             : 
    1004             :     // if its internal delete then peer_identifier will be 0xFFFFFFFF;
    1005             :     // if external delete(via control node) then its stale cleanup so delete
    1006             :     // only when local peer identifier is less than global multicast sequence.
    1007           0 :     if (delete_op) {
    1008           0 :         if ((peer_identifier != ControllerPeerPath::kInvalidPeerIdentifier) &&
    1009             :             (peer_identifier <= obj_peer_identifier))
    1010           0 :             return;
    1011             : 
    1012             :         // After resetting tunnel and mpls label return if it was a delete call,
    1013             :         // dont update peer_identifier. Let it get updated via update operation only
    1014           0 :         MCTRACE(LogSG, "delete bcast path from remote peer", vrf_name,
    1015             :                 src.to_string(), grp.to_string(), 0);
    1016           0 :         DeleteMulticastRoute(peer, vrf_name, src, grp, ethernet_tag, comp_type);
    1017           0 :         ComponentNHKeyList component_nh_key_list; //dummy list
    1018           0 :         return;
    1019           0 :     }
    1020             : 
    1021             :     // - Update operation with lower sequence number sent compared to
    1022             :     // local identifier, ignore
    1023           0 :     if ((peer_identifier < obj_peer_identifier) &&
    1024             :         (comp_type != Composite::TOR)) {
    1025           0 :         return;
    1026             :     }
    1027             : 
    1028             :     // Ideally wrong update call
    1029           0 :     if (peer_identifier == INVALID_PEER_IDENTIFIER) {
    1030           0 :         MCTRACE(LogSG, "Invalid peer identifier sent for modification",
    1031             :                 vrf_name, src.to_string(), grp.to_string(), 0);
    1032           0 :         return;
    1033             :     }
    1034             : 
    1035           0 :     obj->set_peer_identifier(peer_identifier);
    1036           0 :     ComponentNHKeyList component_nh_key_list;
    1037             : 
    1038           0 :     uint32_t route_tunnel_bmap = TunnelType::AllType();
    1039           0 :     for (TunnelOlist::const_iterator it = olist.begin();
    1040           0 :          it != olist.end(); it++) {
    1041             :         TunnelNHKey *key =
    1042           0 :             new TunnelNHKey(agent_->fabric_vrf_name(),
    1043           0 :                             agent_->router_id(),
    1044           0 :                             it->daddr_, false,
    1045           0 :                             TunnelType::ComputeType(it->tunnel_bmap_));
    1046           0 :         TunnelNHData *tnh_data = new TunnelNHData();
    1047           0 :         DBRequest req;
    1048           0 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1049           0 :         req.key.reset(key);
    1050           0 :         req.data.reset(tnh_data);
    1051           0 :         agent_->nexthop_table()->Enqueue(&req);
    1052             : 
    1053           0 :         MCTRACE(Log, "Enqueue add TOR TUNNEL ",
    1054             :                 agent_->fabric_vrf_name(),
    1055             :                 it->daddr_.to_string(), it->label_);
    1056             : 
    1057           0 :         ComponentNHKeyPtr component_key_ptr(new ComponentNHKey(it->label_,
    1058           0 :                     agent_->fabric_vrf_name(),
    1059           0 :                     agent_->router_id(), it->daddr_,
    1060           0 :                     false, it->tunnel_bmap_));
    1061           0 :         component_nh_key_list.push_back(component_key_ptr);
    1062           0 :         route_tunnel_bmap = it->tunnel_bmap_;
    1063           0 :     }
    1064             : 
    1065           0 :     MCTRACE(LogSG, "enqueue route change with remote peer",
    1066             :             obj->vrf_name(),
    1067             :             obj->GetSourceAddress().to_string(),
    1068             :             obj->GetGroupAddress().to_string(),
    1069             :             component_nh_key_list.size());
    1070             : 
    1071             :     //Delete fabric path, so that only PBB route points
    1072             :     //to MPLS route
    1073           0 :     if (comp_type == Composite::FABRIC &&
    1074           0 :         ((obj->mg_list_.empty() == false || obj->pbb_etree_enabled() == true))) {
    1075           0 :         DeleteMulticastRoute(peer, vrf_name, src, grp, ethernet_tag, comp_type);
    1076           0 :         return;
    1077             :     }
    1078             : 
    1079             :     //Add Bridge FF:FF:FF:FF:FF:FF for L2 Multicast
    1080           0 :     if (comp_type == Composite::TOR)
    1081           0 :         route_tunnel_bmap = TunnelType::VxlanType();
    1082           0 :     const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
    1083           0 :     AgentRouteData *data = NULL;
    1084           0 :     AgentRouteData *bridge_data = NULL;
    1085           0 :     if (bgp_peer) {
    1086           0 :         data = BridgeAgentRouteTable::BuildBgpPeerData(peer,
    1087             :                                                        obj->vrf_name(),
    1088             :                                                        obj->GetVnName(),
    1089             :                                                        label,
    1090           0 :                                                        obj->vxlan_id(),
    1091             :                                                        ethernet_tag,
    1092             :                                                        route_tunnel_bmap,
    1093             :                                                        comp_type,
    1094             :                                                        component_nh_key_list,
    1095           0 :                                                        obj->pbb_vrf(), false);
    1096             :     } else {
    1097           0 :         data = BridgeAgentRouteTable::BuildNonBgpPeerData(obj->vrf_name(),
    1098             :                                                           obj->GetVnName(),
    1099             :                                                           label,
    1100           0 :                                                           obj->vxlan_id(),
    1101             :                                                           route_tunnel_bmap,
    1102             :                                                           comp_type,
    1103             :                                                           component_nh_key_list,
    1104           0 :                                                           obj->pbb_vrf(), false);
    1105             :     }
    1106             : 
    1107           0 :     boost::system::error_code ec;
    1108             :     Ip4Address bcast_addr =
    1109           0 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
    1110           0 :     if ((grp != bcast_addr) && !agent_->params()->mvpn_ipv4_enable()) {
    1111           0 :         if (bgp_peer) {
    1112           0 :             bridge_data = BridgeAgentRouteTable::BuildBgpPeerData(peer,
    1113             :                                     obj->vrf_name(), obj->GetVnName(), label,
    1114           0 :                                     obj->vxlan_id(), ethernet_tag,
    1115             :                                     route_tunnel_bmap, Composite::FABRIC,
    1116             :                                     component_nh_key_list,
    1117           0 :                                     obj->pbb_vrf(), false);
    1118             :         } else {
    1119           0 :             bridge_data = BridgeAgentRouteTable::BuildNonBgpPeerData(
    1120             :                                     obj->vrf_name(), obj->GetVnName(), label,
    1121           0 :                                     obj->vxlan_id(), route_tunnel_bmap,
    1122             :                                     Composite::FABRIC, component_nh_key_list,
    1123           0 :                                     obj->pbb_vrf(), false);
    1124             :         }
    1125             :     }
    1126             : 
    1127           0 :     AddMulticastRoute(obj, peer, ethernet_tag, data, bridge_data);
    1128           0 :     MCTRACE(LogSG, "rebake subnet peer for subnet", vrf_name,
    1129             :             obj->GetSourceAddress().to_string(),
    1130             :             obj->GetGroupAddress().to_string(), comp_type);
    1131           0 : }
    1132             : 
    1133         973 : void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_itf,
    1134             :                                                   const std::string &vrf_name) {
    1135         973 :     const uuid intf_uuid = vm_itf->GetUuid();
    1136         973 :     const VnEntry *vn = vm_itf->vn();
    1137         973 :     MulticastGroupObject *all_broadcast = NULL;
    1138         973 :     boost::system::error_code ec;
    1139         973 :     Ip4Address broadcast =  IpAddress::from_string("255.255.255.255",
    1140         973 :                                                    ec).to_v4();
    1141         973 :     bool add_route = false;
    1142         973 :     std::string vn_name = vn->GetName();
    1143             : 
    1144             :     //TODO Push every thing via multi proto and remove multi proto check
    1145             :     //All broadcast addition 255.255.255.255
    1146         973 :     all_broadcast = this->FindGroupObject(vrf_name, Ip4Address(), broadcast);
    1147         973 :     if (all_broadcast == NULL) {
    1148          27 :         all_broadcast = CreateMulticastGroupObject(vrf_name, vn->GetName(),
    1149           0 :                                         Ip4Address(), broadcast,
    1150          27 :                                         vn->GetVxLanId());
    1151          27 :         add_route = true;
    1152             :     }
    1153             : 
    1154             :     //Modify Nexthops
    1155         973 :     if (all_broadcast->AddLocalMember(intf_uuid, vm_itf->vm_mac()) == true) {
    1156         973 :         TriggerLocalRouteChange(all_broadcast, agent_->local_vm_peer());
    1157         973 :         AddVmToMulticastObjMap(intf_uuid, all_broadcast);
    1158             :     }
    1159             :     //Modify routes
    1160         973 :     if (add_route) {
    1161          27 :         if (TunnelType::ComputeType(TunnelType::AllType()) ==
    1162             :             TunnelType::VXLAN) {
    1163           0 :             all_broadcast->set_vxlan_id(vn->GetVxLanId());
    1164             :         }
    1165          27 :         TriggerLocalRouteChange(all_broadcast, agent_->local_vm_peer());
    1166             :     }
    1167         973 : }
    1168             : 
    1169             : /*
    1170             :  * Static funtion to be called to handle XMPP info from ctrl node
    1171             :  * Key is VRF/G/S
    1172             :  * Info has label (for source to vrouter) and
    1173             :  * OLIST of NH (server IP + label for that server)
    1174             :  */
    1175           0 : void MulticastHandler::ModifyFabricMembers(const Peer *peer,
    1176             :                                            const std::string &vrf_name,
    1177             :                                            const Ip4Address &grp,
    1178             :                                            const Ip4Address &src,
    1179             :                                            uint32_t label,
    1180             :                                            const TunnelOlist &olist,
    1181             :                                            uint64_t peer_identifier)
    1182             : {
    1183           0 :     boost::system::error_code ec;
    1184           0 :     MulticastGroupObject *obj = NULL;
    1185           0 :     obj = FindActiveGroupObject(vrf_name, src, grp);
    1186           0 :     MCTRACE(LogSG, "XMPP call(edge replicate) multicast handler ", vrf_name,
    1187             :             src.to_string(), grp.to_string(), label);
    1188             : 
    1189           0 :     bool delete_op = false;
    1190             : 
    1191             :     //Invalid peer identifier signifies delete.
    1192             :     //If add operation, obj should exist, else return.
    1193           0 :     if (peer_identifier == ControllerPeerPath::kInvalidPeerIdentifier) {
    1194           0 :         delete_op = true;
    1195           0 :     } else if (obj == NULL) {
    1196           0 :         return;
    1197             :     }
    1198             : 
    1199           0 :     if (peer == NULL) {
    1200           0 :         return;
    1201             :     }
    1202             : 
    1203           0 :     if (obj) {
    1204           0 :         if (delete_op) {
    1205           0 :             obj->set_peer(NULL);
    1206           0 :             TunnelOlist empty_list;
    1207           0 :             obj->set_fabric_olist(empty_list);
    1208           0 :             obj->set_fabric_label(label);
    1209           0 :         } else {
    1210           0 :             obj->set_peer(peer);
    1211           0 :             obj->set_fabric_olist(olist);
    1212           0 :             obj->set_fabric_label(label);
    1213             :         }
    1214             :     }
    1215             : 
    1216             :     Ip4Address bcast_addr =
    1217           0 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
    1218           0 :     Composite::Type comp_type = Composite::FABRIC;
    1219           0 :     if (grp != bcast_addr) {
    1220           0 :         comp_type = Composite::L3FABRIC;
    1221             :     }
    1222             : 
    1223           0 :     TriggerRemoteRouteChange(obj, peer, vrf_name, src, grp, olist,
    1224             :                              peer_identifier,
    1225             :                              delete_op, comp_type,
    1226             :                              label, true, 0);
    1227             : 
    1228           0 :     if (obj == NULL) {
    1229           0 :         return;
    1230             :     }
    1231             : 
    1232           0 :     for (MulticastGroupObject::MGList::iterator iter = obj->mg_list_begin();
    1233           0 :          iter != obj->mg_list_end(); iter++) {
    1234             :         MulticastGroupObject *mg =
    1235           0 :             static_cast<MulticastGroupObject *>(iter.operator->());
    1236           0 :         TriggerRemoteRouteChange(mg, peer, iter->vrf_name(), src, grp,
    1237             :                                  olist, peer_identifier,
    1238             :                                  delete_op, comp_type,
    1239             :                                  label, true, 0);
    1240             :     }
    1241             : 
    1242           0 :     MCTRACE(LogSG, "Add fabric grp label ", vrf_name, src.to_string(),
    1243             :                                 grp.to_string(), label);
    1244             : }
    1245             : 
    1246           0 : void MulticastHandler::ModifyEvpnMembers(const Peer *peer,
    1247             :                                          const std::string &vrf_name,
    1248             :                                          const Ip4Address &grp,
    1249             :                                          const Ip4Address &src,
    1250             :                                          const TunnelOlist &olist,
    1251             :                                          uint32_t ethernet_tag,
    1252             :                                          uint64_t peer_identifier) {
    1253             : 
    1254           0 :     boost::system::error_code ec;
    1255           0 :     MulticastGroupObject *obj = FindActiveGroupObject(vrf_name, src, grp);
    1256             : 
    1257           0 :     MCTRACE(LogSG, "XMPP call(EVPN) multicast handler ", vrf_name, src.to_string(),
    1258             :                                     grp.to_string(), 0);
    1259             : 
    1260           0 :     bool delete_op = false;
    1261           0 :     if (peer_identifier == ControllerPeerPath::kInvalidPeerIdentifier) {
    1262           0 :         delete_op = true;
    1263           0 :     } else if (obj == NULL) {
    1264           0 :         return;
    1265             :     }
    1266             : 
    1267           0 :     TriggerRemoteRouteChange(obj, peer, vrf_name, src, grp, olist,
    1268             :                                     peer_identifier, delete_op,
    1269             :                                     Composite::EVPN, MplsTable::kInvalidLabel,
    1270             :                                     false, ethernet_tag);
    1271             : 
    1272           0 :     MCTRACE(LogSG, "Add EVPN TOR Olist ", vrf_name, src.to_string(),
    1273             :                                     grp.to_string(), 0);
    1274             : 
    1275           0 :     return;
    1276             : }
    1277             : 
    1278             : /*
    1279             :  * Request to populate evpn olist by list of TOR NH seen by control node
    1280             :  * Currently this is done only for TOR/Gateway(outside contrail vrouter network)
    1281             :  * Source label is ignored as it is used by non-vrouters.
    1282             :  * Olist consists of TOR/Gateway endpoints with label advertised or use VXLAN.
    1283             :  * Note: Non Vrouter can talk in VXLAN/MPLS. Encap received in XMPP will
    1284             :  * convey the same.
    1285             :  */
    1286           0 : void MulticastHandler::ModifyEvpnMembers(const Peer *peer,
    1287             :                                          const std::string &vrf_name,
    1288             :                                          const TunnelOlist &olist,
    1289             :                                          uint32_t ethernet_tag,
    1290             :                                          uint64_t peer_identifier)
    1291             : {
    1292           0 :     boost::system::error_code ec;
    1293           0 :     Ip4Address grp = Ip4Address::from_string("255.255.255.255", ec);
    1294           0 :     MulticastGroupObject *obj = FindActiveGroupObject(vrf_name,
    1295           0 :                                     Ip4Address(), grp);
    1296           0 :     std::string derived_vrf_name = vrf_name;
    1297             : 
    1298           0 :     if (ethernet_tag && obj) {
    1299             :         MulticastGroupObject *dependent_mg =
    1300           0 :             obj->GetDependentMG(ethernet_tag);
    1301           0 :         if (dependent_mg) {
    1302           0 :             obj = dependent_mg;
    1303           0 :             derived_vrf_name = obj->vrf_name();
    1304             :         }
    1305             :     }
    1306             : 
    1307           0 :     MCTRACE(Log, "XMPP call(EVPN) multicast handler ", derived_vrf_name,
    1308             :             grp.to_string(), 0);
    1309             : 
    1310           0 :     bool delete_op = false;
    1311           0 :     if (peer_identifier == ControllerPeerPath::kInvalidPeerIdentifier) {
    1312           0 :         delete_op = true;
    1313           0 :     } else if (obj == NULL) {
    1314           0 :         return;
    1315             :     }
    1316             : 
    1317           0 :     TriggerRemoteRouteChange(obj, peer, derived_vrf_name, Ip4Address(), grp,
    1318             :                              olist, peer_identifier, delete_op, Composite::EVPN,
    1319             :                              MplsTable::kInvalidLabel, false, ethernet_tag);
    1320           0 :     MCTRACE(Log, "Add EVPN TOR Olist ", derived_vrf_name, grp.to_string(), 0);
    1321           0 : }
    1322             : 
    1323           0 : void MulticastHandler::ModifyTorMembers(const Peer *peer,
    1324             :                                         const std::string &vrf_name,
    1325             :                                         const TunnelOlist &olist,
    1326             :                                         uint32_t ethernet_tag,
    1327             :                                         uint64_t peer_identifier)
    1328             : {
    1329           0 :     boost::system::error_code ec;
    1330             : 
    1331           0 :     Ip4Address grp = Ip4Address::from_string("255.255.255.255", ec);
    1332           0 :     MulticastGroupObject *obj = FindActiveGroupObject(vrf_name, Ip4Address(),
    1333             :                                     grp);
    1334           0 :     MCTRACE(Log, "TOR multicast handler ", vrf_name, grp.to_string(), 0);
    1335             : 
    1336           0 :     bool delete_op = false;
    1337           0 :     if (peer_identifier == ControllerPeerPath::kInvalidPeerIdentifier) {
    1338           0 :         delete_op = true;
    1339           0 :     } else if (obj == NULL) {
    1340           0 :         return;
    1341             :     }
    1342             : 
    1343           0 :     TriggerRemoteRouteChange(obj, peer, vrf_name, Ip4Address(), grp, olist,
    1344             :                              peer_identifier, delete_op, Composite::TOR,
    1345             :                              MplsTable::kInvalidLabel, false, ethernet_tag);
    1346           0 :     MCTRACE(Log, "Add external TOR Olist ", vrf_name, grp.to_string(), 0);
    1347             : }
    1348             : 
    1349           0 : void MulticastHandler::ModifyMvpnVrfRegistration(const Peer *peer,
    1350             :                              const std::string &vrf_name,
    1351             :                              const Ip4Address &grp,
    1352             :                              const Ip4Address &src,
    1353             :                              uint64_t peer_identifier) {
    1354             : 
    1355           0 :     MulticastGroupObject *obj = NULL;
    1356           0 :     obj = FindGroupObject(vrf_name, src, grp);
    1357             : 
    1358           0 :     bool delete_op = false;
    1359           0 :     if (peer_identifier == ControllerPeerPath::kInvalidPeerIdentifier) {
    1360           0 :         delete_op = true;
    1361           0 :     } if (!obj) {
    1362           0 :         return;
    1363             :     }
    1364             : 
    1365           0 :     TunnelOlist olist;
    1366           0 :     TriggerRemoteRouteChange(obj, peer, vrf_name, src, grp, olist,
    1367             :                              peer_identifier, delete_op, Composite::L3FABRIC, 0,
    1368             :                              true, 0);
    1369           0 :     return;
    1370           0 : }
    1371             : 
    1372             : // Helper to delete fabric nh
    1373             : // For internal delete it uses invalid identifier.
    1374             : // For delete via control node it uses the sequence sent.
    1375          54 : void MulticastGroupObject::FlushAllPeerInfo(const Agent *agent,
    1376             :                                             const Peer *peer,
    1377             :                                             uint64_t peer_identifier) {
    1378          54 :     if ((peer_identifier != peer_identifier_) ||
    1379             :         (peer_identifier == INVALID_PEER_IDENTIFIER)) {
    1380          54 :         boost::system::error_code ec;
    1381          54 :         Ip4Address bcast_addr = IpAddress::from_string("255.255.255.255",
    1382          54 :                                                        ec).to_v4();
    1383          54 :         if (GetGroupAddress() != bcast_addr) {
    1384           0 :             agent->oper_db()->multicast()->DeleteMulticastRoute(peer,
    1385           0 :                                                        vrf_name_, src_address_,
    1386           0 :                                                        grp_address_, 0,
    1387             :                                                        Composite::L3FABRIC);
    1388             :         } else {
    1389          54 :             agent->oper_db()->multicast()->DeleteBroadcast(peer, vrf_name_, 0,
    1390             :                                                        Composite::FABRIC);
    1391          54 :             MCTRACE(Log, "Delete broadcast route", vrf_name_,
    1392             :                 grp_address_.to_string(), 0);
    1393             :         }
    1394             :     }
    1395          54 : }
    1396             : 
    1397           2 : MulticastHandler::MulticastHandler(Agent *agent) :
    1398           2 :     agent_(agent),
    1399           2 :     vn_listener_id_(DBTable::kInvalidId),
    1400           2 :     interface_listener_id_(DBTable::kInvalidId),
    1401           2 :     physical_device_listener_id_(DBTable::kInvalidId),
    1402           2 :     physical_devices_() {
    1403           2 :     if (agent_->tsn_no_forwarding_enabled()) {
    1404           0 :         te_walker_.reset(new MulticastTEWalker("MulticastTorElectorWalker", agent));
    1405             :     }
    1406           2 :     obj_ = this;
    1407           2 : }
    1408             : 
    1409          19 : bool MulticastHandler::FlushPeerInfo(uint64_t peer_sequence) {
    1410          19 :     for (std::set<MulticastGroupObject *>::iterator it =
    1411          92 :          GetMulticastObjList().begin(); it != GetMulticastObjList().end();
    1412          54 :          it++) {
    1413             :         //Delete all control node given paths
    1414          54 :         (*it)->FlushAllPeerInfo(agent_, agent_->multicast_tree_builder_peer(),
    1415             :                                 peer_sequence);
    1416             :     }
    1417          19 :     return false;
    1418             : }
    1419             : 
    1420             : /*
    1421             :  * Shutdown for clearing all stuff related to multicast
    1422             :  */
    1423           2 : void MulticastHandler::Shutdown() {
    1424             : 
    1425           2 :     boost::system::error_code ec;
    1426           2 :     Ip4Address bcast_addr = IpAddress::from_string("255.255.255.255",
    1427           2 :                                                        ec).to_v4();
    1428             :     //Delete all route mpls and trigger cnh change
    1429           2 :     for (std::set<MulticastGroupObject *>::iterator it =
    1430           4 :          GetMulticastObjList().begin(); it != GetMulticastObjList().end();
    1431           0 :          it++) {
    1432           0 :         MulticastGroupObject *obj = (*it);
    1433             : 
    1434           0 :         AgentRoute *route = NULL;
    1435           0 :         if (obj->GetGroupAddress() != bcast_addr) {
    1436             :             Inet4MulticastAgentRouteTable *mtable =
    1437           0 :                 dynamic_cast<Inet4MulticastAgentRouteTable *>
    1438           0 :                 (agent_->vrf_table()->GetInet4MulticastRouteTable(obj->vrf_name()));
    1439           0 :             if (mtable) {
    1440           0 :                 route = mtable->FindRoute(obj->GetGroupAddress(),
    1441             :                                 obj->GetSourceAddress());
    1442             :             }
    1443             :         } else {
    1444             :             BridgeAgentRouteTable *bridge_table =
    1445             :                 static_cast<BridgeAgentRouteTable *>
    1446           0 :                 (agent_->vrf_table()->GetBridgeRouteTable(obj->vrf_name()));
    1447           0 :             if (bridge_table) {
    1448           0 :                 route = bridge_table->FindRoute(MacAddress::BroadcastMac());
    1449             :             }
    1450             :         }
    1451             : 
    1452           0 :         if (route == NULL) {
    1453           0 :             delete (obj);
    1454           0 :             this->GetMulticastObjList().erase(obj);
    1455           0 :             continue;
    1456             :         }
    1457             : 
    1458           0 :         for(Route::PathList::iterator it = route->GetPathList().begin();
    1459           0 :             it != route->GetPathList().end(); it++) {
    1460             :             const AgentPath *path =
    1461           0 :                 static_cast<const AgentPath *>(it.operator->());
    1462             :             //Delete the tunnel OLIST
    1463           0 :             (obj)->FlushAllPeerInfo(agent_,
    1464             :                                     path->peer(),
    1465             :                                     INVALID_PEER_IDENTIFIER);
    1466             :         }
    1467             :         //Delete the multicast object
    1468           0 :         delete (obj);
    1469           0 :         this->GetMulticastObjList().erase(obj);
    1470             :     }
    1471           2 : }
    1472             : 
    1473          69 : void MulticastHandler::ResyncDependentVrf(MulticastGroupObject *obj) {
    1474             :     std::set<MulticastGroupObject *>::iterator it =
    1475          69 :         multicast_obj_list_.begin();
    1476         219 :     for (; it != multicast_obj_list_.end(); it++) {
    1477             :         MulticastGroupObject *mg =
    1478         150 :             static_cast<MulticastGroupObject *>(*it);
    1479         150 :         if (mg->pbb_vrf() && mg->pbb_vrf_name() == obj->vrf_name()) {
    1480             :             //Since reference is getting added on
    1481             :             //addition, any eventual fabric notification
    1482             :             //will result in ISID VRF also getting updated
    1483           0 :             mg->set_dependent_mg(obj);
    1484           0 :             TriggerLocalRouteChange(mg, agent_->local_vm_peer());
    1485             :         }
    1486             :     }
    1487          69 : }
    1488             : 
    1489          69 : void MulticastHandler::UpdateReference(MulticastGroupObject *obj) {
    1490          69 :     VrfKey key(obj->vrf_name());
    1491             :     VrfEntry *vrf =
    1492          69 :         static_cast<VrfEntry *>(agent_->vrf_table()->FindActiveEntry(&key));
    1493          69 :     if (vrf && vrf->IsPbbVrf()) {
    1494             :         //ISID VRF are dependent on BMAC VRF to build egde replication
    1495             :         //tree, take a reference on BMAC VRF so that every time
    1496             :         //BMAC VRF fabric list changes, ISID VRF can also be updated
    1497           0 :         obj->set_pbb_vrf(true);
    1498           0 :         obj->set_pbb_vrf_name(vrf->bmac_vrf_name());
    1499             : 
    1500             :         //Set dependent VRF
    1501             :         MulticastGroupObject *dependent_mg =
    1502           0 :             FindFloodGroupObject(vrf->bmac_vrf_name());
    1503           0 :         obj->set_dependent_mg(dependent_mg);
    1504           0 :         Resync(obj);
    1505             :     } else {
    1506             :         //If this a BMAC VRF, there may be ISID VRF dependent
    1507             :         //on this new BMAC VRF
    1508             :         //Evaulate them
    1509          69 :         ResyncDependentVrf(obj);
    1510             :     }
    1511          69 : }
    1512             : 
    1513           0 : void MulticastHandler::Resync(MulticastGroupObject *obj) {
    1514           0 :     MulticastGroupObject *dependent_mg = obj->dependent_mg();
    1515           0 :     if (dependent_mg && dependent_mg->peer()) {
    1516           0 :         ModifyFabricMembers(dependent_mg->peer(),
    1517             :                             dependent_mg->vrf_name(),
    1518             :                             dependent_mg->GetGroupAddress(),
    1519             :                             dependent_mg->GetSourceAddress(),
    1520             :                             dependent_mg->fabric_label(),
    1521             :                             dependent_mg->fabric_olist(),
    1522             :                             dependent_mg->peer_identifier());
    1523             :     }
    1524           0 :     TriggerLocalRouteChange(obj, agent_->local_vm_peer());
    1525           0 : }
    1526             : 
    1527           0 : void MulticastHandler::DeleteEvpnPath(MulticastGroupObject *obj) {
    1528           0 :     VrfKey key(obj->vrf_name());
    1529             :     VrfEntry *vrf =
    1530           0 :         static_cast <VrfEntry *>(agent_->vrf_table()->FindActiveEntry(&key));
    1531           0 :     if (vrf == NULL) {
    1532           0 :         return;
    1533             :     }
    1534             : 
    1535             :     BridgeAgentRouteTable *br_table =
    1536           0 :         static_cast<BridgeAgentRouteTable *>(vrf->GetBridgeRouteTable());
    1537             :     BridgeRouteEntry *bridge_route =
    1538           0 :         br_table->FindRoute(MacAddress::BroadcastMac());
    1539           0 :     if (bridge_route == NULL){
    1540           0 :         return;
    1541             :     }
    1542             : 
    1543           0 :     for(Route::PathList::iterator it = bridge_route->GetPathList().begin();
    1544           0 :         it != bridge_route->GetPathList().end();it++) {
    1545             :         AgentPath *path =
    1546           0 :             static_cast<AgentPath *>(it.operator->());
    1547           0 :         const Peer *peer = path->peer();
    1548           0 :         if (peer && peer->GetType() == Peer::BGP_PEER) {
    1549           0 :             DeleteBroadcast(peer, obj->vrf_name(), obj->vxlan_id(),
    1550             :                             Composite::EVPN);
    1551             :         }
    1552             :     }
    1553           0 : }
    1554             : 
    1555           0 : void MulticastHandler::AddLocalPeerRoute(MulticastGroupObject *sg_object) {
    1556             : 
    1557           0 :     ComponentNHKeyList component_nh_key_list;
    1558             : 
    1559             :     uint32_t route_tunnel_bmap;
    1560           0 :     route_tunnel_bmap = agent_->params()->mvpn_ipv4_enable() ?
    1561           0 :                             TunnelType::AllType() : TunnelType::VxlanType();
    1562             : 
    1563             :     AgentRouteData *data =
    1564           0 :         BridgeAgentRouteTable::BuildNonBgpPeerData(sg_object->vrf_name(),
    1565             :                                     sg_object->GetVnName(), 0,
    1566           0 :                                     sg_object->vxlan_id(),
    1567             :                                     route_tunnel_bmap, Composite::L3COMP,
    1568           0 :                                     component_nh_key_list, sg_object->pbb_vrf(),
    1569           0 :                                     sg_object->learning_enabled());
    1570           0 :     Inet4MulticastAgentRouteTable::AddMulticastRoute(agent_->local_peer(),
    1571             :                                     sg_object->vrf_name(),
    1572             :                                     sg_object->GetSourceAddress(),
    1573             :                                     sg_object->GetGroupAddress(),
    1574             :                                     sg_object->vxlan_id(), data);
    1575             : 
    1576           0 :     if (!agent_->params()->mvpn_ipv4_enable()) {
    1577           0 :         MacAddress mac;
    1578           0 :         GetMulticastMacFromIp(sg_object->GetGroupAddress(), mac);
    1579             : 
    1580             :         AgentRouteData *bridge_data =
    1581           0 :             BridgeAgentRouteTable::BuildNonBgpPeerData(sg_object->vrf_name(),
    1582             :                                     sg_object->GetVnName(), 0,
    1583           0 :                                     sg_object->vxlan_id(),
    1584             :                                     route_tunnel_bmap, Composite::L2COMP,
    1585           0 :                                     component_nh_key_list, sg_object->pbb_vrf(),
    1586           0 :                                     sg_object->learning_enabled());
    1587           0 :         BridgeAgentRouteTable::AddBridgeRoute(agent_->local_peer(),
    1588             :                                     sg_object->vrf_name(), mac,
    1589             :                                     sg_object->vxlan_id(), bridge_data);
    1590             :     }
    1591             : 
    1592           0 :     return;
    1593           0 : }
    1594             : 
    1595           0 : void MulticastHandler::DeleteLocalPeerRoute(MulticastGroupObject *sg_object) {
    1596             : 
    1597           0 :     Inet4MulticastAgentRouteTable::DeleteMulticastRoute(agent_->local_peer(),
    1598             :                                     sg_object->vrf_name(),
    1599             :                                     sg_object->GetSourceAddress(),
    1600             :                                     sg_object->GetGroupAddress(),
    1601             :                                     sg_object->vxlan_id(), Composite::L3COMP);
    1602             : 
    1603           0 :     MacAddress mac;
    1604           0 :     GetMulticastMacFromIp(sg_object->GetGroupAddress(), mac);
    1605             : 
    1606           0 :     BridgeAgentRouteTable::DeleteBridgeRoute(agent_->local_peer(),
    1607             :                                     sg_object->vrf_name(), mac,
    1608             :                                     sg_object->vxlan_id(), Composite::L2COMP);
    1609           0 : }
    1610             : 
    1611             : // Create MulticastGroupObject on learning new <S,G>
    1612             : //
    1613             : // Note :
    1614             : //   For EVPN:  Routes are added to both Inet Multicast table
    1615             : //              and Bridge table in the native VRF only.
    1616             : //   For MVPN:  Routes are added to Inet Multicast table only
    1617             : //              but in both the native VRF and ip-fabric VRF.
    1618             : //   However, API CreateMulticastVrfSourceGroup is used only for
    1619             : //   EVPN for now.
    1620             : //
    1621           0 : void MulticastHandler::CreateMulticastVrfSourceGroup(
    1622             :                                     const std::string &vrf_name,
    1623             :                                     const std::string &vn_name,
    1624             :                                     const Ip4Address &src_addr,
    1625             :                                     const Ip4Address &grp_addr) {
    1626             : 
    1627           0 :     VrfEntry *vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
    1628           0 :     if (!vrf || vrf->IsDeleted()) return;
    1629             : 
    1630           0 :     MCTRACE(LogSG, "Add SG ", vrf_name, src_addr.to_string(),
    1631             :                             grp_addr.to_string(), 0);
    1632             : 
    1633           0 :     bool created = false;
    1634           0 :     MulticastGroupObject *sg_object = NULL;
    1635           0 :     sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1636           0 :     if (sg_object == NULL) {
    1637           0 :         sg_object = CreateMulticastGroupObject(vrf_name, vn_name,
    1638             :                                     src_addr, grp_addr, vrf->vxlan_id());
    1639           0 :         AddLocalPeerRoute(sg_object);
    1640           0 :         created = true;
    1641             :     }
    1642             : 
    1643           0 :     if (created) {
    1644           0 :         TriggerLocalRouteChange(sg_object, agent_->local_vm_peer());
    1645             :     }
    1646             : 
    1647           0 :     MCTRACE(LogSG, "Add SG done ", vrf_name, src_addr.to_string(),
    1648             :                             grp_addr.to_string(), 0);
    1649             : 
    1650           0 :     return;
    1651             : }
    1652             : 
    1653             : // Delete VM-Interface from a MulticastGroupObject
    1654             : // Delete of VMI will trigger route change for the <S,G>
    1655             : // Last VMI to go will also trigger cleaning up of route
    1656             : // and also the VRF,<S,G> data structure.
    1657             : // API used in case of EVPN
    1658           0 : void MulticastHandler::HandleRouteChangeAndMulticastObject(
    1659             :                                 MulticastGroupObject *sg_object,
    1660             :                                 boost::uuids::uuid vm_itf_uuid) {
    1661             : 
    1662           0 :     if (!sg_object) {
    1663           0 :         return;
    1664             :     }
    1665             : 
    1666           0 :     Composite::Type comp_type = Composite::L3INTERFACE;
    1667             : 
    1668           0 :     if ((sg_object->DeleteLocalMember(vm_itf_uuid) == true) &&
    1669           0 :         (sg_object->IsDeleted() == false) &&
    1670           0 :         (sg_object->GetLocalListSize() != 0)) {
    1671             : 
    1672           0 :         TriggerLocalRouteChange(sg_object, agent_->local_vm_peer());
    1673           0 :         MCTRACE(LogSG, "modify route, vm is deleted for <S,G> ",
    1674             :                             sg_object->vrf_name(),
    1675             :                             sg_object->GetSourceAddress().to_string(),
    1676             :                             sg_object->GetGroupAddress().to_string(), 0);
    1677             :     }
    1678             : 
    1679           0 :     if (sg_object->GetLocalListSize() == 0) {
    1680           0 :         if (sg_object->vrf_name() != agent_->fabric_policy_vrf_name()) {
    1681           0 :             MulticastGroupObject *mvpn_sg_object = NULL;
    1682           0 :             mvpn_sg_object = FindGroupObject(
    1683           0 :                                     agent_->fabric_policy_vrf_name(),
    1684             :                                     sg_object->GetSourceAddress(),
    1685             :                                     sg_object->GetGroupAddress());
    1686           0 :             if (mvpn_sg_object)
    1687           0 :                 mvpn_sg_object->decr_vn_count();
    1688             :         }
    1689             :     }
    1690             : 
    1691           0 :     if ((sg_object->GetLocalListSize() == 0) &&
    1692           0 :         (sg_object->vn_count() == 0)) {
    1693             : 
    1694             :         //Time to delete route(for mcast address) and mpls
    1695           0 :         DeleteMulticastRoute(agent_->local_vm_peer(),
    1696             :                             sg_object->vrf_name(),
    1697             :                             sg_object->GetSourceAddress(),
    1698             :                             sg_object->GetGroupAddress(), 0, comp_type);
    1699           0 :         DeleteLocalPeerRoute(sg_object);
    1700           0 :         DeleteMulticastObject(sg_object->vrf_name(),
    1701             :                             sg_object->GetSourceAddress(),
    1702             :                             sg_object->GetGroupAddress());
    1703             :     }
    1704             : 
    1705           0 :     return;
    1706             : }
    1707             : 
    1708             : // Delete all VM-Interfaces for a particular <S,G> for a particular VRF
    1709             : // API used in case of EVPN
    1710           0 : void MulticastHandler::DeleteMulticastVrfSourceGroup(
    1711             :                                     const std::string &vrf_name,
    1712             :                                     const Ip4Address &src_addr,
    1713             :                                     const Ip4Address &grp_addr) {
    1714             : 
    1715           0 :     MulticastGroupObject *sg_object = NULL;
    1716             : 
    1717           0 :     MCTRACE(LogSG, "Delete SG ", vrf_name, src_addr.to_string(),
    1718             :                             grp_addr.to_string(), 0);
    1719             : 
    1720           0 :     sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1721           0 :     if (!sg_object) {
    1722           0 :         return;
    1723             :     }
    1724             : 
    1725           0 :     std::map<uuid, MacAddress>::const_iterator it;
    1726           0 :     it = sg_object->GetLocalList().begin();
    1727           0 :     while (it != sg_object->GetLocalList().end()) {
    1728             : 
    1729           0 :         boost::uuids::uuid vm_itf_uuid = it->first;
    1730           0 :         HandleRouteChangeAndMulticastObject(sg_object, vm_itf_uuid);
    1731             : 
    1732           0 :         DeleteVmToMulticastObjMap(vm_itf_uuid, sg_object);
    1733             : 
    1734           0 :         MCTRACE(LogSG, "VMI delete notify done for <S,G> ", vrf_name,
    1735             :                                 src_addr.to_string(), grp_addr.to_string(), 0);
    1736             : 
    1737           0 :         sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1738           0 :         if (sg_object) {
    1739           0 :             it = sg_object->GetLocalList().begin();
    1740             :         } else  {
    1741           0 :             break;
    1742             :         }
    1743             :     }
    1744             : 
    1745           0 :     MCTRACE(LogSG, "Delete SG done ", vrf_name, src_addr.to_string(),
    1746             :                             grp_addr.to_string(), 0);
    1747             : 
    1748           0 :     return;
    1749             : }
    1750             : 
    1751             : // Add VM-Interface for a particular <S,G> for a particular VRF
    1752             : // API used in case of MVPN and also EVPN
    1753           0 : bool MulticastHandler::AddVmInterfaceToVrfSourceGroup(
    1754             :                                     const std::string &vrf_name,
    1755             :                                     const std::string &vn_name,
    1756             :                                     const VmInterface *vm_itf,
    1757             :                                     const Ip4Address &src_addr,
    1758             :                                     const Ip4Address &grp_addr) {
    1759             : 
    1760           0 :     VrfEntry *vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
    1761           0 :     if (!vrf || vrf->IsDeleted()) return false;
    1762             : 
    1763           0 :     MCTRACE(LogSG, "VMI add notify ", vrf_name, src_addr.to_string(),
    1764             :                             grp_addr.to_string(), 0);
    1765             : 
    1766           0 :     const uuid intf_uuid = vm_itf->GetUuid();
    1767           0 :     MulticastGroupObject *sg_object = NULL;
    1768             : 
    1769           0 :     bool created = false;
    1770             : 
    1771           0 :     sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1772           0 :     if (sg_object == NULL) {
    1773           0 :         sg_object = CreateMulticastGroupObject(vrf_name, vn_name, src_addr,
    1774             :                                     grp_addr, vrf->vxlan_id());
    1775           0 :         AddLocalPeerRoute(sg_object);
    1776           0 :         created = true;
    1777             :     }
    1778             : 
    1779             :     //Modify Nexthops
    1780           0 :     if (sg_object->AddLocalMember(intf_uuid, vm_itf->vm_mac()) == true) {
    1781           0 :         TriggerLocalRouteChange(sg_object, agent_->local_vm_peer());
    1782           0 :         AddVmToMulticastObjMap(intf_uuid, sg_object);
    1783           0 :     } else if (created) {
    1784             :         //Modify routes
    1785           0 :         TriggerLocalRouteChange(sg_object, agent_->local_vm_peer());
    1786             :     }
    1787             : 
    1788           0 :     MCTRACE(LogSG, "VMI add notify done ", vrf_name, src_addr.to_string(),
    1789             :                             grp_addr.to_string(), 0);
    1790             : 
    1791           0 :     return created;
    1792             : }
    1793             : 
    1794             : // Add VM-Interface for a particular <S,G>
    1795             : // API used in case of MVPN
    1796           0 : void MulticastHandler::AddVmInterfaceToSourceGroup(
    1797             :                                     const std::string &mc_vrf_name,
    1798             :                                     const std::string &vn_name,
    1799             :                                     const VmInterface *vm_itf,
    1800             :                                     const Ip4Address &src_addr,
    1801             :                                     const Ip4Address &grp_addr) {
    1802             : 
    1803           0 :     VrfEntry *vrf = agent_->vrf_table()->FindVrfFromName(mc_vrf_name);
    1804           0 :     if (!vrf || vrf->IsDeleted()) return;
    1805             : 
    1806           0 :     MCTRACE(LogSG, "VMI add notify ", mc_vrf_name, src_addr.to_string(),
    1807             :                             grp_addr.to_string(), 0);
    1808             : 
    1809           0 :     bool created = false;
    1810           0 :     created = AddVmInterfaceToVrfSourceGroup(vm_itf->vrf()->GetName(), vn_name,
    1811             :                                     vm_itf, src_addr, grp_addr);
    1812             : 
    1813           0 :     MulticastGroupObject *mvpn_sg_object = NULL;
    1814             : 
    1815           0 :     MulticastGroupObject *sg_object = NULL;
    1816           0 :     sg_object = FindGroupObject(vm_itf->vrf()->GetName(), src_addr, grp_addr);
    1817           0 :     if (sg_object) {
    1818           0 :         if (sg_object->mvpn_registered()) {
    1819           0 :             AddVmInterfaceToVrfSourceGroup(mc_vrf_name,
    1820             :                                     vn_name, vm_itf, src_addr, grp_addr);
    1821           0 :             mvpn_sg_object = FindGroupObject(mc_vrf_name, src_addr, grp_addr);
    1822             :         } else {
    1823           0 :             mvpn_sg_object = FindGroupObject(mc_vrf_name, src_addr, grp_addr);
    1824           0 :             if (mvpn_sg_object == NULL) {
    1825           0 :                 mvpn_sg_object = CreateMulticastGroupObject(mc_vrf_name,
    1826             :                                     vn_name, src_addr, grp_addr, vrf->vxlan_id());
    1827           0 :                 AddLocalPeerRoute(sg_object);
    1828           0 :                 TriggerLocalRouteChange(mvpn_sg_object, agent_->local_vm_peer());
    1829             :             }
    1830             :         }
    1831             :     }
    1832           0 :     if (created) {
    1833           0 :         mvpn_sg_object->incr_vn_count();
    1834             :     }
    1835             : 
    1836           0 :     MCTRACE(LogSG, "VMI add notify done ", mc_vrf_name, src_addr.to_string(),
    1837             :                             grp_addr.to_string(), 0);
    1838             : 
    1839           0 :     return;
    1840             : }
    1841             : 
    1842             : // Delete VM-Interface from a particular <S,G> for the specified VRF.
    1843             : // API used in case of MVPN and also EVPN
    1844           0 : void MulticastHandler::DeleteVmInterfaceFromVrfSourceGroup(
    1845             :                                     const std::string &vrf_name,
    1846             :                                     const VmInterface *vm_itf,
    1847             :                                     const Ip4Address &src_addr,
    1848             :                                     const Ip4Address &grp_addr) {
    1849             : 
    1850           0 :     MulticastGroupObject *sg_object = NULL;
    1851             : 
    1852           0 :     sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1853           0 :     if (!sg_object) {
    1854           0 :         return;
    1855             :     }
    1856             : 
    1857           0 :     MCTRACE(LogSG, "VMI delete notify ", vrf_name, src_addr.to_string(),
    1858             :                             grp_addr.to_string(), 0);
    1859             : 
    1860           0 :     boost::uuids::uuid vm_itf_uuid = vm_itf->GetUuid();
    1861           0 :     HandleRouteChangeAndMulticastObject(sg_object, vm_itf_uuid);
    1862             : 
    1863           0 :     DeleteVmToMulticastObjMap(vm_itf->GetUuid(), sg_object);
    1864             : 
    1865           0 :     MCTRACE(LogSG, "VMI delete notify done ", vrf_name, src_addr.to_string(),
    1866             :                             grp_addr.to_string(), 0);
    1867             : 
    1868           0 :     return;
    1869             : }
    1870             : 
    1871             : // Delete VM-Interface from a particular <S,G>
    1872             : // API used in case of MVPN
    1873           0 : void MulticastHandler::DeleteVmInterfaceFromSourceGroup(
    1874             :                                     const std::string &mc_vrf_name,
    1875             :                                     const VmInterface *vm_itf,
    1876             :                                     const Ip4Address &src_addr,
    1877             :                                     const Ip4Address &grp_addr) {
    1878             : 
    1879           0 :     DeleteVmInterfaceFromVrfSourceGroup(vm_itf->vrf()->GetName(),
    1880             :                                     vm_itf, src_addr, grp_addr);
    1881           0 :     DeleteVmInterfaceFromVrfSourceGroup(mc_vrf_name, vm_itf, src_addr,
    1882             :                                     grp_addr);
    1883           0 : }
    1884             : 
    1885             : // Delete VM-Interface from all the learnt <S,G>s belonging
    1886             : // to a particular group for the specified VRF.
    1887             : // API used in case of MVPN and also EVPN
    1888             : // grp_addr, when default, indicate all <S,G>s except broadcast.
    1889           0 : void MulticastHandler::DeleteVmInterfaceFromVrfSourceGroup(
    1890             :                                     const std::string &vrf_name,
    1891             :                                     const VmInterface *vm_itf,
    1892             :                                     const Ip4Address &grp_addr) {
    1893             : 
    1894           0 :     MulticastGroupObjectList objList;
    1895             : 
    1896           0 :     if (!FindVmToMulticastObjMap(vm_itf->GetUuid(), objList)) {
    1897           0 :         return;
    1898             :     }
    1899             : 
    1900           0 :     MCTRACE(LogSG, "VMI delete notify ", vrf_name, Ip4Address().to_string(),
    1901             :                             grp_addr.to_string(), 0);
    1902             : 
    1903           0 :     std::set<MulticastGroupObject *> sg_to_delete;
    1904           0 :     boost::system::error_code ec;
    1905             :     Ip4Address bcast_addr =
    1906           0 :                     IpAddress::from_string("255.255.255.255", ec).to_v4();
    1907           0 :     for(std::set<MulticastGroupObject *>::iterator sg_it = objList.begin();
    1908           0 :         sg_it != objList.end(); sg_it++) {
    1909             : 
    1910           0 :         if ((*sg_it)->vrf_name() != vrf_name) {
    1911             : 
    1912           0 :             continue;
    1913             :         }
    1914             : 
    1915           0 :         if ((grp_addr.is_unspecified() &&
    1916           0 :             (*sg_it)->GetGroupAddress() == bcast_addr)) {
    1917             : 
    1918           0 :             continue;
    1919             :         }
    1920             : 
    1921           0 :         if ((!grp_addr.is_unspecified() &&
    1922           0 :             (*sg_it)->GetGroupAddress() != grp_addr)) {
    1923             : 
    1924           0 :             continue;
    1925             :         }
    1926             : 
    1927           0 :         boost::uuids::uuid vm_itf_uuid = vm_itf->GetUuid();
    1928           0 :         HandleRouteChangeAndMulticastObject((*sg_it), vm_itf_uuid);
    1929             : 
    1930           0 :         sg_to_delete.insert(*sg_it);
    1931             :     }
    1932             : 
    1933           0 :     for(std::set<MulticastGroupObject *>::iterator sg_it = sg_to_delete.begin();
    1934           0 :         sg_it != sg_to_delete.end(); sg_it++) {
    1935           0 :         DeleteVmToMulticastObjMap(vm_itf->GetUuid(), *sg_it);
    1936             :     }
    1937             : 
    1938           0 :     MCTRACE(LogSG, "VMI delete notify done ", vrf_name,
    1939             :                             Ip4Address().to_string(),
    1940             :                             grp_addr.to_string(), 0);
    1941             : 
    1942           0 :     return;
    1943           0 : }
    1944             : 
    1945             : // Delete VM-Interface from all the learnt <S,G>s belonging
    1946             : // to a particular group
    1947             : // API used in case of MVPN
    1948           0 : void MulticastHandler::DeleteVmInterfaceFromSourceGroup(
    1949             :                                     const std::string &mc_vrf_name,
    1950             :                                     const VmInterface *vm_itf,
    1951             :                                     const Ip4Address &grp_addr) {
    1952             : 
    1953           0 :     DeleteVmInterfaceFromVrfSourceGroup(vm_itf->vrf()->GetName(), vm_itf,
    1954             :                                     grp_addr);
    1955           0 :     DeleteVmInterfaceFromVrfSourceGroup(mc_vrf_name, vm_itf, grp_addr);
    1956           0 : }
    1957             : 
    1958             : // Delete VM-Interface from all the learnt <S,G>s
    1959             : // API used in case of MVPN
    1960           0 : void MulticastHandler::DeleteVmInterfaceFromSourceGroup(
    1961             :                                     const std::string &mc_vrf_name,
    1962             :                                     const std::string &vm_vrf_name,
    1963             :                                     const VmInterface *vm_itf) {
    1964             : 
    1965           0 :     DeleteVmInterfaceFromVrfSourceGroup(vm_vrf_name, vm_itf);
    1966           0 :     DeleteVmInterfaceFromVrfSourceGroup(mc_vrf_name, vm_itf);
    1967           0 : }
    1968             : 
    1969             : // Flags set to for use in SMET routes. Flags sent in XMPP message
    1970             : // to the control BGP
    1971           0 : void MulticastHandler::SetEvpnMulticastSGFlags(
    1972             :                                     const std::string &vrf_name,
    1973             :                                     const Ip4Address &src_addr,
    1974             :                                     const Ip4Address &grp_addr,
    1975             :                                     uint32_t flags) {
    1976             : 
    1977           0 :     MulticastGroupObject *sg_object = NULL;
    1978           0 :     sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1979             : 
    1980           0 :     if (sg_object) sg_object->set_evpn_igmp_flags(flags);
    1981             : 
    1982           0 :     return;
    1983             : }
    1984             : 
    1985             : // Flags Get API for use of flags in SMET routes. Flags sent in XMPP
    1986             : // message to the control BGP
    1987           0 : uint32_t MulticastHandler::GetEvpnMulticastSGFlags(
    1988             :                                     const std::string &vrf_name,
    1989             :                                     const Ip4Address &src_addr,
    1990             :                                     const Ip4Address &grp_addr) {
    1991             : 
    1992           0 :     MulticastGroupObject *sg_object = NULL;
    1993           0 :     sg_object = FindGroupObject(vrf_name, src_addr, grp_addr);
    1994             : 
    1995           0 :     return (sg_object ? sg_object->evpn_igmp_flags() : 0);
    1996             : }
    1997             : 
    1998           0 : MulticastTEWalker::MulticastTEWalker(const std::string &name, Agent *agent) :
    1999           0 :     AgentRouteWalker(name, agent) {
    2000           0 : }
    2001             : 
    2002           0 : MulticastTEWalker::~MulticastTEWalker() {
    2003           0 : }
    2004             : 
    2005           0 : bool MulticastTEWalker::RouteWalkNotify(DBTablePartBase *partition,
    2006             :                                         DBEntryBase *e) {
    2007             :     Agent *agent = (static_cast<AgentRouteTable *>
    2008           0 :                     (partition->parent()))->agent();
    2009           0 :     BridgeRouteEntry *bridge_route = static_cast<BridgeRouteEntry *>(e);
    2010           0 :     bool notify = false;
    2011           0 :     for(Route::PathList::iterator it = bridge_route->GetPathList().begin();
    2012           0 :         it != bridge_route->GetPathList().end();it++) {
    2013           0 :         MulticastRoutePath *path = dynamic_cast<MulticastRoutePath *>
    2014           0 :             (it.operator->());
    2015           0 :         if (!path)
    2016           0 :             continue;
    2017             : 
    2018           0 :         const Peer *peer = path->peer();
    2019           0 :         if (!peer)
    2020           0 :             continue;
    2021             : 
    2022           0 :         if (peer->GetType() != Peer::BGP_PEER)
    2023           0 :             continue;
    2024             : 
    2025           0 :         const CompositeNH *cnh = dynamic_cast<const CompositeNH *>
    2026           0 :             (path->nexthop());
    2027           0 :         if (!cnh)
    2028           0 :             continue;
    2029             : 
    2030           0 :         if (cnh->composite_nh_type() != Composite::EVPN)
    2031           0 :             continue;
    2032           0 :         NextHop *nh = path->UpdateNH(agent,
    2033           0 :                                      static_cast<CompositeNH *>(path->original_nh().get()),
    2034           0 :                                      agent->oper_db()->tsn_elector());
    2035           0 :         if (path->ChangeNH(agent, nh) && bridge_route->ReComputePathAdd(path))
    2036           0 :             notify = true;
    2037             :     }
    2038           0 :     if (notify)
    2039           0 :         partition->Notify(bridge_route);
    2040           0 :     return true;
    2041             : }

Generated by: LCOV version 1.14