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