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: 312 981 31.8 %
Date: 2026-06-08 02:02:55 Functions: 29 67 43.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14