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 2 : void MulticastHandler::Register() {
51 2 : vn_listener_id_ = agent_->vn_table()->Register(
52 : boost::bind(&MulticastHandler::ModifyVN, this, _1, _2));
53 2 : vrf_listener_id_ = agent_->vrf_table()->Register(
54 : boost::bind(&MulticastHandler::ModifyVRF, this, _1, _2));
55 2 : interface_listener_id_ = agent_->interface_table()->Register(
56 : boost::bind(&MulticastHandler::ModifyVmInterface, this, _1, _2));
57 2 : bridge_domain_id_ = agent_->bridge_domain_table()->Register(
58 : boost::bind(&MulticastHandler::AddBridgeDomain, this, _1, _2));
59 2 : physical_device_listener_id_ = DBTable::kInvalidId;
60 2 : 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 2 : GetMulticastObjList().clear();
69 2 : }
70 :
71 2 : void MulticastHandler::Terminate() {
72 2 : agent_->vn_table()->Unregister(vn_listener_id_);
73 2 : agent_->interface_table()->Unregister(interface_listener_id_);
74 2 : agent_->vrf_table()->Unregister(vrf_listener_id_);
75 2 : agent_->bridge_domain_table()->Unregister(bridge_domain_id_);
76 2 : if (physical_device_listener_id_ != DBTable::kInvalidId) {
77 0 : agent_->physical_device_table()->
78 0 : Unregister(physical_device_listener_id_);
79 : }
80 2 : 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 2 : }
86 :
87 17 : 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 17 : if (obj->pbb_vrf() && obj->dependent_mg() == NULL) {
96 17 : return;
97 : }
98 :
99 17 : boost::system::error_code ec;
100 17 : 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 17 : GetInterfaceComponentNHKeyList(obj, InterfaceNHFlags::BRIDGE);
104 17 : if (component_nh_key_list.size() == 0)
105 17 : 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 17 : }
122 :
123 : /*
124 : * Route address 255.255.255.255 deletion from last VM in VN del
125 : */
126 18 : void MulticastHandler::DeleteBroadcast(const Peer *peer,
127 : const std::string &vrf_name,
128 : uint32_t ethernet_tag,
129 : COMPOSITETYPE type)
130 : {
131 18 : boost::system::error_code ec;
132 18 : MCTRACE(Log, "delete bcast route ", vrf_name, "255.255.255.255", 0);
133 18 : BridgeAgentRouteTable::DeleteBroadcastReq(peer, vrf_name, ethernet_tag,
134 : type);
135 18 : ComponentNHKeyList component_nh_key_list; //dummy list
136 18 : }
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 61 : void MulticastHandler::HandleVnParametersChange(DBTablePartBase *partition,
161 : DBEntryBase *e) {
162 61 : VnEntry *vn = static_cast<VnEntry *>(e);
163 61 : bool deleted = false;
164 :
165 : //Extract paramters from VN.
166 61 : const VrfEntry *vrf = vn->GetVrf();
167 61 : uint32_t vn_vxlan_id = vn->GetVxLanId();
168 :
169 : MulticastDBState *state = static_cast<MulticastDBState *>
170 61 : (vn->GetState(partition->parent(), vn_listener_id_));
171 :
172 61 : deleted = vn->IsDeleted() || !(vrf);
173 : //Extract old parameters from state
174 61 : uint32_t old_vxlan_id = state ? state->vxlan_id_ : 0;
175 :
176 61 : boost::system::error_code ec;
177 61 : Ip4Address broadcast = IpAddress::from_string("255.255.255.255",
178 61 : ec).to_v4();
179 : //Add operation
180 61 : if (!deleted) {
181 : MulticastGroupObject *all_broadcast =
182 17 : FindFloodGroupObject(vn->GetVrf()->GetName());
183 :
184 17 : if (!state) {
185 17 : state = new MulticastDBState(vn->GetVrf()->GetName(),
186 17 : vn_vxlan_id);
187 17 : vn->SetState(partition->parent(), vn_listener_id_, state);
188 : //Also create multicast object
189 17 : if (all_broadcast == NULL) {
190 17 : all_broadcast = CreateMulticastGroupObject(state->vrf_name_,
191 34 : vn->GetName(), Ip4Address(), broadcast,
192 : state->vxlan_id_);
193 : }
194 17 : 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 17 : ComponentNHKeyList component_nh_key_list;
204 : AgentRouteData *data =
205 34 : BridgeAgentRouteTable::BuildNonBgpPeerData(state->vrf_name_,
206 : vn->GetName(),
207 : 0,
208 17 : state->vxlan_id_,
209 : TunnelType::VxlanType(),
210 : Composite::L2COMP,
211 : component_nh_key_list,
212 17 : all_broadcast->pbb_vrf(),
213 : all_broadcast->
214 17 : learning_enabled());
215 17 : BridgeAgentRouteTable::AddBridgeBroadcastRoute(agent_->local_peer(),
216 17 : state->vrf_name_,
217 : state->vxlan_id_,
218 : data);
219 17 : Ip4Address broadcast = IpAddress::from_string("255.255.255.255",
220 17 : ec).to_v4();
221 17 : AddL2BroadcastRoute(all_broadcast, state->vrf_name_, vn->GetName(),
222 : broadcast, MplsTable::kInvalidLabel,
223 17 : state->vxlan_id_, 0);
224 17 : }
225 :
226 : //Delete or withdraw old vxlan id
227 61 : if (deleted) {
228 44 : if (!state)
229 27 : return;
230 :
231 : MulticastGroupObject *all_broadcast =
232 17 : FindFloodGroupObject(state->vrf_name_);
233 17 : if (all_broadcast) {
234 17 : all_broadcast->reset_vn();
235 : }
236 :
237 17 : DeleteMulticastObject(state->vrf_name_, Ip4Address(), broadcast);
238 17 : BridgeAgentRouteTable::DeleteBroadcastReq(agent_->local_peer(),
239 17 : state->vrf_name_,
240 : old_vxlan_id,
241 : Composite::L2COMP);
242 :
243 17 : vn->ClearState(partition->parent(), vn_listener_id_);
244 17 : delete state;
245 : }
246 : }
247 :
248 : /* Regsitered call for VN */
249 61 : void MulticastHandler::ModifyVN(DBTablePartBase *partition, DBEntryBase *e)
250 : {
251 61 : const VnEntry *vn = static_cast<const VnEntry *>(e);
252 :
253 61 : HandleIpam(vn);
254 61 : HandleVnParametersChange(partition, e);
255 61 : }
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 267 : void MulticastHandler::ModifyVRF(DBTablePartBase *partition, DBEntryBase *e) {
339 :
340 267 : if (!agent_->params()->mvpn_ipv4_enable()) {
341 267 : 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 35 : bool MulticastGroupObject::CanBeDeleted() const {
476 55 : if ((local_olist_.size() == 0) && (vn_.get() == NULL) &&
477 20 : bridge_domain_.get() == NULL)
478 20 : return true;
479 15 : 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 20 : 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 20 : new MulticastGroupObject(vrf_name, vn_name, grp_addr, src_addr);
501 20 : AddToMulticastObjList(obj);
502 20 : obj->set_vxlan_id(vxlan_id);
503 :
504 20 : boost::system::error_code ec;
505 : Ip4Address bcast_addr =
506 20 : IpAddress::from_string("255.255.255.255", ec).to_v4();
507 20 : if (obj->GetGroupAddress() == bcast_addr) {
508 20 : UpdateReference(obj);
509 : }
510 20 : return obj;
511 : }
512 :
513 61 : void MulticastHandler::HandleIpam(const VnEntry *vn) {
514 61 : const uuid &vn_uuid = vn->GetUuid();
515 61 : const std::vector<VnIpam> &ipam = vn->GetVnIpam();
516 61 : bool delete_ipam = false;
517 61 : std::map<uuid, string>::iterator it;
518 61 : string vrf_name;
519 :
520 102 : if (!(vn->layer3_forwarding()) || vn->IsDeleted() || (ipam.size() == 0) ||
521 41 : (vn->GetVrf() == NULL)) {
522 44 : delete_ipam = true;
523 : }
524 :
525 61 : it = vn_vrf_mapping_.find(vn_uuid);
526 61 : if (it != vn_vrf_mapping_.end()) {
527 17 : vrf_name = it->second;
528 17 : vrf_ipam_mapping_.erase(vrf_name);
529 17 : if (delete_ipam) {
530 17 : vn_vrf_mapping_.erase(vn_uuid);
531 17 : return;
532 : }
533 : } else {
534 44 : if (delete_ipam == false) {
535 17 : vrf_name = vn->GetVrf()->GetName();
536 17 : vn_vrf_mapping_.insert(std::pair<uuid, string>(vn_uuid, vrf_name));
537 : }
538 : }
539 :
540 44 : if (delete_ipam)
541 27 : return;
542 :
543 17 : vrf_ipam_mapping_.insert(std::pair<string, std::vector<VnIpam> >(vrf_name,
544 : ipam));
545 61 : }
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 125 : bool MulticastHandler::FilterVmi(const VmInterface *vm_itf) {
572 125 : if (vm_itf->device_type() == VmInterface::TOR) {
573 : //Ignore TOR VMI, they are not active VMI.
574 6 : return true;
575 : }
576 :
577 119 : if (vm_itf->vmi_type() == VmInterface::VHOST) {
578 2 : return true;
579 : }
580 :
581 117 : if (vm_itf->device_type() == VmInterface::VMI_ON_LR) {
582 0 : return true;
583 : }
584 :
585 117 : if (vm_itf->device_type() == VmInterface::VM_SRIOV) {
586 0 : return true;
587 : }
588 :
589 117 : return false;
590 : }
591 :
592 : /* Registered call for VM */
593 144 : void MulticastHandler::ModifyVmInterface(DBTablePartBase *partition,
594 : DBEntryBase *e)
595 : {
596 144 : Interface *intf = static_cast<Interface *>(e);
597 : VmInterface *vm_itf;
598 :
599 144 : if (intf->type() != Interface::VM_INTERFACE) {
600 19 : return;
601 : }
602 :
603 125 : vm_itf = static_cast<VmInterface *>(intf);
604 125 : if (FilterVmi(vm_itf)) {
605 8 : return;
606 : }
607 :
608 : MulticastIntfDBState *state = static_cast<MulticastIntfDBState *>(
609 117 : vm_itf->GetState(partition->parent(), interface_listener_id_));
610 :
611 167 : if (intf->IsDeleted() || ((vm_itf->l2_active() == false) &&
612 50 : (vm_itf->ipv4_active() == false) &&
613 50 : (vm_itf->ipv6_active() == false))) {
614 78 : if (state) {
615 25 : DeleteVmInterface(vm_itf, state);
616 25 : if (intf->IsDeleted()) {
617 25 : vm_itf->ClearState(partition->parent(), interface_listener_id_);
618 25 : delete state;
619 : }
620 : }
621 78 : return;
622 : }
623 39 : assert(vm_itf->vn() != NULL);
624 :
625 39 : if (state == NULL) {
626 25 : state = new MulticastIntfDBState();
627 25 : vm_itf->SetState(partition->parent(), interface_listener_id_, state);
628 : }
629 :
630 : //Build all the VRF group interface belong to
631 39 : AddVmInterfaceInFloodGroup(vm_itf, state);
632 39 : return;
633 : }
634 :
635 39 : void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_intf,
636 : MulticastIntfDBState *state) {
637 39 : std::set<std::string> new_vrf_list;
638 39 : new_vrf_list.insert(vm_intf->vrf()->GetName());
639 :
640 : //Build all PBB VRF
641 : VmInterface::BridgeDomainEntrySet::const_iterator it =
642 39 : vm_intf->bridge_domain_list().list_.begin();
643 39 : 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 39 : for (std::set<std::string>::const_iterator it = new_vrf_list.begin();
651 78 : it != new_vrf_list.end(); it++) {
652 39 : AddVmInterfaceInFloodGroup(vm_intf, *it);
653 39 : state->vrf_list_.erase(*it);
654 : }
655 :
656 39 : for (std::set<std::string>::const_iterator it = state->vrf_list_.begin();
657 39 : it != state->vrf_list_.end(); it++) {
658 0 : DeleteVmInterface(vm_intf, *it);
659 : }
660 :
661 39 : state->vrf_list_ = new_vrf_list;
662 39 : }
663 :
664 25 : void MulticastHandler::DeleteVmInterface(const VmInterface *intf,
665 : MulticastIntfDBState *state) {
666 25 : for (std::set<std::string>::const_iterator it = state->vrf_list_.begin();
667 50 : it != state->vrf_list_.end(); it++) {
668 25 : DeleteVmInterface(intf, *it);
669 : }
670 25 : }
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 25 : void MulticastHandler::DeleteVmInterface(const VmInterface *intf,
679 : const std::string &vrf_name) {
680 :
681 25 : const VmInterface *vm_itf = static_cast<const VmInterface *>(intf);
682 25 : boost::system::error_code ec;
683 : Ip4Address bcast_addr =
684 25 : IpAddress::from_string("255.255.255.255", ec).to_v4();
685 25 : std::set<MulticastGroupObject *> &obj_list = GetVmToMulticastObjMap(
686 : vm_itf->GetUuid());
687 25 : for (std::set<MulticastGroupObject *>::iterator it = obj_list.begin();
688 25 : it != obj_list.end(); it++) {
689 :
690 50 : if (((*it)->vrf_name() != vrf_name) ||
691 25 : ((*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 25 : if (((*it)->DeleteLocalMember(vm_itf->GetUuid()) == true) &&
701 50 : ((*it)->IsDeleted() == false) &&
702 25 : ((*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 25 : if((*it)->GetLocalListSize() == 0) {
710 18 : 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 18 : DeleteBroadcast(agent_->local_vm_peer(),
714 18 : (*it)->vrf_name_, 0, Composite::L2INTERFACE);
715 : /* delete mcast object */
716 : // TODO : delete only when all creators are gone
717 18 : DeleteMulticastObject((*it)->vrf_name_, Ip4Address(), bcast_addr);
718 : }
719 25 : DeleteVmToMulticastObjMap(vm_itf->GetUuid(), *it);
720 25 : break;
721 : }
722 25 : MCTRACE(Info, "Del vm notify done ", vm_itf->primary_ip_addr().to_string());
723 25 : }
724 :
725 : //Delete multicast object for vrf/S/G
726 35 : void MulticastHandler::DeleteMulticastObject(const std::string &vrf_name,
727 : const Ip4Address &src_addr,
728 : const Ip4Address &grp_addr) {
729 :
730 35 : for (std::set<MulticastGroupObject *>::iterator it =
731 35 : this->GetMulticastObjList().begin();
732 43 : it != this->GetMulticastObjList().end(); it++) {
733 :
734 78 : if (((*it)->vrf_name() == vrf_name) &&
735 78 : ((*it)->GetGroupAddress() == grp_addr) &&
736 35 : ((*it)->GetSourceAddress() == src_addr)) {
737 :
738 35 : if (!((*it)->CanBeDeleted())) {
739 15 : return;
740 : }
741 :
742 20 : 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 20 : 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 20 : delete (*it);
758 20 : this->GetMulticastObjList().erase(it);
759 20 : break;
760 : }
761 : }
762 : }
763 :
764 34 : MulticastGroupObject *MulticastHandler::FindFloodGroupObject(const std::string &vrf_name) {
765 34 : boost::system::error_code ec;
766 34 : Ip4Address broadcast = IpAddress::from_string("255.255.255.255",
767 34 : ec).to_v4();
768 34 : return (FindGroupObject(vrf_name, Ip4Address(), broadcast));
769 : }
770 :
771 : //Helper to find object for VRF/S/G
772 73 : MulticastGroupObject *MulticastHandler::FindGroupObject(
773 : const std::string &vrf_name,
774 : const Ip4Address &sip,
775 : const Ip4Address &dip) {
776 73 : for(std::set<MulticastGroupObject *>::iterator it =
777 73 : this->GetMulticastObjList().begin();
778 85 : it != this->GetMulticastObjList().end(); it++) {
779 118 : if (((*it)->vrf_name() == vrf_name) &&
780 118 : ((*it)->GetGroupAddress() == dip) &&
781 53 : ((*it)->GetSourceAddress() == sip)) {
782 53 : return (*it);
783 : }
784 : }
785 20 : MCTRACE(LogSG, "mcast obj size ", vrf_name, sip.to_string(),
786 : dip.to_string(), this->GetMulticastObjList().size());
787 20 : 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 17 : void MulticastGroupObject::set_vn(const VnEntry *vn) {
805 17 : vn_.reset(vn);
806 17 : }
807 :
808 17 : void MulticastGroupObject::reset_vn() {
809 17 : vn_.reset();
810 17 : }
811 :
812 : ComponentNHKeyList
813 66 : MulticastGroupObject::GetInterfaceComponentNHKeyList(uint8_t interface_flags) {
814 :
815 66 : ComponentNHKeyList component_nh_key_list;
816 66 : for (std::map<uuid, MacAddress>::iterator it = local_olist_.begin();
817 148 : it != local_olist_.end(); it++) {
818 82 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(0, it->first,
819 : interface_flags,
820 82 : it->second));
821 82 : component_nh_key_list.push_back(component_nh_key);
822 82 : }
823 66 : return component_nh_key_list;
824 0 : }
825 :
826 : ComponentNHKeyList
827 66 : MulticastHandler::GetInterfaceComponentNHKeyList(MulticastGroupObject *obj,
828 : uint8_t interface_flags) {
829 :
830 : ComponentNHKeyList component_nh_key_list =
831 66 : obj->GetInterfaceComponentNHKeyList(interface_flags);
832 66 : 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 49 : void MulticastHandler::TriggerLocalRouteChange(MulticastGroupObject *obj,
844 : const Peer *peer) {
845 49 : DBRequest req;
846 49 : ComponentNHKeyList component_nh_key_list;
847 :
848 49 : if (obj->pbb_vrf() && obj->dependent_mg() == NULL) {
849 0 : return;
850 : }
851 :
852 49 : uint8_t intf_flags = InterfaceNHFlags::BRIDGE;
853 49 : Composite::Type comp_type = Composite::L2INTERFACE;
854 49 : uint32_t route_tunnel_bmap = TunnelType::AllType();
855 49 : boost::system::error_code ec;
856 : Ip4Address bcast_addr =
857 49 : IpAddress::from_string("255.255.255.255", ec).to_v4();
858 49 : 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 49 : GetInterfaceComponentNHKeyList(obj, intf_flags);
866 :
867 49 : 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 49 : BridgeAgentRouteTable::BuildNonBgpPeerData(obj->vrf_name(),
875 : obj->GetVnName(), MplsTable::kInvalidLabel,
876 49 : obj->vxlan_id(), route_tunnel_bmap,
877 : comp_type, component_nh_key_list,
878 49 : obj->pbb_vrf(),
879 49 : obj->learning_enabled());
880 :
881 49 : 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 49 : BridgeAgentRouteTable::AddBridgeBroadcastRoute(peer,
909 : obj->vrf_name(),
910 : 0,
911 : data);
912 : }
913 49 : }
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 39 : void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_itf,
1133 : const std::string &vrf_name) {
1134 39 : const uuid intf_uuid = vm_itf->GetUuid();
1135 39 : const VnEntry *vn = vm_itf->vn();
1136 39 : MulticastGroupObject *all_broadcast = NULL;
1137 39 : boost::system::error_code ec;
1138 39 : Ip4Address broadcast = IpAddress::from_string("255.255.255.255",
1139 39 : ec).to_v4();
1140 39 : bool add_route = false;
1141 39 : 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 39 : all_broadcast = this->FindGroupObject(vrf_name, Ip4Address(), broadcast);
1146 39 : 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 39 : if (all_broadcast->AddLocalMember(intf_uuid, vm_itf->vm_mac()) == true) {
1155 39 : TriggerLocalRouteChange(all_broadcast, agent_->local_vm_peer());
1156 39 : AddVmToMulticastObjMap(intf_uuid, all_broadcast);
1157 : }
1158 : //Modify routes
1159 39 : 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 39 : }
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 2 : MulticastHandler::MulticastHandler(Agent *agent) :
1397 2 : agent_(agent),
1398 2 : vn_listener_id_(DBTable::kInvalidId),
1399 2 : interface_listener_id_(DBTable::kInvalidId),
1400 2 : physical_device_listener_id_(DBTable::kInvalidId),
1401 2 : physical_devices_() {
1402 2 : if (agent_->tsn_no_forwarding_enabled()) {
1403 0 : te_walker_.reset(new MulticastTEWalker("MulticastTorElectorWalker", agent));
1404 : }
1405 2 : obj_ = this;
1406 2 : }
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 2 : void MulticastHandler::Shutdown() {
1423 :
1424 2 : boost::system::error_code ec;
1425 2 : Ip4Address bcast_addr = IpAddress::from_string("255.255.255.255",
1426 2 : ec).to_v4();
1427 : //Delete all route mpls and trigger cnh change
1428 2 : for (std::set<MulticastGroupObject *>::iterator it =
1429 4 : 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 2 : }
1471 :
1472 20 : void MulticastHandler::ResyncDependentVrf(MulticastGroupObject *obj) {
1473 : std::set<MulticastGroupObject *>::iterator it =
1474 20 : multicast_obj_list_.begin();
1475 46 : for (; it != multicast_obj_list_.end(); it++) {
1476 : MulticastGroupObject *mg =
1477 26 : static_cast<MulticastGroupObject *>(*it);
1478 26 : 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 20 : }
1487 :
1488 20 : void MulticastHandler::UpdateReference(MulticastGroupObject *obj) {
1489 20 : VrfKey key(obj->vrf_name());
1490 : VrfEntry *vrf =
1491 20 : static_cast<VrfEntry *>(agent_->vrf_table()->FindActiveEntry(&key));
1492 20 : 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 20 : ResyncDependentVrf(obj);
1509 : }
1510 20 : }
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 : }
|