OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_mvpn.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "bgp/bgp_mvpn.h"
6 
7 #include <utility>
8 
9 #include <boost/foreach.hpp>
10 
11 #include "base/task_annotations.h"
15 #include "bgp/bgp_log.h"
16 #include "bgp/bgp_multicast.h"
17 #include "bgp/bgp_server.h"
18 #include "bgp/bgp_update.h"
19 #include "bgp/mvpn/mvpn_table.h"
22 #include "bgp/routing-instance/routing_instance_analytics_types.h"
26 
27 using std::make_pair;
28 using std::ostringstream;
29 using std::pair;
30 using std::string;
31 using std::vector;
32 
33 // A global MVPN state for a given <S.G> within a MvpnProjectManager.
35  sg_(sg), global_ermvpn_tree_rt_(NULL), spmsi_rt_(NULL),
36  source_active_rt_(NULL), states_(states), project_manager_(pm) {
37  refcount_ = 0;
38 }
39 
41  assert(!global_ermvpn_tree_rt_);
42  assert(!spmsi_rt_);
43  assert(!source_active_rt_);
44  assert(spmsi_routes_received_.empty());
45  assert(leafad_routes_attr_received_.empty());
46  MVPN_TRACE(MvpnStateCreate, sg_.source.to_string(), sg_.group.to_string());
47 }
48 
49 const ErmVpnTable *MvpnState::table() const {
50  return project_manager_ ? project_manager_->table() : NULL;
51 }
52 
53 // MvpnProjectManager is deleted when parent ErmVpnTable is deleted.
55 public:
56  explicit DeleteActor(MvpnProjectManager *manager)
57  : LifetimeActor(manager->table_->routing_instance()->server()->
58  lifetime_manager()), manager_(manager) {
59  }
60 
61  virtual ~DeleteActor() {
62  }
63 
64  virtual bool MayDelete() const {
65  CHECK_CONCURRENCY("bgp::Config");
66  return manager_->MayDelete();
67  }
68 
69  virtual void Shutdown() {
70  }
71 
72  virtual void Destroy() {
74  }
75 
76 private:
78 };
79 
80 // Create MvpnProjectManager object and take a lifetime reference to the
81 // parent ErmVpnTable object.
83  : table_(table),
84  listener_id_(DBTable::kInvalidId),
85  table_delete_ref_(this, table->deleter()) {
86  deleter_.reset(new DeleteActor(this));
87 }
88 
90 }
91 
92 // MvpnProjectManager can be deleted only after all <S,G> MvpnState objects
93 // are deleted from the map.
95  BOOST_FOREACH(const MvpnProjectManagerPartition *partition, partitions_) {
96  if (!partition->states().empty()) {
97  MVPN_LOG(MvpnProjectManagerDelete,
98  "MvpnProjectManager::MayDelete() paused due to pending " +
99  integerToString(partition->states().size()) + " MvpnStates");
100  return false;
101  }
102  }
103  return true;
104 }
105 
107  return deleter_.get();
108 }
109 
111  return deleter_.get();
112 }
113 
114 // Create MvpnProjectManagerPartitions and register with the ErmVpnTable to
115 // get route change notifications.
117  if (!table_->server()->mvpn_ipv4_enable())
118  return;
119 
120  AllocPartitions();
121 
123  boost::bind(&MvpnProjectManager::RouteListener, this, _1, _2),
124  "MvpnProjectManager");
125  MVPN_LOG(MvpnProjectManagerCreate, "Initialized MvpnProjectManager");
126 }
127 
129  CHECK_CONCURRENCY("bgp::Config");
132  FreePartitions();
133  MVPN_LOG(MvpnProjectManagerDelete, "Terminated MvpnProjectManager");
134 }
135 
137  for (int part_id = 0; part_id < table_->PartitionCount(); part_id++)
138  partitions_.push_back(new MvpnProjectManagerPartition(this, part_id));
139 }
140 
142  for (size_t part_id = 0; part_id < partitions_.size(); part_id++) {
143  delete partitions_[part_id];
144  }
145  partitions_.clear();
146 }
147 
149  return partitions_[part_id];
150 }
151 
153  int part_id) const {
154  return partitions_[part_id];
155 }
156 
158  deleter_->Delete();
159 }
160 
162  return deleter_->IsDeleted();
163 }
164 
166  MvpnState::SG sg(route->GetPrefix().source(), route->GetPrefix().group());
167  return GetPartition(route->get_table_partition()->index())->GetState(sg);
168 }
169 
171  return static_cast<const MvpnProjectManager *>(this)->GetState(route);
172 }
173 
175  MvpnState::SG sg(route->GetPrefix().source(), route->GetPrefix().group());
176  return GetPartition(route->get_table_partition()->index())->GetState(sg);
177 }
178 
180  MvpnProjectManager *manager, int part_id)
181  : manager_(manager), part_id_(part_id) {
182 }
183 
185  assert(states_.empty());
186 }
187 
189  MvpnStatePtr state(new MvpnState(sg, &states_, manager_));
190  assert(states_.insert(make_pair(sg, state.get())).second);
191  MVPN_TRACE(MvpnStateCreate, sg.source.to_string(), sg.group.to_string());
192  return state;
193 }
194 
196  MvpnStatePtr mvpn_state = GetState(sg);
197  if (mvpn_state)
198  return mvpn_state;
199  mvpn_state = CreateState(sg);
200  assert(mvpn_state);
201  return mvpn_state;
202 }
203 
205  MvpnState::StatesMap::const_iterator iter = states_.find(sg);
206  return iter != states_.end() ? iter->second : NULL;
207 }
208 
210  MvpnState::StatesMap::iterator iter = states_.find(sg);
211  return iter != states_.end() ? iter->second : NULL;
212 }
213 
214 MvpnNeighbor::MvpnNeighbor() : source_as_(0) {
215 }
216 
218  const IpAddress &originator) :
219  rd_(rd), originator_(originator), source_as_(0) {
220 }
221 
223  return rd_;
224 }
225 
226 uint32_t MvpnNeighbor::source_as() const {
227  return source_as_;
228 }
229 
231  return originator_;
232 }
233 
234 bool MvpnNeighbor::operator==(const MvpnNeighbor &rhs) const {
235  return rd_ == rhs.rd_ && originator_ == rhs.originator_ &&
236  source_as_ == rhs.source_as_;
237 }
238 
240  MvpnNeighbor *nbr) const {
241  tbb::reader_writer_lock::scoped_lock_read lock(neighbors_mutex_);
242  NeighborMap::const_iterator iter = neighbors_.find(rd);
243  if (iter != neighbors_.end()) {
244  *nbr = iter->second;
245  return true;
246  }
247  return false;
248 }
249 
251  // Assert that lock cannot be taken now as it must have been taken already.
252  // assert(!neighbors_mutex_.try_lock_read());
253  return neighbors_;
254 }
255 
257  tbb::reader_writer_lock::scoped_lock_read lock(neighbors_mutex_);
258  return neighbors_.size();
259 }
260 
261 MvpnState::SG::SG(const Ip4Address &source, const Ip4Address &group) :
262  source(IpAddress(source)), group(IpAddress(group)) {
263 }
264 
266  source(route->GetPrefix().source()),
267  group(route->GetPrefix().group()) {
268 }
269 
271  source(route->GetPrefix().source()), group(route->GetPrefix().group()) {
272 }
273 
274 MvpnState::SG::SG(const IpAddress &source, const IpAddress &group) :
275  source(source), group(group) {
276 }
277 
278 bool MvpnState::SG::operator<(const SG &other) const {
279  if (source < other.source)
280  return true;
281  if (source > other.source)
282  return false;
283  if (group < other.group)
284  return true;
285  if (group > other.group)
286  return false;
287  return false;
288 }
289 
290 const MvpnState::SG &MvpnState::sg() const {
291  return sg_;
292 }
293 
295  return global_ermvpn_tree_rt_;
296 }
297 
299  return global_ermvpn_tree_rt_;
300 }
301 
303  return spmsi_rt_;
304 }
305 
307  return spmsi_rt_;
308 }
309 
311  return spmsi_routes_received_;
312 }
313 
315  return spmsi_routes_received_;
316 }
317 
320 }
321 
324 }
325 
328 }
329 
332 }
333 
335  return source_active_rt_;
336 }
337 
339  return source_active_rt_;
340 }
341 
344 }
345 
346 MvpnDBState::MvpnDBState(MvpnStatePtr state) : state_(state) , route_(NULL) {
347 }
348 
350  set_state(NULL);
351 }
352 
354  return state_;
355 }
356 
358  return route_;
359 }
360 
362  route_ = route;
363 }
364 
366  state_ = state;
367 }
368 
370 public:
371  explicit DeleteActor(MvpnManager *manager)
372  : LifetimeActor(manager->table_->routing_instance()->server()->
373  lifetime_manager()), manager_(manager) {
374  }
375  virtual ~DeleteActor() {
376  }
377 
378  virtual bool MayDelete() const {
379  CHECK_CONCURRENCY("bgp::Config");
380  return manager_->MayDelete();
381  }
382 
383  virtual void Shutdown() {
384  if (manager_->table()->IsDeleted())
385  return;
387  }
388 
389  virtual void Destroy() {
391  }
392 
393 private:
395 };
396 
398  : table_(table),
399  ermvpn_table_(ermvpn_table),
400  listener_id_(DBTable::kInvalidId),
401  identifier_listener_id_(-1),
402  table_delete_ref_(this, table->deleter()),
403  ermvpn_table_delete_ref_(this, ermvpn_table->deleter()) {
404  deleter_.reset(new DeleteActor(this));
405  db_states_count_ = 0;
406 }
407 
409 }
410 
412  return table_;
413 }
414 
416  return table_;
417 }
418 
420  return listener_id_;
421 }
422 
423 bool MvpnManager::deleted() const {
424  return deleter_->IsDeleted();
425 }
426 
428  return deleter_.get();
429 }
430 
432  CHECK_CONCURRENCY("bgp::Config");
433 
434  // Delete locally originated type-1 route.
435  MvpnRoute *type1_route = table_->FindType1ADRoute();
436  if (type1_route) {
437  BgpPath *path = type1_route->FindPath(BgpPath::Local, 0);
438  if (path)
439  type1_route->DeletePath(path);
440  type1_route->NotifyOrDelete();
441  }
442 
443  if (identifier_listener_id_ != -1) {
447  }
450  FreePartitions();
451  MVPN_LOG(MvpnManagerDelete, "Terminated MvpnManager");
452 }
453 
455  deleter_->Delete();
456 }
457 
459  for (int part_id = 0; part_id < table_->PartitionCount(); part_id++)
460  partitions_.push_back(new MvpnManagerPartition(this, part_id));
461 }
462 
464  for (size_t part_id = 0; part_id < partitions_.size(); part_id++) {
465  delete partitions_[part_id];
466  }
467  partitions_.clear();
468 }
469 
470 // MvpnManager can be deleted only after all associated DB States are cleared.
472  if (!db_states_count_)
473  return true;
474  MVPN_LOG(MvpnManagerDelete,
475  "MvpnManager::MayDelete() paused due to pending " +
476  integerToString(db_states_count_) + " MvpnDBStates");
477  return false;
478 }
479 
480 // Set DB State and update count.
481 void MvpnManager::SetDBState(MvpnRoute *route, MvpnDBState *mvpn_dbstate) {
482  route->SetState(table_, listener_id_, mvpn_dbstate);
484 }
485 
486 // Create DB State and update count. If there is no DB State associated in the
487 // table, resume table deletion if the deletion was pending.
489  route->ClearState(table_, listener_id_);
490  assert(db_states_count_);
492 
493  // Retry deletion now as there is no more attached db state in the table.
494  if (!db_states_count_ && deleter_->IsDeleted())
495  deleter_->RetryDelete();
496 }
497 
499  return manager_->table();
500 }
501 
503  return manager_->listener_id();
504 }
505 
507  : manager_(manager), part_id_(part_id) {
508 }
509 
511 }
512 
515  MvpnProjectManager *project_manager = manager_->GetProjectManager();
516  return project_manager ? project_manager->GetPartition(part_id_) : NULL;
517 }
518 
521  MvpnProjectManager *project_manager = manager_->GetProjectManager();
522  return project_manager ? project_manager->GetPartition(part_id_) : NULL;
523 }
524 
526  return table_->GetProjectManager();
527 }
528 
530  return listener_id_;
531 }
532 
534  return manager_->listener_id();
535 }
536 
538  MvpnProjectManagerPartition *project_manager_partition =
540  assert(project_manager_partition);
542  rt->GetPrefix().groupIpAddress());
543  return project_manager_partition->LocateState(sg);
544 }
545 
547  const MvpnProjectManagerPartition *project_manager_partition =
549  if (!project_manager_partition)
550  return NULL;
552  rt->GetPrefix().groupIpAddress());
553  return project_manager_partition->GetState(sg);
554 }
555 
557  return static_cast<const MvpnManagerPartition *>(this)->GetState(rt);
558 }
559 
561  return table_;
562 }
563 
565  return table_;
566 }
567 
569  return manager_->table();
570 }
571 
573  return manager_->table();
574 }
575 
577  const Ip4Address &source, const Ip4Address &group) {
578  if (table()->tree_manager())
579  table()->tree_manager()->NotifyForestNode(part_id_, source, group);
580 }
581 
583  const Ip4Address &source, const Ip4Address &group) {
585  if (pm)
586  pm->NotifyForestNode(source, group);
587 }
588 
590  uint32_t *label, Ip4Address *address, vector<string> *enc) const {
591  if (!table()->tree_manager())
592  return false;
593  return table()->tree_manager()->GetForestNodePMSI(rt, label, address, enc);
594 }
595 
597  Ip4Address *address, vector<string> *encap) const {
599  return pm ? pm->GetForestNodePMSI(rt, label, address, encap) : false;
600 }
601 
603 
604 // Initialize MvpnManager by allcating one MvpnManagerPartition for each DB
605 // partition, and register a route listener for the MvpnTable.
607  if (!table_->server()->mvpn_ipv4_enable())
608  return;
609 
610  assert(!table_->IsMaster());
611  AllocPartitions();
612 
614  boost::bind(&MvpnManager::RouteListener, this, _1, _2),
615  "MvpnManager");
616 
621 
622  MVPN_LOG(MvpnManagerCreate, "Initialized MvpnManager");
623 }
624 
625 void MvpnManager::ReOriginateType1Route(const Ip4Address &old_identifier) {
626  // Check if a path is already origianted. If so, delete it.
627  MvpnRoute *route = table_->FindType1ADRoute(old_identifier);
628  if (route) {
629  BgpPath *path = route->FindPath(BgpPath::Local, 0);
630  if (path) {
631  route->DeletePath(path);
632  route->NotifyOrDelete();
633  }
634  }
636 }
637 
639  // Originate Type1 Intra AS Auto-Discovery path.
640  BgpServer *server = table_->server();
641 
642  // Check for the presence of valid identifier.
643  if (!table_->server()->bgp_identifier())
644  return;
645  MvpnRoute *route = table_->LocateType1ADRoute();
646  BgpAttrSpec attr_spec;
647  BgpAttrNextHop nexthop(server->bgp_identifier());
648  attr_spec.push_back(&nexthop);
649  BgpAttrPtr attr = server->attr_db()->Locate(attr_spec);
650  BgpPath *path = new BgpPath(NULL, 0, BgpPath::Local, attr, 0, 0, 0);
651  route->InsertPath(path);
652  route->Notify();
653 
654  // TODO(Ananth) Originate Type2 Inter AS Auto-Discovery Route.
655 }
656 
657 // MvpnTable route listener callback function.
658 //
659 // Process changes (create/update/delete) to all different types of MvpnRoute.
661  CHECK_CONCURRENCY("db::DBTable");
662 
663  MvpnRoute *route = dynamic_cast<MvpnRoute *>(db_entry);
664  assert(route);
665 
666  MvpnManagerPartition *partition = partitions_[tpart->index()];
667 
668  // Process Type1 Intra-AS AD route.
669  if (route->GetPrefix().type() == MvpnPrefix::IntraASPMSIADRoute) {
670  ProcessType1ADRoute(route);
671  return;
672  }
673 
674  // TODO(Ananth) Inter-AS Multiast Site AD.
675 
676  // Process Type3 S-PMSI route.
677  if (route->GetPrefix().type() == MvpnPrefix::SPMSIADRoute) {
678  partition->ProcessType3SPMSIRoute(route);
679  return;
680  }
681 
682  // Process Type7 C-Join route.
683  if (route->GetPrefix().type() == MvpnPrefix::SourceTreeJoinRoute) {
684  partition->ProcessType7SourceTreeJoinRoute(route);
685  return;
686  }
687 
688  // Process Type5 Source Active route.
689  if (route->GetPrefix().type() == MvpnPrefix::SourceActiveADRoute) {
690  partition->ProcessType5SourceActiveRoute(route);
691  return;
692  }
693 
694  // Process Type4 LeafAD route.
695  if (route->GetPrefix().type() == MvpnPrefix::LeafADRoute) {
696  partition->ProcessType4LeafADRoute(route);
697  return;
698  }
699 }
700 
701 // Update MVPN neighbor list with create/delete/update of auto-discovery routes.
702 //
703 // Protect access to neighbors_ map with a mutex as the same be 'read' off other
704 // DB tasks in parallel. (Type-1 and Type-2 do not carrry any <S,G> information)
707 
708  // Check if an entry is already present.
709  MvpnNeighbor old_neighbor;
710  bool found = FindNeighbor(rd, &old_neighbor);
711 
712  if (!route->IsUsable()) {
713  if (!found)
714  return;
715  tbb::reader_writer_lock::scoped_lock lock(neighbors_mutex_);
716  MVPN_LOG(MvpnNeighborDelete, old_neighbor.rd().ToString(),
717  old_neighbor.originator().to_string(),
718  old_neighbor.source_as());
719  neighbors_.erase(rd);
720  return;
721  }
722 
723  // Ignore primary paths.
724  if (!route->BestPath()->IsReplicated())
725  return;
726 
727  MvpnNeighbor neighbor(route->GetPrefix().route_distinguisher(),
728  route->GetPrefix().originator());
729 
730  // Ignore if there is no change.
731  if (found && old_neighbor == neighbor)
732  return;
733 
734  tbb::reader_writer_lock::scoped_lock lock(neighbors_mutex_);
735  if (found)
736  neighbors_.erase(rd);
737  neighbors_.insert(make_pair(rd, neighbor));
738  MVPN_LOG(MvpnNeighborCreate, neighbor.rd().ToString(),
739  neighbor.originator().to_string(), neighbor.source_as());
740 }
741 
742 // Check whether an ErmVpnRoute is locally originated GlobalTreeRoute.
744  ErmVpnRoute *ermvpn_route) const {
745  if (!ermvpn_route || !ermvpn_route->IsUsable())
746  return NULL;
747  if (!table()->tree_manager())
748  return false;
750  ermvpn_route->GetPrefix().source(), ermvpn_route->GetPrefix().group());
751  return (global_rt && global_rt == ermvpn_route);
752 }
753 
754 // ErmVpnTable route listener callback function.
755 //
756 // Process changes (create/update/delete) to GlobalErmVpnRoute in vrf.ermvpn.0
758  DBEntryBase *db_entry) {
759  CHECK_CONCURRENCY("db::DBTable");
760  MvpnProjectManagerPartition *partition = GetPartition(tpart->index());
761  partition->RouteListener(db_entry);
762 }
763 
764 // Process changes to ErmVpnRoutes. We only care about changes to routes of
765 // type GlobalTreeRoute.
767  ErmVpnRoute *ermvpn_route = dynamic_cast<ErmVpnRoute *>(db_entry);
768  assert(ermvpn_route);
769 
770  // We only care about global tree routes for mvpn stitching.
771  if (ermvpn_route->GetPrefix().type() != ErmVpnPrefix::GlobalTreeRoute)
772  return;
773 
774  MvpnDBState *mvpn_dbstate = dynamic_cast<MvpnDBState *>(
775  ermvpn_route->GetState(table(), listener_id()));
776 
777  // Handle GlobalTreeRoute route deletion.
778  if (!IsUsableGlobalTreeRootRoute(ermvpn_route)) {
779  // Ignore if there is no DB State associated with route.
780  if (!mvpn_dbstate)
781  return;
782  MvpnStatePtr mvpn_state = mvpn_dbstate->state();
783  mvpn_state->set_global_ermvpn_tree_rt(NULL);
784 
785  // Notify all received Type3 spmsi routes for PMSI re-computation.
786  // Since usable global ermvpn is no longer available, any advertised
787  // type-4 lead-ad routes must now be withdrawn.
788  BOOST_FOREACH(MvpnRoute *route, mvpn_state->spmsi_routes_received()) {
789  route->Notify();
790  }
791  ermvpn_route->ClearState(table(), listener_id());
792  MVPN_ERMVPN_RT_LOG(ermvpn_route,
793  "Processed MVPN GlobalErmVpnRoute deletion");
794  delete mvpn_dbstate;
795  return;
796  }
797 
798  // Set DB State in the route if not already done so before.
799  MvpnStatePtr mvpn_state;
800  if (!mvpn_dbstate) {
801  MvpnState::SG sg(ermvpn_route);
802  mvpn_state = LocateState(sg);
803  mvpn_dbstate = new MvpnDBState(mvpn_state);
804  ermvpn_route->SetState(table(), listener_id(), mvpn_dbstate);
805  } else {
806  mvpn_state = mvpn_dbstate->state();
807  }
808 
809  // Note down current usable ermvpn route for stitching to mvpn.
810  mvpn_dbstate->state()->set_global_ermvpn_tree_rt(ermvpn_route);
811 
812  // Notify all originated Type3 spmsi routes for PMSI re-computation.
813  BOOST_FOREACH(MvpnRoute *route, mvpn_state->spmsi_routes_received()) {
814  route->Notify();
815  }
816 
817  MVPN_ERMVPN_RT_LOG(ermvpn_route,
818  "Processed MVPN GlobalErmVpnRoute creation");
819 }
820 
821 // Process change to MVPN Type-5 SourceActive route.
823  MvpnDBState *mvpn_dbstate = dynamic_cast<MvpnDBState *>(rt->GetState(
824  table(), listener_id()));
825 
826  // Process route change as delete if ProjectManager is not set.
827  bool is_usable = rt->IsUsable() && table()->IsProjectManagerUsable();
828  if (!is_usable) {
829  if (!mvpn_dbstate)
830  return;
831 
832  // Delete any associated type-3 s-pmsi route.
833  MvpnRoute *spmsi_rt =
834  mvpn_dbstate->state() ? mvpn_dbstate->state()->spmsi_rt() : NULL;
835  if (spmsi_rt && spmsi_rt->IsUsable()) {
836  BgpPath *path = spmsi_rt->FindPath(BgpPath::Local, 0);
837  if (path)
838  spmsi_rt->DeletePath(path);
839  }
840 
841  mvpn_dbstate->set_route(NULL);
842  mvpn_dbstate->state()->set_source_active_rt(NULL);
843  mvpn_dbstate->state()->set_spmsi_rt(NULL);
844  if (spmsi_rt)
845  spmsi_rt->NotifyOrDelete();
846  manager_->ClearDBState(rt);
847  MVPN_RT_LOG(rt, "Processed MVPN Source Active route deletion");
848  delete mvpn_dbstate;
849  return;
850  }
851 
852  const BgpPath *path = rt->BestPath();
853  // Here in the sender side, we only care about changes to the primary path.
854  if (path->IsReplicated())
855  return;
856 
857  MvpnStatePtr state = LocateState(rt);
858  state->set_source_active_rt(rt);
859 
860  // Set DB State if not already done so.
861  if (!mvpn_dbstate) {
862  mvpn_dbstate = new MvpnDBState(state);
863  manager_->SetDBState(rt, mvpn_dbstate);
864  }
865 
866  // Check if there is any receiver interested. If not, do not originate
867  // type-3 spmsi route. Also, we originate Type3 S-PMSI route only if there
868  // is an imported secondary path for the join route (i.e when the join
869  // route reached the sender)
870  const MvpnRoute *join_rt = table()->FindType7SourceTreeJoinRoute(rt);
871  if (!join_rt || !join_rt->IsUsable() ||
872  !join_rt->BestPath()->IsReplicated()) {
873  // Remove any type-3 spmsi path originated before.
874  MvpnRoute *spmsi_rt = mvpn_dbstate->route();
875  if (spmsi_rt) {
876  assert(!state->spmsi_rt() || spmsi_rt == state->spmsi_rt());
877  state->set_spmsi_rt(NULL);
878  mvpn_dbstate->set_route(NULL);
879  BgpPath *path = spmsi_rt->FindPath(BgpPath::Local, 0);
880  if (path) {
881  MVPN_RT_LOG(spmsi_rt, "Deleted already originated SPMSI path");
882  spmsi_rt->DeletePath(path);
883  spmsi_rt->NotifyOrDelete();
884  }
885  }
886  return;
887  }
888 
889  // Originate Type-3 S-PMSI route to send towards the receivers.
890  MvpnRoute *spmsi_rt = table()->LocateType3SPMSIRoute(join_rt);
891  assert(spmsi_rt);
892  state->set_spmsi_rt(spmsi_rt);
893  if (!mvpn_dbstate->route()) {
894  mvpn_dbstate->set_route(spmsi_rt);
895  } else {
896  assert(spmsi_rt == mvpn_dbstate->route());
897  BgpPath *path = spmsi_rt->FindPath(BgpPath::Local, 0);
898  assert(path);
899 
900  // Ignore if there is no change in the attributes.
901  if (path->GetAttr() == rt->BestPath()->GetAttr())
902  return;
903  spmsi_rt->DeletePath(path);
904  }
905 
906  PmsiTunnelSpec pmsi_spec;
908  BgpAttrDB *attr_db = table()->server()->attr_db();
909  BgpAttrPtr new_attrp = attr_db->ReplacePmsiTunnelAndLocate(
910  rt->BestPath()->GetAttr(), &pmsi_spec);
911 
912  // Insert new path and notify.
913  BgpPath *new_path = new BgpPath(NULL, 0, BgpPath::Local,
914  new_attrp, 0, 0, 0);
915  spmsi_rt->InsertPath(new_path);
916  spmsi_rt->Notify();
917  MVPN_RT_LOG(rt, "Processed MVPN Source Active route creation");
918 }
919 
921  MvpnDBState *mvpn_dbstate = dynamic_cast<MvpnDBState *>(
922  join_rt->GetState(table(), listener_id()));
923 
924  // Process route change as delete if ProjectManager is not set.
925  bool is_usable = join_rt->IsUsable() && table()->IsProjectManagerUsable();
926  if (!is_usable) {
927  if (!mvpn_dbstate)
928  return;
929 
930  // Notify associatd source-active route so that any s-pmsi route if
931  // originated before can be withdrawn as there is no more active join
932  // route (receiver) for this <S,G>.
933  if (mvpn_dbstate->state()->source_active_rt())
934  mvpn_dbstate->state()->source_active_rt()->Notify();
935  manager_->ClearDBState(join_rt);
936  MVPN_RT_LOG(join_rt, "Processed Type 7 Join route deletion");
937  delete mvpn_dbstate;
938  return;
939  }
940 
941  // We care only for imported secondary type-7 joins (at the sender).
942  if (!join_rt->BestPath()->IsReplicated())
943  return;
944 
945  MvpnStatePtr state = LocateState(join_rt);
946  if (!mvpn_dbstate) {
947  mvpn_dbstate = new MvpnDBState(state);
948  manager_->SetDBState(join_rt, mvpn_dbstate);
949  }
950 
951  // A join has been received or updated at the sender. Re-evaluate the
952  // type5 source active, if one such route is present.
953  if (state->source_active_rt()) {
954  state->source_active_rt()->Notify();
955  MVPN_RT_LOG(join_rt, "Processed Type 7 Join route creation and "
956  "notified Source Active route");
957  } else {
958  MVPN_RT_LOG(join_rt, "Processed Type 7 Join route creation");
959  }
960 }
961 
963  MvpnDBState *mvpn_dbstate = dynamic_cast<MvpnDBState *>(
964  leaf_ad->GetState(table(), listener_id()));
965  // Process route change as delete if ProjectManager is not set.
966  bool is_usable = leaf_ad->IsUsable() && table()->IsProjectManagerUsable();
967  if (!is_usable) {
968  if (!mvpn_dbstate)
969  return;
970  assert(mvpn_dbstate->state()->leafad_routes_attr_received().
971  erase(leaf_ad));
972  MvpnRoute *sa_active_rt = mvpn_dbstate->state()->source_active_rt();
973 
974  // Re-evaluate type5 route as secondary type4 leafad route is deleted.
975  // olist needs to be updated and sent to the sender route agent.
976  if (sa_active_rt && sa_active_rt->IsUsable()) {
977  sa_active_rt->Notify();
978  MVPN_RT_LOG(leaf_ad, "Processed Type 4 LeafAD route deletion"
979  " and notified type5 source active route");
980  } else {
981  MVPN_RT_LOG(leaf_ad, "Processed Type 4 LeafAD route deletion");
982  }
983  manager_->ClearDBState(leaf_ad);
984  delete mvpn_dbstate;
985  return;
986  }
987 
988  const BgpPath *path = leaf_ad->BestPath();
989  if (!path->IsReplicated())
990  return;
991 
992  // Secondary leaft-ad path has been imported.
993  MvpnStatePtr state = LocateState(leaf_ad);
994  if (!mvpn_dbstate) {
995  mvpn_dbstate = new MvpnDBState(state);
996  manager_->SetDBState(leaf_ad, mvpn_dbstate);
997  }
998 
999  pair<MvpnState::RoutesMap::iterator, bool> result =
1000  state->leafad_routes_attr_received().insert(make_pair(leaf_ad,
1001  leaf_ad->BestPath()->GetAttr()));
1002 
1003  // Overwrite the entry with new best path attributes if one already exists.
1004  if (!result.second) {
1005  // Ignore if there is no change in the best path's attributes.
1006  if (result.first->second.get() == leaf_ad->BestPath()->GetAttr())
1007  return;
1008  result.first->second = leaf_ad->BestPath()->GetAttr();
1009  }
1010 
1011  // Update the sender source-active route to update the olist.
1012  MvpnRoute *sa_active_rt = mvpn_dbstate->state()->source_active_rt();
1013  if (sa_active_rt && sa_active_rt->IsUsable()) {
1014  sa_active_rt->Notify();
1015  MVPN_RT_LOG(sa_active_rt, "Processed Type 4 Leaf AD route creation"
1016  " and Type-5 source active route was notified");
1017  } else {
1018  MVPN_RT_LOG(sa_active_rt, "Processed Type 4 Leaf AD route creation");
1019  }
1020 }
1021 
1022 // Process changes to Type3 S-PMSI routes by originating or deleting Type4 Leaf
1023 // AD paths as appropriate.
1025  // Retrieve any state associcated with this S-PMSI route.
1026  MvpnDBState *mvpn_dbstate = dynamic_cast<MvpnDBState *>(
1027  spmsi_rt->GetState(table(), listener_id()));
1028 
1029  MvpnRoute *leaf_ad_route = NULL;
1030  // Process route change as delete if ProjectManager is not set.
1031  bool is_usable = spmsi_rt->IsUsable() && table()->IsProjectManagerUsable();
1032  if (!is_usable) {
1033  if (!mvpn_dbstate)
1034  return;
1035  MvpnStatePtr mvpn_state = GetState(spmsi_rt);
1036  assert(mvpn_dbstate->state() == mvpn_state);
1037 
1038  // Check if a Type4 LeafAD path was already originated before for this
1039  // S-PMSI path. If so, delete it as the S-PMSI path is no nonger usable.
1040  leaf_ad_route = mvpn_dbstate->route();
1041  if (leaf_ad_route) {
1042  BgpPath *path = leaf_ad_route->FindPath(BgpPath::Local, 0);
1043  if (path)
1044  leaf_ad_route->DeletePath(path);
1045  mvpn_dbstate->set_route(NULL);
1046  }
1047 
1048  assert(mvpn_state->spmsi_routes_received().erase(spmsi_rt));
1049  manager_->ClearDBState(spmsi_rt);
1050  delete mvpn_dbstate;
1051  if (leaf_ad_route) {
1052  leaf_ad_route->NotifyOrDelete();
1053 
1054  // Forest node route needs to be updated to delete the source
1055  // address if advertised before.
1056  NotifyForestNode(spmsi_rt->GetPrefix().source(),
1057  spmsi_rt->GetPrefix().group());
1058  MVPN_RT_LOG(spmsi_rt, "Processed Type 3 S-PMSI route deletion"
1059  " and notified local ForestNode");
1060  } else {
1061  MVPN_RT_LOG(spmsi_rt, "Processed Type 3 S-PMSI route deletion");
1062  }
1063  return;
1064  }
1065 
1066  // Ignore notifications of primary S-PMSI paths.
1067  if (!spmsi_rt->BestPath()->IsReplicated())
1068  return;
1069 
1070  // Don't send Type 4 route if there is no receiver in this vrf
1071  const MvpnRoute *join_rt = table()->FindType7SourceTreeJoinRoute(spmsi_rt);
1072  if (!join_rt || !join_rt->IsUsable())
1073  return;
1074 
1075  // A valid S-PMSI path has been imported to a table. Originate a new
1076  // LeafAD path, if GlobalErmVpnTreeRoute is available to stitch.
1077  // TODO(Ananth) If LeafInfoRequired bit is not set in the S-PMSI route,
1078  // then we do not need to originate a leaf ad route for this s-pmsi rt.
1079  MvpnStatePtr mvpn_state = LocateState(spmsi_rt);
1080  assert(mvpn_state);
1081  if (!mvpn_dbstate) {
1082  mvpn_dbstate = new MvpnDBState(mvpn_state);
1083  manager_->SetDBState(spmsi_rt, mvpn_dbstate);
1084  assert(mvpn_state->spmsi_routes_received().insert(spmsi_rt).second);
1085  } else {
1086  leaf_ad_route = mvpn_dbstate->route();
1087  }
1088 
1089  // If LeafInfoRequired bit is not set, no need to process further
1090  if (!spmsi_rt->BestPath()->GetAttr()->pmsi_tunnel() ||
1091  (!(spmsi_rt->BestPath()->GetAttr()->pmsi_tunnel()->tunnel_flags() &
1093  MVPN_RT_LOG(spmsi_rt, "No need to process Type 3 S-PMSI route as"
1094  " LeafInfoRequired bit is not set");
1095  return;
1096  }
1097 
1098  ErmVpnRoute *global_rt = mvpn_state->global_ermvpn_tree_rt();
1099  uint32_t label;
1100  Ip4Address address;
1101  vector<string> tunnel_encaps;
1102  bool pmsi_found =
1103  GetForestNodePMSI(global_rt, &label, &address, &tunnel_encaps);
1104 
1105  if (!pmsi_found) {
1106  // There is no ermvpn route available to stitch at this time. Remove any
1107  // originated Type4 LeafAD route. DB State shall remain on the route as
1108  // SPMSI route itself is still a usable route.
1109  if (leaf_ad_route) {
1110  BgpPath *path = leaf_ad_route->FindPath(BgpPath::Local, 0);
1111  if (path)
1112  leaf_ad_route->DeletePath(path);
1113  mvpn_dbstate->set_route(NULL);
1114  leaf_ad_route->NotifyOrDelete();
1115  NotifyForestNode(spmsi_rt->GetPrefix().source(),
1116  spmsi_rt->GetPrefix().group());
1117  MVPN_RT_LOG(spmsi_rt, "Processed Type 3 S-PMSI route as deletion"
1118  " and notified local ForestNode due to missing PMSI");
1119  }
1120  return;
1121  }
1122 
1123  if (!leaf_ad_route) {
1124  leaf_ad_route = table()->LocateType4LeafADRoute(spmsi_rt);
1125  mvpn_dbstate->set_route(leaf_ad_route);
1126  }
1127  BgpPath *old_path = leaf_ad_route->FindPath(BgpPath::Local, 0);
1128 
1129  // For LeafAD routes, rtarget is always <sender-router-id>:0.
1130  BgpAttrPtr attrp = BgpAttrPtr(spmsi_rt->BestPath()->GetAttr());
1132  rtarget.push_back(RouteTarget(spmsi_rt->GetPrefix().originator(), 0).
1133  GetExtCommunity());
1134  ExtCommunityPtr ext_community = table()->server()->extcomm_db()->
1135  ReplaceRTargetAndLocate(attrp->ext_community(), rtarget);
1136 
1137  ExtCommunity::ExtCommunityList tunnel_encaps_list;
1138  BOOST_FOREACH(string encap, tunnel_encaps) {
1139  tunnel_encaps_list.push_back(TunnelEncap(encap).GetExtCommunity());
1140  }
1141 
1142  ext_community = table()->server()->extcomm_db()->
1143  ReplaceTunnelEncapsulationAndLocate(ext_community.get(),
1144  tunnel_encaps_list);
1145 
1147  attrp.get(), ext_community);
1148 
1149  // Retrieve PMSI tunnel attribute from the GlobalErmVpnTreeRoute.
1150  PmsiTunnelSpec pmsi_spec;
1151  pmsi_spec.tunnel_flags = 0;
1153  pmsi_spec.SetLabel(label, ext_community.get());
1154  pmsi_spec.SetIdentifier(address);
1155 
1156  // Replicate the LeafAD path with appropriate PMSI tunnel info as part of
1157  // the path attributes. Community should be route-target with root ingress
1158  // PE router-id + 0 (Page 254).
1159  BgpAttrPtr new_attrp =
1160  table()->server()->attr_db()->ReplacePmsiTunnelAndLocate(attrp.get(),
1161  &pmsi_spec);
1162 
1163  // Ignore if there is no change in the path attributes of already originated
1164  // leaf ad path.
1165  if (old_path && old_path->GetAttr() == new_attrp.get())
1166  return;
1167 
1168  BgpPath *path = new BgpPath(NULL, 0, BgpPath::Local, new_attrp, 0, 0, 0);
1169  if (old_path)
1170  leaf_ad_route->DeletePath(old_path);
1171  leaf_ad_route->InsertPath(path);
1172  leaf_ad_route->NotifyOrDelete();
1173  NotifyForestNode(spmsi_rt->GetPrefix().source(),
1174  spmsi_rt->GetPrefix().group());
1175  MVPN_RT_LOG(spmsi_rt, "Processed Type 3 S-PMSI route creation");
1176 }
1177 
1179  BgpTable::TableSet *secondary_tables) const {
1180  // Find the right MvpnProjectManagerPartition based on the rt's partition.
1181  const MvpnProjectManagerPartition *partition =
1182  table()->GetProjectManagerPartition(mvpn_rt);
1183  if (!partition)
1184  return;
1185 
1186  // Retrieve MVPN state. Ignore if there is no state or if there is no usable
1187  // Type3 SPMSI route 0associated with it (perhaps it was deleted already).
1188  MvpnState::SG sg(mvpn_rt);
1189  MvpnStatePtr state = partition->GetState(sg);
1190  if (!state || !state->spmsi_rt() || !state->spmsi_rt()->IsUsable())
1191  return;
1192 
1193  // Matching Type-3 S-PMSI route was found. Return its table.
1194  BgpTable *table = dynamic_cast<BgpTable *>(
1195  state->spmsi_rt()->get_table_partition()->parent());
1196  assert(table);
1197 
1198  // Update table list to let replicator invoke RouteReplicate() for this
1199  // LeafAD route for this table which has the corresponding Type3 SPMSI
1200  // route. This was originated as the 'Sender' since receiver joined to
1201  // the <C-S,G> group.
1202  secondary_tables->insert(table);
1203  MVPN_RT_LOG(mvpn_rt, "Updated tables for replication with table " +
1204  table->name());
1205 }
1206 
1207 // Return source_address of the type-3 s-pmsi route used for rpf check in the
1208 // forest node.
1210  Ip4Address *addrp) const {
1211  // Bail if project manager is deleted.
1212  if (deleter_->IsDeleted())
1213  return;
1214 
1215  // Bail if there is no state for this <S,G>.
1216  MvpnStatePtr state = GetState(ermvpn_route);
1217  if (!state)
1218  return;
1219 
1220  // Bail if there is no usable global_ermvpn_tree_rt.
1221  if (!state->global_ermvpn_tree_rt() ||
1222  !state->global_ermvpn_tree_rt()->IsUsable()) {
1223  return;
1224  }
1225 
1226  // Bail if there is no s-pmsi route received (no active sender)
1227  if (state->spmsi_routes_received().empty())
1228  return;
1229 
1230  // Use mvpn type3 spmsi route originator address as the source address.
1231  *addrp = (*(state->spmsi_routes_received().begin()))->
1232  GetPrefix().originator();
1233  MVPN_ERMVPN_RT_LOG(ermvpn_route, "Found Source Address for RPF Check " +
1234  addrp->to_string());
1235 }
1236 
1238  BgpAttrPtr attr = route->BestPath()->GetAttr();
1239  UpdateInfo *uinfo = new UpdateInfo;
1240  uinfo->roattr = RibOutAttr(table(), route, attr.get(), 0, false, true);
1241  return uinfo;
1242 }
1243 
1245  assert((route->GetPrefix().type() == MvpnPrefix::SourceActiveADRoute) ||
1247 
1249  return GetType7UpdateInfo(route);
1250  MvpnStatePtr state = GetState(route);
1251 
1252  // If there is no imported leaf-ad route, then essentially there is no
1253  // olist that can be formed. Route can be withdrawn if already advertised.
1254  if (!state || state->leafad_routes_attr_received().empty())
1255  return NULL;
1256 
1257  // Retrieve olist element from each of the imported type-4 leaf-ad route.
1258  BgpOListSpec olist_spec(BgpAttribute::OList);
1259  BOOST_FOREACH(MvpnState::RoutesMap::value_type &iter,
1260  state->leafad_routes_attr_received()) {
1261  BgpAttrPtr attr = iter.second;
1262  const PmsiTunnel *pmsi = attr->pmsi_tunnel();
1263  if (!pmsi)
1264  continue;
1266  continue;
1267  const ExtCommunity *extcomm = attr->ext_community();
1268  uint32_t label = attr->pmsi_tunnel()->GetLabel(extcomm);
1269  if (!label)
1270  continue;
1271  BgpOListElem elem(pmsi->identifier(), label,
1272  extcomm ? extcomm->GetTunnelEncap() : vector<string>());
1273  olist_spec.elements.push_back(elem);
1274  MVPN_RT_LOG(route, "Encoded olist " + pmsi->pmsi_tunnel().ToString());
1275  }
1276 
1277  if (olist_spec.elements.empty())
1278  return NULL;
1279 
1280  BgpAttrDB *attr_db = table()->server()->attr_db();
1281  BgpAttrPtr attr = attr_db->ReplaceOListAndLocate(
1282  route->BestPath()->GetAttr(), &olist_spec);
1283  UpdateInfo *uinfo = new UpdateInfo;
1284  uinfo->roattr = RibOutAttr(table(), route, attr.get(), 0, false, true);
1285  return uinfo;
1286 }
virtual ErmVpnRoute * GetGlobalTreeRootRoute(const Ip4Address &source, const Ip4Address &group) const
ErmVpnRoute * global_ermvpn_tree_rt()
Definition: bgp_mvpn.cc:294
MvpnProjectManager(ErmVpnTable *table)
Definition: bgp_mvpn.cc:82
const NeighborMap & neighbors() const
Definition: bgp_mvpn.cc:250
Elements elements
Definition: bgp_attr.h:694
MvpnStatePtr GetState(MvpnRoute *route) const
Definition: bgp_mvpn.cc:165
const Ip4Address identifier() const
Definition: bgp_attr.h:384
const MvpnState::StatesMap & states() const
Definition: bgp_mvpn.h:377
tbb::reader_writer_lock neighbors_mutex_
Definition: bgp_mvpn.h:209
const RouteDistinguisher & rd() const
Definition: bgp_mvpn.cc:222
MvpnTable * table_
Definition: bgp_mvpn.h:201
virtual void Initialize()
Definition: bgp_mvpn.cc:606
MvpnProjectManagerPartition * GetProjectManagerPartition()
Definition: bgp_mvpn.cc:514
const BgpPath * BestPath() const
Definition: bgp_route.cc:46
TypePtr Locate(Type *attr)
const ErmVpnPrefix & GetPrefix() const
Definition: ermvpn_route.h:81
MvpnManager * manager_
Definition: bgp_mvpn.h:130
RibOutAttr roattr
Definition: bgp_update.h:100
void NotifyOrDelete()
Definition: bgp_route.cc:747
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
void ManagedDelete()
Definition: bgp_mvpn.cc:157
void set_global_ermvpn_tree_rt(ErmVpnRoute *global_ermvpn_tree_rt)
Definition: bgp_mvpn.cc:326
MvpnManagerPartition(MvpnManager *manager, int part_id)
Definition: bgp_mvpn.cc:506
std::map< RouteDistinguisher, MvpnNeighbor > NeighborMap
Definition: bgp_mvpn.h:161
IpAddress groupIpAddress() const
Definition: mvpn_route.h:77
void ReOriginateType1Route(const Ip4Address &old_identifier)
Definition: bgp_mvpn.cc:625
int listener_id() const
Definition: bgp_mvpn.cc:502
void NotifyForestNode(const Ip4Address &source, const Ip4Address &group)
Definition: bgp_mvpn.cc:576
void SetDBState(MvpnRoute *route, MvpnDBState *mvpn_dbstate)
Definition: bgp_mvpn.cc:481
MvpnProjectManager * project_manager_
Definition: bgp_mvpn.h:321
boost::scoped_ptr< DeleteActor > deleter_
Definition: bgp_mvpn.h:211
RoutesSet spmsi_routes_received_
Definition: bgp_mvpn.h:318
MvpnStatePtr LocateState(const SG &sg)
Definition: bgp_mvpn.cc:195
virtual ~MvpnProjectManagerPartition()
Definition: bgp_mvpn.cc:184
DeleteActor(MvpnProjectManager *manager)
Definition: bgp_mvpn.cc:56
virtual void Terminate()
Definition: bgp_mvpn.cc:431
MvpnStatePtr state_
Definition: bgp_mvpn.h:343
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
void NotifyForestNode(int part_id, const Ip4Address &source, const Ip4Address &group)
boost::asio::ip::address IpAddress
Definition: address.h:13
MvpnRoute * source_active_rt()
Definition: bgp_mvpn.cc:334
MvpnRoute * spmsi_rt_
Definition: bgp_mvpn.h:316
RoutesSet & spmsi_routes_received()
Definition: bgp_mvpn.cc:310
ErmVpnTable * table()
Definition: bgp_mvpn.cc:560
void set_spmsi_rt(MvpnRoute *spmsi_rt)
Definition: bgp_mvpn.cc:330
uint8_t tunnel_type
Definition: bgp_attr.h:359
const uint8_t tunnel_type() const
Definition: bgp_attr.h:383
MvpnManager(MvpnTable *table, ErmVpnTable *ermvpn_table)
Definition: bgp_mvpn.cc:397
MvpnRoute * LocateType4LeafADRoute(const MvpnRoute *type3_spmsi_rt)
Definition: mvpn_table.cc:303
MvpnStatePtr state()
Definition: bgp_mvpn.cc:353
void ProcessType5SourceActiveRoute(MvpnRoute *join_rt)
Definition: bgp_mvpn.cc:822
std::vector< BgpAttribute * > BgpAttrSpec
Definition: bgp_attr.h:822
const BgpPath * FindPath(BgpPath::PathSource src) const
Definition: bgp_route.cc:145
void NotifyAllEntries()
Definition: db_table.cc:596
MvpnRoute * route_
Definition: bgp_mvpn.h:344
ErmVpnRoute * global_ermvpn_tree_rt_
Definition: bgp_mvpn.h:315
tbb::atomic< int > db_states_count_
Definition: bgp_mvpn.h:205
boost::scoped_ptr< DeleteActor > deleter_
Definition: bgp_mvpn.h:455
uint32_t source_as() const
Definition: bgp_mvpn.cc:226
MvpnProjectManager * GetProjectManager()
Definition: bgp_mvpn.cc:525
void ProcessType4LeafADRoute(MvpnRoute *leaf_ad)
Definition: bgp_mvpn.cc:962
virtual void UpdateSecondaryTablesForReplication(MvpnRoute *rt, BgpTable::TableSet *secondary_tables) const
Definition: bgp_mvpn.cc:1178
RouteDistinguisher rd_
Definition: bgp_mvpn.h:68
void Unregister(ListenerId listener)
Definition: db_table.cc:186
UpdateInfo * GetType7UpdateInfo(MvpnRoute *route)
Definition: bgp_mvpn.cc:1237
MvpnTable * table()
Definition: bgp_mvpn.cc:498
MvpnRoute * route()
Definition: bgp_mvpn.cc:357
virtual void Initialize()
Definition: bgp_mvpn.cc:116
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
const McastTreeManager * tree_manager() const
Definition: ermvpn_table.h:64
void GetMvpnSourceAddress(ErmVpnRoute *ermvpn_route, Ip4Address *address) const
Definition: bgp_mvpn.cc:1209
bool IsUsable() const
Definition: bgp_route.cc:324
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
bool FindNeighbor(const RouteDistinguisher &rd, MvpnNeighbor *nbr) const
Definition: bgp_mvpn.cc:239
bool IsDeleted() const
Definition: bgp_table.h:143
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
void FreePartitions()
Definition: bgp_mvpn.cc:463
uint8_t type() const
Definition: ermvpn_route.h:56
uint8_t type() const
Definition: mvpn_route.h:72
const LifetimeActor * deleter() const
Definition: bgp_mvpn.cc:427
void DestroyManager()
Definition: mvpn_table.cc:113
const uint8_t tunnel_flags() const
Definition: bgp_attr.h:382
int RegisterIdentifierUpdateCallback(IdentifierUpdateCb callback)
Definition: bgp_server.cc:947
boost::intrusive_ptr< MvpnState > MvpnStatePtr
Definition: bgp_mvpn.h:39
PartitionList partitions_
Definition: bgp_mvpn.h:453
MvpnRoute * FindType1ADRoute(const Ip4Address &originator_ip)
Definition: mvpn_table.cc:371
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
virtual ~MvpnState()
Definition: bgp_mvpn.cc:40
DeleteActor(MvpnManager *manager)
Definition: bgp_mvpn.cc:371
const MvpnRoute * FindType7SourceTreeJoinRoute(MvpnRoute *rt) const
Definition: mvpn_table.cc:381
bool operator<(const SG &other) const
Definition: bgp_mvpn.cc:278
void RouteListener(DBEntryBase *db_entry)
Definition: bgp_mvpn.cc:766
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:187
bool operator==(const MvpnNeighbor &rhs) const
Definition: bgp_mvpn.cc:234
MvpnProjectManagerPartition(MvpnProjectManager *manager, int part_id)
Definition: bgp_mvpn.cc:179
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
std::map< SG, MvpnState * > StatesMap
Definition: bgp_mvpn.h:279
bool mvpn_ipv4_enable() const
Definition: bgp_server.h:303
void SetIdentifier(Ip4Address identifier)
Definition: bgp_attr.cc:340
virtual ~MvpnManager()
Definition: bgp_mvpn.cc:408
#define CHECK_CONCURRENCY(...)
bool MayDelete() const
Definition: bgp_mvpn.cc:471
std::set< BgpTable * > TableSet
Definition: bgp_table.h:38
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
Definition: bgp_mvpn.cc:660
bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
Definition: bgp_mvpn.cc:589
const LifetimeActor * deleter() const
Definition: bgp_mvpn.cc:110
MvpnTable * table()
Definition: bgp_mvpn.cc:411
IpAddress source
Definition: bgp_mvpn.h:275
IpAddress sourceIpAddress() const
Definition: mvpn_route.h:78
MvpnStatePtr GetState(const SG &sg)
Definition: bgp_mvpn.cc:209
MvpnState::StatesMap states_
Definition: bgp_mvpn.h:399
bool MayDelete() const
Definition: bgp_mvpn.cc:94
MvpnProjectManagerPartition * GetPartition(int part_id)
Definition: bgp_mvpn.cc:148
const std::string & name() const
Definition: db_table.h:110
bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
Definition: bgp_mvpn.cc:596
RoutesMap & leafad_routes_attr_received()
Definition: bgp_mvpn.cc:318
MvpnManager * manager_
Definition: bgp_mvpn.cc:394
uint32_t source_as_
Definition: bgp_mvpn.h:70
int listener_id() const
Definition: bgp_mvpn.cc:529
virtual std::string ToString() const
Definition: bgp_attr.cc:309
Ip4Address source() const
Definition: ermvpn_route.h:60
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
void ProcessType3SPMSIRoute(MvpnRoute *spmsi_rt)
Definition: bgp_mvpn.cc:1024
void SetLabel(uint32_t label, const ExtCommunity *ext)
Definition: bgp_attr.cc:328
BgpAttrPtr ReplacePmsiTunnelAndLocate(const BgpAttr *attr, const PmsiTunnelSpec *pmsi_spec)
Definition: bgp_attr.cc:1405
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
UpdateInfo * GetUpdateInfo(MvpnRoute *route)
Definition: bgp_mvpn.cc:1244
#define MVPN_TRACE(type,...)
Definition: bgp_mvpn.h:510
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
Ip4Address group() const
Definition: ermvpn_route.h:59
virtual int PartitionCount() const
Definition: ermvpn_table.h:44
size_t neighbors_count() const
Definition: bgp_mvpn.cc:256
void FreePartitions()
Definition: bgp_mvpn.cc:141
std::set< MvpnRoute * > RoutesSet
Definition: bgp_mvpn.h:263
BgpServer * server()
Definition: bgp_table.cc:88
MvpnStatePtr CreateState(const SG &sg)
Definition: bgp_mvpn.cc:188
void set_source_active_rt(MvpnRoute *source_active_rt)
Definition: bgp_mvpn.cc:342
void AllocPartitions()
Definition: bgp_mvpn.cc:458
uint32_t bgp_identifier() const
Definition: bgp_server.h:208
bool deleted() const
Definition: bgp_mvpn.cc:423
uint8_t tunnel_flags
Definition: bgp_attr.h:358
MvpnStatePtr GetState(MvpnRoute *route)
Definition: bgp_mvpn.cc:556
void AllocPartitions()
Definition: bgp_mvpn.cc:136
const MvpnProjectManager * GetProjectManager() const
Definition: mvpn_table.cc:185
void DestroyMvpnProjectManager()
BgpAttrDB * attr_db()
Definition: bgp_server.h:181
void set_route(MvpnRoute *route)
Definition: bgp_mvpn.cc:361
const MvpnProjectManagerPartition * GetProjectManagerPartition(BgpRoute *route) const
Definition: mvpn_table.cc:222
BgpAttrPtr ReplaceOListAndLocate(const BgpAttr *attr, const BgpOListSpec *olist_spec)
Definition: bgp_attr.cc:1378
void ProcessType1ADRoute(MvpnRoute *route)
Definition: bgp_mvpn.cc:705
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
bool IsMaster() const
Definition: mvpn_table.cc:664
virtual void Terminate()
Definition: bgp_mvpn.cc:128
ErmVpnTable * table()
Definition: bgp_mvpn.cc:568
void ProcessType7SourceTreeJoinRoute(MvpnRoute *join_rt)
Definition: bgp_mvpn.cc:920
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
virtual bool MayDelete() const
Definition: bgp_mvpn.cc:64
bool deleted() const
Definition: bgp_mvpn.cc:161
std::vector< std::string > GetTunnelEncap() const
Definition: community.cc:595
NeighborMap neighbors_
Definition: bgp_mvpn.h:208
virtual void Shutdown()
Definition: bgp_mvpn.cc:383
static const int kInvalidId
Definition: db_table.h:64
std::string ToString() const
Definition: rd.cc:56
bool IsUsableGlobalTreeRootRoute(ErmVpnRoute *ermvpn_route) const
Definition: bgp_mvpn.cc:743
MvpnStatePtr LocateState(MvpnRoute *route)
Definition: bgp_mvpn.cc:537
void ManagedDelete()
Definition: bgp_mvpn.cc:454
virtual void Destroy()
Definition: bgp_mvpn.cc:389
void OriginateType1Route()
Definition: bgp_mvpn.cc:638
const PmsiTunnelSpec & pmsi_tunnel() const
Definition: bgp_attr.h:373
virtual ~MvpnProjectManager()
Definition: bgp_mvpn.cc:89
RoutesMap leafad_routes_attr_received_
Definition: bgp_mvpn.h:319
MvpnRoute * spmsi_rt()
Definition: bgp_mvpn.cc:302
tbb::atomic< int > refcount_
Definition: bgp_mvpn.h:322
void DeletePath(BgpPath *path)
Definition: bgp_route.cc:126
MvpnDBState(MvpnStatePtr state)
Definition: bgp_mvpn.cc:346
int identifier_listener_id_
Definition: bgp_mvpn.h:204
IpAddress group
Definition: bgp_mvpn.h:276
const ErmVpnTable * table() const
Definition: bgp_mvpn.cc:49
void Notify()
Definition: db_entry.cc:127
const SG & sg() const
Definition: bgp_mvpn.cc:290
MvpnProjectManager * manager_
Definition: bgp_mvpn.cc:77
MvpnState(const SG &sg, StatesMap *states, MvpnProjectManager *pm)
Definition: bgp_mvpn.cc:34
void ClearDBState(MvpnRoute *route)
Definition: bgp_mvpn.cc:488
virtual bool MayDelete() const
Definition: bgp_mvpn.cc:378
DBTablePartBase * get_table_partition() const
Definition: db_entry.cc:115
const IpAddress & originator() const
Definition: bgp_mvpn.cc:230
#define MVPN_LOG(type,...)
Definition: bgp_mvpn.h:506
int listener_id_
Definition: bgp_mvpn.h:203
Ip4Address source() const
Definition: mvpn_route.h:75
const MvpnPrefix & GetPrefix() const
Definition: mvpn_route.h:139
ErmVpnTable * table_
Definition: bgp_mvpn.h:451
void NotifyForestNode(const Ip4Address &source, const Ip4Address &group)
Definition: bgp_mvpn.cc:582
const PmsiTunnel * pmsi_tunnel() const
Definition: bgp_attr.h:917
MvpnRoute * source_active_rt_
Definition: bgp_mvpn.h:317
const RouteDistinguisher & route_distinguisher() const
Definition: mvpn_route.h:73
#define MVPN_ERMVPN_RT_LOG(rt,...)
Definition: bgp_mvpn.h:498
IpAddress originator_
Definition: bgp_mvpn.h:69
Ip4Address originator() const
Definition: mvpn_route.h:76
MvpnRoute * LocateType3SPMSIRoute(const MvpnRoute *type7_join_rt)
Definition: mvpn_table.cc:342
virtual bool IsReplicated() const
Definition: bgp_path.h:91
PartitionList partitions_
Definition: bgp_mvpn.h:206
void UnregisterIdentifierUpdateCallback(int listener)
Definition: bgp_server.cc:963
std::map< MvpnRoute *, BgpAttrPtr > RoutesMap
Definition: bgp_mvpn.h:264
virtual int PartitionCount() const
Definition: mvpn_table.h:49
bool IsProjectManagerUsable() const
Definition: mvpn_table.cc:200
#define MVPN_RT_LOG(rt,...)
Definition: bgp_mvpn.h:490
virtual ~MvpnManagerPartition()
Definition: bgp_mvpn.cc:510
virtual bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
int listener_id() const
Definition: bgp_mvpn.cc:419
MvpnProjectManager * manager_
Definition: bgp_mvpn.h:395
MvpnRoute * LocateType1ADRoute()
Definition: mvpn_table.cc:366
void set_state(MvpnStatePtr state)
Definition: bgp_mvpn.cc:365
int index() const
SG(const Ip4Address &source, const Ip4Address &group)
Definition: bgp_mvpn.cc:261
Ip4Address group() const
Definition: mvpn_route.h:74
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
Definition: bgp_mvpn.cc:757