OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_evpn.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "bgp/bgp_evpn.h"
6 
7 #include <boost/foreach.hpp>
8 
9 #include <algorithm>
10 #include <string>
11 
12 #include "base/set_util.h"
13 #include "base/task_annotations.h"
14 #include "bgp/bgp_log.h"
15 #include "bgp/bgp_multicast.h"
16 #include "bgp/bgp_peer_types.h"
17 #include "bgp/bgp_server.h"
18 #include "bgp/bgp_update.h"
21 #include "bgp/evpn/evpn_table.h"
24 #include "bgp/routing-instance/routing_instance_analytics_types.h"
26 
27 using std::pair;
28 using std::set;
29 using std::sort;
30 using std::string;
31 using std::vector;
32 
33 // A global MVPN state for a given <S.G> within a EvpnProjectManager.
34 EvpnState::EvpnState(const SG &sg, StatesMap *states, EvpnManager *manager) :
35  sg_(sg), global_ermvpn_tree_rt_(NULL), states_(states),
36  manager_(manager) {
37  refcount_ = 0;
38 }
39 
41  assert(!global_ermvpn_tree_rt_);
42  EVPN_TRACE(EvpnStateCreate, sg_.source.to_string(), sg_.group.to_string());
43 }
44 
45 const ErmVpnTable *EvpnState::table() const {
46  return manager_ ? manager_->ermvpn_table() : NULL;
47 }
48 
50 public:
51  explicit DeleteActor(EvpnManager *evpn_manager)
52  : LifetimeActor(evpn_manager->server()->lifetime_manager()),
53  evpn_manager_(evpn_manager) {
54  }
55  virtual ~DeleteActor() {
56  }
57 
58  virtual bool MayDelete() const {
59  CHECK_CONCURRENCY("bgp::Config");
60  return evpn_manager_->MayDelete();
61  }
62 
63  virtual void Shutdown() {
65  }
66 
67  virtual void Destroy() {
69  }
70 
71 private:
73 };
74 
75 //
76 // Constructor for EvpnMcastNode. The type indicates whether this is a local
77 // or remote EvpnMcastNode.
78 //
80  EvpnRoute *route, uint8_t type)
81  : partition_(partition),
82  state_(NULL),
83  route_(route),
84  type_(type),
85  label_(0),
86  edge_replication_not_supported_(false),
87  assisted_replication_supported_(false),
88  assisted_replication_leaf_(false) {
89  UpdateAttributes(route);
90 }
91 
93  EvpnRoute *route, uint8_t type, EvpnStatePtr state)
94  : partition_(partition),
95  state_(state),
96  route_(route),
97  type_(type),
98  label_(0),
99  edge_replication_not_supported_(false),
100  assisted_replication_supported_(false),
101  assisted_replication_leaf_(false) {
102  if (route)
103  UpdateAttributes(route);
104 }
105 
106 //
107 // Destructor for EvpnMcastNode.
108 //
110  set_state(NULL);
111 }
112 
113 //
114 // Update the label and attributes for a EvpnMcastNode.
115 // Return true if either of them changed.
116 //
118  bool changed = false;
119  const BgpPath *path = route->BestPath();
120  if (path->GetLabel() != label_) {
121  label_ = path->GetLabel();
122  changed = true;
123  }
124  if (path->GetAttr() != attr_) {
125  attr_ = path->GetAttr();
126  changed = true;
127  }
128 
129  const PmsiTunnel *pmsi_tunnel = attr_->pmsi_tunnel();
130  uint8_t ar_type = 0;
131  bool edge_replication_not_supported = false;
132  if (pmsi_tunnel) {
133  ar_type = pmsi_tunnel->tunnel_flags() &
135  if ((pmsi_tunnel->tunnel_flags() &
137  edge_replication_not_supported = true;
138  }
139  if (replicator_address_ != pmsi_tunnel->identifier()) {
140  replicator_address_ = pmsi_tunnel->identifier();
141  changed = true;
142  }
143  }
144 
145  if (edge_replication_not_supported != edge_replication_not_supported_) {
147  changed = true;
148  }
149 
150  bool assisted_replication_supported = false;
151  if (ar_type == PmsiTunnelSpec::ARReplicator)
152  assisted_replication_supported = true;
153  if (assisted_replication_supported != assisted_replication_supported_) {
155  changed = true;
156  }
157 
158  bool assisted_replication_leaf = false;
159  if (ar_type == PmsiTunnelSpec::ARLeaf)
160  assisted_replication_leaf = true;
161  if (assisted_replication_leaf != assisted_replication_leaf_) {
163  changed = true;
164  }
165 
166  if (address_ != path->GetAttr()->nexthop().to_v4()) {
167  address_ = path->GetAttr()->nexthop().to_v4();
168  changed = true;
169  }
170 
171  return changed;
172 }
173 
174 //
175 // Constructor for EvpnLocalMcastNode.
176 //
177 // Add an Inclusive Multicast route corresponding to Broadcast MAC route.
178 //
179 // Need to Notify the Broadcast MAC route so that the table Export method
180 // can run and build the OList. OList is not built till EvpnLocalMcastNode
181 // has been created.
182 //
184  EvpnRoute *route)
185  : EvpnMcastNode(partition, route, EvpnMcastNode::LocalNode),
186  inclusive_mcast_route_(NULL) {
188  DBTablePartition *tbl_partition = partition_->GetTablePartition();
189  tbl_partition->Notify(route_);
190 }
191 
193  EvpnRoute *route, EvpnStatePtr state)
194  : EvpnMcastNode(partition, route, EvpnMcastNode::LocalNode, state),
195  inclusive_mcast_route_(NULL) {
196  if (!route)
197  return;
199  DBTablePartition *tbl_partition = partition_->GetTablePartition();
200  tbl_partition->Notify(route_);
201 }
202 
203 //
204 // Destructor for EvpnLocalMcastNode.
205 //
208 }
209 
210 //
211 // Add Inclusive Multicast route for this EvpnLocalMcastNode.
212 // The attributes are based on the Broadcast MAC route.
213 //
215  // No need to create IMET route if group is specified
216  if (!route_->GetPrefix().group().is_unspecified())
217  return;
218  assert(!inclusive_mcast_route_);
219  if (label_ == 0)
220  return;
221 
222  // Construct the prefix and route key.
223  // Build the RD using the TOR IP address, not the TOR agent IP address.
224  // This ensures that the MAC broadcast route from the primary and backup
225  // TOR Agents results in the same Inclusive Multicast prefix.
226  const EvpnPrefix &mac_prefix = route_->GetPrefix();
228  address_.to_ulong(), mac_prefix.route_distinguisher().GetVrfId());
229  EvpnPrefix prefix(rd, mac_prefix.tag(), address_);
230  EvpnRoute rt_key(prefix);
231 
232  // Find or create the route.
233  DBTablePartition *tbl_partition = partition_->GetTablePartition();
234  EvpnRoute *route = static_cast<EvpnRoute *>(tbl_partition->Find(&rt_key));
235  if (!route) {
236  route = new EvpnRoute(prefix);
237  tbl_partition->Add(route);
238  } else {
239  route->ClearDelete();
240  }
241  // Add MulticastFlags community to specify that it supports SMET route
243  mcastFlags.push_back(MulticastFlags().GetExtCommunity());
244  ExtCommunityPtr ext_community = partition_->server()->extcomm_db()->
245  ReplaceMFlagsAndLocate(attr_->ext_community(), mcastFlags);
247  attr_.get(), ext_community);
248 
249  // Add a path with source BgpPath::Local and the peer address as path_id.
250  uint32_t path_id = mac_prefix.route_distinguisher().GetAddress();
251  BgpPath *path = new BgpPath(path_id, BgpPath::Local, attr_, 0, label_);
252  route->InsertPath(path);
254  tbl_partition->Notify(inclusive_mcast_route_);
255  BGP_LOG_ROUTE(partition_->table(), static_cast<IPeer *>(NULL),
256  route, "Insert new Local path");
257 }
258 
259 //
260 // Delete Inclusive Multicast route for this EvpnLocalMcastNode.
261 //
264  return;
265 
266  const EvpnPrefix &mac_prefix = route_->GetPrefix();
267  uint32_t path_id = mac_prefix.route_distinguisher().GetAddress();
268  DBTablePartition *tbl_partition = partition_->GetTablePartition();
270  BGP_LOG_ROUTE(partition_->table(), static_cast<IPeer *>(NULL),
271  inclusive_mcast_route_, "Delete Local path");
272 
274  tbl_partition->Delete(inclusive_mcast_route_);
275  } else {
276  tbl_partition->Notify(inclusive_mcast_route_);
277  }
278  inclusive_mcast_route_ = NULL;
279 }
280 
281 //
282 // Handle update of EvpnLocalMcastNode.
283 //
284 // We delete and add the Inclusive Multicast route to ensure that all the
285 // attributes are updated. An in-place update is not always possible since
286 // the vRouter address is part of the key for the Inclusive Multicast route.
287 //
291 }
292 
293 //
294 // Construct an UpdateInfo with the RibOutAttr that needs to be advertised to
295 // the IPeer for the EvpnRoute associated with this EvpnLocalMcastNode. This
296 // is used the Export method of the EvpnTable. It is expected that the caller
297 // fills in the target RibPeerSet in the UpdateInfo.
298 //
299 // The main functionality here is to build a per-IPeer BgpOList from the list
300 // of EvpnRemoteMcastNodes.
301 //
303  CHECK_CONCURRENCY("db::DBTable");
304 
305  // Nothing to send for a leaf as it already knows the replicator-address.
307  return NULL;
308 
310  bool pbb_evpn_enable = rti->virtual_network_pbb_evpn_enable();
311  uint32_t local_ethernet_tag = route_->GetPrefix().tag();
312 
314  route->GetPrefix().group());
315  // Go through list of EvpnRemoteMcastNodes and build the BgpOList.
316  BgpOListSpec olist_spec(BgpAttribute::OList);
317  if (partition_->remote_mcast_node_list()->count(sg)) {
318  set<EvpnMcastNode*> nodes = (*partition_->remote_mcast_node_list())[sg];
319  BOOST_FOREACH(EvpnMcastNode *node, nodes) {
320  if (node->address() == address_)
321  continue;
322  if (node->assisted_replication_leaf())
323  continue;
326  continue;
327  uint32_t remote_ethernet_tag = node->route()->GetPrefix().tag();
328 
329  if (pbb_evpn_enable && remote_ethernet_tag &&
330  (local_ethernet_tag != remote_ethernet_tag))
331  continue;
332 
333  const ExtCommunity *extcomm = node->attr()->ext_community();
334  BgpOListElem elem(node->address(), node->label(),
335  extcomm ? extcomm->GetTunnelEncap() : vector<string>());
336  olist_spec.elements.push_back(elem);
337  }
338  }
339 
340  // Go through list of leaf EvpnMcastNodes and build the leaf BgpOList.
341  BgpOListSpec leaf_olist_spec(BgpAttribute::LeafOList);
343  if (partition_->leaf_node_list()->count(sg)) {
344  set<EvpnMcastNode*> nodes = (*partition_->leaf_node_list())[sg];
345  BOOST_FOREACH(EvpnMcastNode *node, nodes) {
346  if (node->replicator_address() != address_)
347  continue;
348 
349  const ExtCommunity *extcomm = node->attr()->ext_community();
350  BgpOListElem elem(node->address(), node->label(),
351  extcomm ? extcomm->GetTunnelEncap() : vector<string>());
352  leaf_olist_spec.elements.push_back(elem);
353  }
354  }
355  }
356 
357  // Bail if both BgpOLists are empty.
358  if (olist_spec.elements.empty() && leaf_olist_spec.elements.empty())
359  return NULL;
360 
361  // Add BgpOList and leaf BgpOList to RibOutAttr for broadcast MAC route.
362  BgpAttrDB *attr_db = partition_->server()->attr_db();
363  BgpAttrPtr attr = attr_db->ReplaceOListAndLocate(attr_.get(), &olist_spec);
364  attr = attr_db->ReplaceLeafOListAndLocate(attr.get(), &leaf_olist_spec);
365 
366  UpdateInfo *uinfo = new UpdateInfo;
367  uinfo->roattr =
368  RibOutAttr(partition_->table(), route_, attr.get(), 0, false, true);
369  return uinfo;
370 }
371 
372 //
373 // Constructor for EvpnRemoteMcastNode.
374 //
376  EvpnRoute *route)
377  : EvpnMcastNode(partition, route, EvpnMcastNode::RemoteNode) {
378 }
379 
381  EvpnRoute *route, EvpnStatePtr state)
382  : EvpnMcastNode(partition, route, EvpnMcastNode::RemoteNode, state) {
383 }
384 
385 //
386 // Destructor for EvpnRemoteMcastNode.
387 //
389 }
390 
391 //
392 // Handle update of EvpnRemoteMcastNode.
393 //
395 }
396 
397 //
398 // Constructor for EvpnSegment.
399 //
401  : evpn_manager_(manager),
402  esi_(esi),
403  esi_ad_route_(NULL),
404  single_active_(true),
405  route_lists_(DB::PartitionCount()) {
406 }
407 
408 //
409 // Destructor for EvpnSegment.
410 //
412  assert(!esi_ad_route_);
413  assert(pe_list_.empty());
414 }
415 
416 //
417 // Add the given MAC route as a dependent of this EvpnSegment.
418 //
419 void EvpnSegment::AddMacRoute(size_t part_id, EvpnRoute *route) {
420  pair<RouteList::iterator, bool> ret = route_lists_[part_id].insert(route);
421  assert(ret.second);
422 }
423 
424 //
425 // Delete the given MAC route as a dependent of this EvpnSegment.
426 // Trigger deletion of the EvpnSegment if there are no dependent
427 // routes in the partition.
428 //
429 void EvpnSegment::DeleteMacRoute(size_t part_id, EvpnRoute *route) {
430  size_t count = route_lists_[part_id].erase(route);
431  assert(count == 1);
432  if (route_lists_[part_id].empty())
434 }
435 
436 //
437 // Trigger an update of all dependent MAC routes for this EvpnSegment.
438 // Note that the bgp::EvpnSegment task is mutually exclusive with the
439 // db::DBTable task.
440 //
442  CHECK_CONCURRENCY("bgp::EvpnSegment");
443 
444  for (size_t part_id = 0; part_id < route_lists_.size(); ++part_id) {
445  EvpnManagerPartition *partition = evpn_manager_->GetPartition(part_id);
446  BOOST_FOREACH(EvpnRoute *route, route_lists_[part_id]) {
447  partition->TriggerMacRouteUpdate(route);
448  }
449  }
450 }
451 
452 //
453 // Update the PE list for this EvpnSegment. This should be called when
454 // the AutoDisocvery route is updated.
455 // Return true if there's a change in the PE list i.e. if an entry is
456 // added, deleted or updated.
457 //
459  CHECK_CONCURRENCY("bgp::EvpnSegment");
460 
461  // Mark all entries as invalid.
462  for (RemotePeList::iterator it = pe_list_.begin();
463  it != pe_list_.end(); ++it) {
464  it->esi_valid = false;
465  }
466 
467  // Go through all paths for the route and refresh/update existing entries
468  // or add new ones as necessary. Remember that there was a change in the
469  // list if any element changed or is added/deleted.
470  bool changed = false;
471  for (Route::PathList::const_iterator path_it =
472  esi_ad_route_->GetPathList().begin();
473  path_it != esi_ad_route_->GetPathList().end(); ++path_it) {
474  const BgpPath *path =
475  static_cast<const BgpPath *>(path_it.operator->());
476  const BgpAttr *attr = path->GetAttr();
477 
478  // Skip non-VXLAN paths for now.
479  const ExtCommunity *extcomm = attr->ext_community();
480  if (!extcomm || !extcomm->ContainsTunnelEncapVxlan())
481  continue;
482 
483  // Go through existing pe list and try to find the RemotePe.
484  bool found = false;
485  RemotePe remote_pe(path);
486  for (RemotePeList::iterator it = pe_list_.begin();
487  it != pe_list_.end(); ++it) {
488  // Skip if the nexthop doesn't match.
489  if (it->attr->nexthop() != remote_pe.attr->nexthop())
490  continue;
491 
492  // We're done if there are multiple paths for the same remote PE
493  // e.g. when a pair of route reflectors is being used.
494  if (it->esi_valid) {
495  found = true;
496  break;
497  }
498 
499  // Check if we have a match.
500  if (*it == remote_pe) {
501  it->esi_valid = true;
502  found = true;
503  break;
504  }
505  }
506 
507  // Add a new entry to the pe list if we didn't find the RemotePe.
508  if (!found) {
509  pe_list_.push_back(remote_pe);
510  changed = true;
511  }
512  }
513 
514  // Erase invalid entries from the list.
515  for (RemotePeList::iterator it = pe_list_.begin(), next = it;
516  it != pe_list_.end(); it = next) {
517  ++next;
518  if (!it->esi_valid) {
519  pe_list_.erase(it);
520  changed = true;
521  }
522  }
523 
524  // Update the single active status of the EvpnSegment itself.
525  single_active_ = false;
526  for (RemotePeList::iterator it = pe_list_.begin();
527  it != pe_list_.end(); ++it) {
528  if (it->single_active) {
529  single_active_ = true;
530  break;
531  }
532  }
533 
534  return changed;
535 }
536 
537 //
538 // Return true if it's safe to delete this EvpnSegment.
539 //
541  CHECK_CONCURRENCY("bgp::EvpnSegment");
542 
543  // Bail if we have state set on the per-ESI AD route.
544  if (esi_ad_route_)
545  return false;
546 
547  // Bail if the dependent route list for any partition is not empty.
548  for (size_t part_id = 0; part_id < route_lists_.size(); ++part_id) {
549  if (!route_lists_[part_id].empty())
550  return false;
551  }
552 
553  return true;
554 }
555 
556 //
557 // Constructor for EvpnSegment::RemotePe.
558 //
560  : esi_valid(true),
561  single_active(path->GetAttr()->evpn_single_active()),
562  peer(path->GetPeer()),
563  attr(path->GetAttr()),
564  flags(path->GetFlags()),
565  src(path->GetSource()) {
566 }
567 
568 //
569 // Equality operator for EvpnSegment::RemotePe.
570 // Do not compare esi_valid and single_active fields since they are
571 // derived.
572 //
574  if (peer != rhs.peer)
575  return false;
576  if (attr != rhs.attr)
577  return false;
578  if (flags != rhs.flags)
579  return false;
580  if (src != rhs.src)
581  return false;
582  return true;
583 }
584 
585 //
586 // Constructor for EvpnMacState.
587 //
589  : evpn_manager_(evpn_manager), route_(route), segment_(NULL) {
590 }
591 
592 //
593 // Destructor for EvpnMacState.
594 //
596  assert(segment_ == NULL);
597  assert(aliased_path_list_.empty());
598 }
599 
600 //
601 // Add the BgpPath specified by the iterator to the aliased path list.
602 // Also inserts the BgpPath to the BgpRoute.
603 //
604 void EvpnMacState::AddAliasedPath(AliasedPathList::const_iterator it) {
605  BgpPath *path = *it;
606  const IPeer *peer = path->GetPeer();
607  aliased_path_list_.insert(path);
608  route_->InsertPath(path);
609  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
610  "Added aliased path " << route_->ToString() <<
611  " peer " << (peer ? peer->ToString() : "None") <<
612  " nexthop " << path->GetAttr()->nexthop().to_string() <<
613  " label " << path->GetLabel() <<
614  " in table " << evpn_manager_->table()->name());
615 }
616 
617 //
618 // Delete the BgpPath specified by the iterator from the aliased path list.
619 // Also deletes the BgpPath from the BgpRoute.
620 //
621 void EvpnMacState::DeleteAliasedPath(AliasedPathList::const_iterator it) {
622  BgpPath *path = *it;
623  const IPeer *peer = path->GetPeer();
624  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
625  "Deleted aliased path " << route_->ToString() <<
626  " peer " << (peer ? peer->ToString() : "None") <<
627  " nexthop " << path->GetAttr()->nexthop().to_string() <<
628  " label " << path->GetLabel() <<
629  " in table " << evpn_manager_->table()->name());
630  route_->DeletePath(path);
631  aliased_path_list_.erase(it);
632 }
633 
634 //
635 // Find or create the matching aliased BgpPath.
636 //
638  const EvpnSegment::RemotePe *remote_pe, uint32_t label) {
639  const IPeer *peer = remote_pe->peer;
640  const BgpAttr *attr = remote_pe->attr.get();
641  uint32_t flags = remote_pe->flags | BgpPath::AliasedPath;
642  BgpPath::PathSource src = remote_pe->src;
643  for (AliasedPathList::iterator it = aliased_path_list_.begin();
644  it != aliased_path_list_.end(); ++it) {
645  BgpPath *path = *it;
646  if (path->GetPeer() == peer &&
647  path->GetAttr() == attr &&
648  path->GetFlags() == flags &&
649  path->GetLabel() == label) {
650  return path;
651  }
652  }
653 
654  return (new BgpPath(peer, src, attr, flags, label));
655 }
656 
657 //
658 // Update aliased BgpPaths for the EvpnRoute based on the remote PEs
659 // for the EvpnSegment.
660 // Return true if the list of aliased paths is modified.
661 //
663  CHECK_CONCURRENCY("db::DBTable");
664 
665  const BgpPath *path = route_->BestPath();
666 
667  // Find the remote PE entry that corresponds to the primary path.
668  bool found_primary_pe = false;
670  if (path && segment_ && !segment_->single_active())
671  it = segment_->begin();
672  for (; path && segment_ && !segment_->single_active() &&
673  it != segment_->end(); ++it) {
674  if (path->GetAttr()->nexthop() != it->attr->nexthop())
675  continue;
676  found_primary_pe = true;
677  break;
678  }
679 
680  // Go through the remote PE list for the EvpnSegment and build the
681  // list of future aliased paths.
682  AliasedPathList future_aliased_path_list;
683  if (found_primary_pe && path && segment_ && !segment_->single_active())
684  it = segment_->begin();
685  for (; found_primary_pe && path && segment_ &&
686  !segment_->single_active() && it != segment_->end(); ++it) {
687  // Skip if there's a BGP_XMPP path with the remote PE as nexthop.
688  if (route_->FindPath(it->attr->nexthop()))
689  continue;
690 
691  // Locate the aliased path using attributes for the remote PE and
692  // label from the primary path.
693  BgpPath *aliased_path =
694  LocateAliasedPath(it.operator->(), path->GetLabel());
695  future_aliased_path_list.insert(aliased_path);
696  }
697 
698  // Reconcile the current and future aliased paths and notify/delete the
699  // route as appropriate.
700  bool modified = set_synchronize(&aliased_path_list_,
701  &future_aliased_path_list,
702  boost::bind(&EvpnMacState::AddAliasedPath, this, _1),
703  boost::bind(&EvpnMacState::DeleteAliasedPath, this, _1));
704  return modified;
705 }
706 
707 //
708 // Constructor for EvpnManagerPartition.
709 //
711  size_t part_id)
712  : evpn_manager_(evpn_manager),
713  part_id_(part_id),
714  mac_update_trigger_(new TaskTrigger(
715  boost::bind(&EvpnManagerPartition::ProcessMacUpdateList, this),
716  TaskScheduler::GetInstance()->GetTaskId("db::DBTable"),
717  part_id)) {
719 }
720 
721 //
722 // Destructor for EvpnManagerPartition.
723 //
725  assert(local_mcast_node_list_.empty());
726  assert(remote_mcast_node_list_.empty());
727  assert(mac_update_list_.empty());
728 }
729 
730 //
731 // Get the DBTablePartition for the EvpnTable for our partition id.
732 //
735 }
736 
737 //
738 // Notify the Broadcast MAC route for the given EvpnMcastNode.
739 //
741  DBTablePartition *tbl_partition = GetTablePartition();
742  tbl_partition->Notify(node->route());
743 }
744 
745 //
746 // Go through all replicator EvpnMcastNodes and notify associated Broadcast
747 // MAC route.
748 //
750  DBTablePartition *tbl_partition = GetTablePartition();
751  EvpnMcastNodeList::const_iterator it = replicator_node_list_.begin();
752  for (; it != replicator_node_list_.end(); it++) {
753  BOOST_FOREACH(EvpnMcastNode *node, it->second)
754  tbl_partition->Notify(node->route());
755  }
756 }
757 
758 //
759 // Go through all ingress replication client EvpnMcastNodes and notify the
760 // associated Broadcast MAC route.
761 //
763  bool exclude_edge_replication_supported) {
764  DBTablePartition *tbl_partition = GetTablePartition();
765  EvpnMcastNodeList::const_iterator it = ir_client_node_list_.begin();
766  for (; it != ir_client_node_list_.end(); it++) {
767  BOOST_FOREACH(EvpnMcastNode *node, it->second) {
768  if (exclude_edge_replication_supported &&
770  continue;
771  }
772  tbl_partition->Notify(node->route());
773  }
774  }
775 }
776 
777 //
778 // Add an EvpnMcastNode to the EvpnManagerPartition.
779 //
782  rt->GetPrefix().group());
783  if (node->type() == EvpnMcastNode::LocalNode) {
784  local_mcast_node_list_[sg].insert(node);
785  if (node->assisted_replication_supported())
786  replicator_node_list_[sg].insert(node);
787  if (!node->assisted_replication_leaf())
788  ir_client_node_list_[sg].insert(node);
789  NotifyNodeRoute(node);
790  } else {
791  remote_mcast_node_list_[sg].insert(node);
792  if (node->assisted_replication_leaf()) {
793  leaf_node_list_[sg].insert(node);
795  } else if (node->edge_replication_not_supported()) {
796  regular_node_list_[sg].insert(node);
798  } else if (!node->assisted_replication_leaf()) {
800  }
801  }
802 }
803 
804 //
805 // Delete an EvpnMcastNode from the EvpnManagerPartition.
806 //
808  EvpnMcastNode *node,
809  EvpnMcastNodeList *list) {
810  size_t deleted = 0;
811  if (list->count(sg)) {
812  deleted = (*list)[sg].erase(node);
813  if ((*list)[sg].size() == 0)
814  list->erase(sg);
815  }
816  return (deleted > 0);
817 }
818 
819 //
820 // Delete an EvpnMcastNode from the EvpnManagerPartition.
821 //
823  EvpnRoute * rt) {
825  rt->GetPrefix().group());
826  if (node->type() == EvpnMcastNode::LocalNode) {
830  } else {
832  if (RemoveMcastNodeFromList(sg, node, &leaf_node_list_)) {
834  } else {
836  }
839  }
840  }
841  if (empty())
843 }
844 
845 //
846 // Update an EvpnMcastNode in the EvpnManagerPartition.
847 // Need to remove/add EvpnMcastNode from the replicator, leaf and ir client
848 // lists as appropriate.
849 //
851  node->TriggerUpdate();
853  rt->GetPrefix().group());
854  if (node->type() == EvpnMcastNode::LocalNode) {
856  if (node->assisted_replication_supported())
857  replicator_node_list_[sg].insert(node);
859  if (!node->assisted_replication_leaf())
860  ir_client_node_list_[sg].insert(node);
861  NotifyNodeRoute(node);
862  } else {
863  bool was_leaf = RemoveMcastNodeFromList(sg, node, &leaf_node_list_);
864  if (node->assisted_replication_leaf())
865  leaf_node_list_[sg].insert(node);
866  if (was_leaf || node->assisted_replication_leaf())
868  if (!was_leaf || !node->assisted_replication_leaf())
870  bool was_regular = RemoveMcastNodeFromList(
871  sg, node, &regular_node_list_);
872  if (node->edge_replication_not_supported())
873  regular_node_list_[sg].insert(node);
874  if (was_regular || node->edge_replication_not_supported())
876  }
877 }
878 
879 //
880 // Add the given MAC route to the update list.
881 // This method gets called either when the MAC route itself changes or when
882 // the remote PE list for the EvpnSegment of the MAC route gets updated.
883 //
885  CHECK_CONCURRENCY("db::DBTable", "bgp::EvpnSegment");
886 
887  mac_update_list_.insert(route);
888  mac_update_trigger_->Set();
889 }
890 
891 //
892 // Process the MAC route update list for this EvpnManagerPartition.
893 //
895  CHECK_CONCURRENCY("db::DBTable");
896 
898  int listener_id = evpn_manager_->listener_id();
899 
900  BOOST_FOREACH(EvpnRoute *route, mac_update_list_) {
901  // Skip if the route is on the change list. We will get another
902  // chance to process it after the MacAdvertisement listener sees
903  // it and changes the EvpnMacState to point to the updated value
904  // of EvpnSegment.
905  if (route->is_onlist())
906  continue;
907 
908  EvpnMacState *mac_state =
909  dynamic_cast<EvpnMacState *>(route->GetState(table, listener_id));
910  assert(mac_state);
911  bool modified = mac_state->ProcessMacRouteAliasing();
912  if (route->HasPaths()) {
913  if (!mac_state->segment()) {
914  route->ClearState(table, listener_id);
915  delete mac_state;
916  }
917  if (modified) {
918  table_partition_->Notify(route);
919  }
920  } else {
921  route->ClearState(table, listener_id);
922  table_partition_->Delete(route);
923  delete mac_state;
924  }
925  }
926 
927  mac_update_list_.clear();
929  return true;
930 }
931 
933  Ip4Address *address) const {
935  return false;
936  uint32_t label;
937  vector<string> te;
939  rt, &label, address, &te);
940 }
941 
943  EvpnState::StatesMap::const_iterator iter = states_.find(sg);
944  return iter != states_.end() ? iter->second : NULL;
945 }
946 
948  EvpnState::StatesMap::iterator iter = states_.find(sg);
949  return iter != states_.end() ? iter->second : NULL;
950 }
951 
954  rt->GetPrefix().group());
955  return GetState(sg);
956 }
957 
959  EvpnStatePtr state(new EvpnState(sg, &states_, evpn_manager_));
960  assert(states_.insert(make_pair(sg, state.get())).second);
961  EVPN_TRACE(EvpnStateCreate, sg.source.to_string(), sg.group.to_string());
962  return state;
963 }
964 
966  EvpnStatePtr evpn_state = GetState(sg);
967  if (evpn_state)
968  return evpn_state;
969  evpn_state = CreateState(sg);
970  assert(evpn_state);
971  return evpn_state;
972 }
973 
976  rt->GetPrefix().group());
977  return LocateState(sg);
978 }
979 
980 //
981 // Disable processing of the update list.
982 // For testing only.
983 //
985  mac_update_trigger_->set_disable();
986 }
987 
988 //
989 // Enable processing of the update list.
990 // For testing only.
991 //
993  mac_update_trigger_->set_enable();
994 }
995 
996 //
997 // Return true if the EvpnManagerPartition is empty i.e. it has no local
998 // or remote EvpnMcastNodes and no MAC routes that need to be updated.
999 //
1001  if (!local_mcast_node_list_.empty())
1002  return false;
1003  if (!remote_mcast_node_list_.empty())
1004  return false;
1005  if (!mac_update_list_.empty())
1006  return false;
1007  assert(leaf_node_list_.empty());
1008  assert(replicator_node_list_.empty());
1009  assert(regular_node_list_.empty());
1010  assert(ir_client_node_list_.empty());
1011  return true;
1012 }
1013 
1014 //
1015 // Return the BgpServer for the EvpnManagerPartition.
1016 //
1018  return evpn_manager_->server();
1019 }
1020 
1021 //
1022 // Return the EvpnTable for the EvpnManagerPartition.
1023 //
1025  return evpn_manager_->table();
1026 }
1027 
1028 //
1029 // Constructor for EvpnManager.
1030 //
1032  : table_(table),
1033  listener_id_(DBTable::kInvalidId),
1034  segment_delete_trigger_(new TaskTrigger(
1035  boost::bind(&EvpnManager::ProcessSegmentDeleteSet, this),
1036  TaskScheduler::GetInstance()->GetTaskId("bgp::EvpnSegment"), 0)),
1037  segment_update_trigger_(new TaskTrigger(
1038  boost::bind(&EvpnManager::ProcessSegmentUpdateSet, this),
1039  TaskScheduler::GetInstance()->GetTaskId("bgp::EvpnSegment"), 0)),
1040  table_delete_ref_(this, table->deleter()) {
1041  deleter_.reset(new DeleteActor(this));
1042  db_states_count_ = 0;
1043 }
1044 
1045 //
1046 // Destructor for EvpnManager.
1047 //
1049  assert(segment_map_.empty());
1050  assert(segment_delete_set_.empty());
1051  assert(segment_update_set_.empty());
1052 }
1053 
1054 //
1055 // Initialize the EvpnManager. We allocate the EvpnManagerPartitions
1056 // and register a DBListener for the EvpnTable.
1057 //
1059  AllocPartitions();
1061  boost::bind(&EvpnManager::RouteListener, this, _1, _2),
1062  "EvpnManager");
1063  ermvpn_table_ = dynamic_cast<ErmVpnTable *>(
1065  if (ermvpn_table_)
1067  boost::bind(&EvpnManager::ErmVpnRouteListener, this, _1, _2),
1068  "EvpnManager");
1069 }
1070 
1071 //
1072 // Terminate the EvpnManager. We free the EvpnManagerPartitions
1073 // and unregister from the EvpnTable.
1074 //
1076  CHECK_CONCURRENCY("bgp::Config");
1082  }
1083  FreePartitions();
1084 }
1085 
1086 //
1087 // Allocate the EvpnManagerPartitions.
1088 //
1090  for (int part_id = 0; part_id < DB::PartitionCount(); part_id++) {
1091  partitions_.push_back(new EvpnManagerPartition(this, part_id));
1092  }
1093 }
1094 
1095 //
1096 // Free the EvpnManagerPartitions.
1097 //
1100 }
1101 
1102 //
1103 // Disable processing of the update lists in all partitions.
1104 // For testing only.
1105 //
1107  for (int part_id = 0; part_id < DB::PartitionCount(); part_id++) {
1108  partitions_[part_id]->DisableMacUpdateProcessing();
1109  }
1110 }
1111 
1112 //
1113 // Enable processing of the update lists in all partitions.
1114 // For testing only.
1115 //
1117  for (int part_id = 0; part_id < DB::PartitionCount(); part_id++) {
1118  partitions_[part_id]->EnableMacUpdateProcessing();
1119  }
1120 }
1121 
1122 //
1123 // Get the EvpnManagerPartition for the given partition id.
1124 //
1126  return partitions_[part_id];
1127 }
1128 
1129 //
1130 // Get the DBTablePartition for the EvpnTable for given partition id.
1131 //
1133  return static_cast<DBTablePartition *>(table_->GetTablePartition(part_id));
1134 }
1135 
1136 //
1137 // Construct export state for the given EvpnRoute. Note that the route
1138 // only needs to be exported to the IPeer from which it was learnt.
1139 //
1141  CHECK_CONCURRENCY("db::DBTable");
1142 
1143  DBState *dbstate = route->GetState(table_, listener_id_);
1144  EvpnLocalMcastNode *local_node =
1145  dynamic_cast<EvpnLocalMcastNode *>(dbstate);
1146 
1147  if (!local_node)
1148  return NULL;
1149 
1150  return local_node->GetUpdateInfo(route);
1151 }
1152 
1154  return table_->server();
1155 }
1156 
1157 //
1158 // Find or create the EvpnSegment for the given EthernetSegmentId.
1159 //
1161  assert(!esi.IsZero());
1162  tbb::spin_rw_mutex::scoped_lock write_lock(segment_rw_mutex_, true);
1163  SegmentMap::iterator loc = segment_map_.find(esi);
1164  EvpnSegment *segment = (loc != segment_map_.end()) ? loc->second : NULL;
1165  if (!segment) {
1166  segment = new EvpnSegment(this, esi);
1167  segment_map_.insert(esi, segment);
1168  }
1169  return segment;
1170 }
1171 
1172 //
1173 // Find the EvpnSegment for the given EthernetSegmentId.
1174 //
1176  assert(!esi.IsZero());
1177  tbb::spin_rw_mutex::scoped_lock read_lock(segment_rw_mutex_, false);
1178  SegmentMap::iterator loc = segment_map_.find(esi);
1179  return (loc != segment_map_.end()) ? loc->second : NULL;
1180 }
1181 
1182 //
1183 // Trigger deletion of the given EvpnSegment.
1184 // The EvpnSegment is added to a set of EvpnSegments that can potentially
1185 // be deleted. This method can be invoked from multiple db::DBTable tasks
1186 // in parallel when a MAC routes are removed from the dependency list in an
1187 // EvpnSegment. Hence we ensure exclusive access using a write lock.
1188 //
1189 // The list is processed from the context of bgp::EvpnSegment task which is
1190 // mutually exclusive with db::DBTable task.
1191 //
1193  CHECK_CONCURRENCY("db::DBTable", "bgp::EvpnSegment");
1194 
1195  tbb::spin_rw_mutex::scoped_lock write_lock(segment_rw_mutex_, true);
1196  segment_delete_set_.insert(segment);
1197  segment_delete_trigger_->Set();
1198 }
1199 
1200 //
1201 // Process the set of EvpnSegments that can potentially be deleted.
1202 // Remove the EvpnSegment from the map and destroy if it's fine to
1203 // to delete the EvpnSegment.
1204 //
1206  CHECK_CONCURRENCY("bgp::EvpnSegment");
1207 
1208  BOOST_FOREACH(EvpnSegment *segment, segment_delete_set_) {
1209  if (segment->MayDelete()) {
1210  segment_update_set_.erase(segment);
1211  EthernetSegmentId esi = segment->esi();
1212  segment_map_.erase(esi);
1213  }
1214  }
1215  segment_delete_set_.clear();
1216  RetryDelete();
1217  return true;
1218 }
1219 
1220 //
1221 // Disable processing of the delete list.
1222 // For testing only.
1223 //
1225  segment_delete_trigger_->set_disable();
1226 }
1227 
1228 //
1229 // Enable processing of the delete list.
1230 // For testing only.
1231 //
1233  segment_delete_trigger_->set_enable();
1234 }
1235 
1236 //
1237 // Trigger update of the given EvpnSegment.
1238 // The EvpnSegment is added to a set of EvpnSegments for which updates
1239 // need triggered. This method is called in the context of db::DBTable
1240 // task and a task instance of 0 since all AutoDisocvery routes always
1241 // get sharded to partition 0.
1242 //
1243 // The set is processed in the context of bgp::EvpnSegment task, which
1244 // is mutually exclusive with db::DBTable task.
1245 //
1247  CHECK_CONCURRENCY("db::DBTable");
1248 
1249  segment_update_set_.insert(segment);
1250  segment_update_trigger_->Set();
1251 }
1252 
1253 //
1254 // Process the set of EvpnSegments that need to be updated.
1255 //
1256 // Go through each EvpnSegment and update it's PE list. Trigger updates
1257 // of all it's dependent MAC routes if there's a change in the PE list.
1258 //
1260  CHECK_CONCURRENCY("bgp::EvpnSegment");
1261 
1262  BOOST_FOREACH(EvpnSegment *segment, segment_update_set_) {
1263  EvpnRoute *esi_ad_route = segment->esi_ad_route();
1264  bool changed = segment->UpdatePeList();
1265  if (changed)
1266  segment->TriggerMacRouteUpdate();
1267  if (!esi_ad_route->IsValid()) {
1268  segment->clear_esi_ad_route();
1269  esi_ad_route->ClearState(table_, listener_id_);
1270  TriggerSegmentDelete(segment);
1271  }
1272  }
1273  segment_update_set_.clear();
1274  RetryDelete();
1275  return true;
1276 }
1277 
1278 //
1279 // Disable processing of the update list.
1280 // For testing only.
1281 //
1283  segment_update_trigger_->set_disable();
1284 }
1285 
1286 //
1287 // Enable processing of the update list.
1288 // For testing only.
1289 //
1291  segment_update_trigger_->set_enable();
1292 }
1293 
1294 //
1295 // DBListener callback handler for AutoDisocvery routes in the EvpnTable.
1296 //
1298  CHECK_CONCURRENCY("db::DBTable");
1299 
1300  DBState *dbstate = route->GetState(table_, listener_id_);
1301  if (!dbstate) {
1302  // We have no previous DBState for this route.
1303  // Bail if the route is not valid.
1304  if (!route->IsValid())
1305  return;
1306 
1307  // Locate the EvpnSegment and associate it with the route.
1308  // Trigger an update of EvpnSegment so that it's PE list
1309  // gets updated.
1310  EvpnSegment *segment = LocateSegment(route->GetPrefix().esi());
1311  segment->set_esi_ad_route(route);
1312  route->SetState(table_, listener_id_, segment);
1313  TriggerSegmentUpdate(segment);
1314  } else {
1315  // Trigger an update of EvpnSegment so that it's PE list
1316  // gets updated.
1317  EvpnSegment *segment = dynamic_cast<EvpnSegment *>(dbstate);
1318  assert(segment);
1319  TriggerSegmentUpdate(segment);
1320  }
1321 }
1322 
1323 //
1324 // DBListener callback handler for MacAdvertisement routes in the EvpnTable.
1325 //
1327  EvpnManagerPartition *partition, EvpnRoute *route) {
1328  CHECK_CONCURRENCY("db::DBTable");
1329 
1330  DBState *dbstate = route->GetState(table_, listener_id_);
1331  if (!dbstate) {
1332  // We have no previous DBState for this route.
1333  // Bail if the route is not valid or if it doesn't have an ESI.
1334  if (!route->IsValid())
1335  return;
1336  const BgpPath *path = route->BestPath();
1337  if (path->GetAttr()->esi().IsZero())
1338  return;
1339 
1340  // Create a new EvpnMacState and associate it with the route.
1341  EvpnMacState *mac_state = new EvpnMacState(this, route);
1342  route->SetState(table_, listener_id_, mac_state);
1343 
1344  // Locate the EvpnSegment and add the MAC route as a dependent
1345  // of the EvpnSegment.
1346  EvpnSegment *segment = LocateSegment(path->GetAttr()->esi());
1347  mac_state->set_segment(segment);
1348  segment->AddMacRoute(partition->part_id(), route);
1349  partition->TriggerMacRouteUpdate(route);
1350  } else {
1351  EvpnMacState *mac_state = dynamic_cast<EvpnMacState *>(dbstate);
1352  assert(mac_state);
1353  EvpnSegment *segment = mac_state->segment();
1354 
1355  // Handle change in the ESI and update the dependency on the
1356  // EvpnSegment as appropriate.
1357  // Note that the DBState on the EvpnRoute doesn't get cleared
1358  // here. That only happens when aliasing for the route is being
1359  // processed.
1360  const BgpPath *path = route->BestPath();
1361  if (!route->IsValid() || (path && path->GetAttr()->esi().IsZero())) {
1362  if (segment) {
1363  segment->DeleteMacRoute(partition->part_id(), route);
1364  mac_state->clear_segment();
1365  }
1366  } else if (!segment && !path->GetAttr()->esi().IsZero()) {
1367  segment = LocateSegment(path->GetAttr()->esi());
1368  mac_state->set_segment(segment);
1369  segment->AddMacRoute(partition->part_id(), route);
1370  } else if (segment && segment->esi() != path->GetAttr()->esi()) {
1371  segment->DeleteMacRoute(partition->part_id(), route);
1372  mac_state->clear_segment();
1373  segment = LocateSegment(path->GetAttr()->esi());
1374  mac_state->set_segment(segment);
1375  segment->AddMacRoute(partition->part_id(), route);
1376  }
1377  partition->TriggerMacRouteUpdate(route);
1378  }
1379 }
1380 
1381 //
1382 // DBListener callback handler for InclusiveMulticast routes in the EvpnTable.
1383 //
1385  EvpnManagerPartition *partition, EvpnRoute *route) {
1386  CHECK_CONCURRENCY("db::DBTable");
1387 
1388  DBState *dbstate = route->GetState(table_, listener_id_);
1389  if (!dbstate) {
1390  // We have no previous DBState for this route.
1391  // Bail if the route is not valid.
1392  if (!route->IsValid())
1393  return;
1394 
1395  // Create a new EvpnMcastNode and associate it with the route.
1396  EvpnMcastNode *node;
1397  if (route->GetPrefix().type() == EvpnPrefix::MacAdvertisementRoute) {
1398  node = new EvpnLocalMcastNode(partition, route);
1399  } else {
1400  node = new EvpnRemoteMcastNode(partition, route);
1401  }
1402  partition->AddMcastNode(node, route);
1403  route->SetState(table_, listener_id_, node);
1404  } else {
1405  EvpnMcastNode *node = dynamic_cast<EvpnMcastNode *>(dbstate);
1406  assert(node);
1407 
1408  if (!route->IsValid()) {
1409  // Delete the EvpnMcastNode associated with the route.
1410  route->ClearState(table_, listener_id_);
1411  partition->DeleteMcastNode(node, route);
1412  delete node;
1413  } else if (node->UpdateAttributes(route)) {
1414  // Update the EvpnMcastNode associated with the route.
1415  partition->UpdateMcastNode(node, route);
1416  }
1417  }
1418 }
1419 
1420 //
1421 // DBListener callback handler for SelectiveMulticast routes in the EvpnTable.
1422 //
1424  EvpnManagerPartition *partition, EvpnRoute *route) {
1425 
1426  CHECK_CONCURRENCY("db::DBTable");
1427  EvpnMcastNode *dbstate = dynamic_cast<EvpnMcastNode *>(
1428  route->GetState(table_, listener_id_));
1429  bool is_usable = route->IsUsable();
1430  bool is_deleted = route->IsDeleted();
1431  bool checkErmvpnRoute = false;
1432  if (route->BestPath()) {
1433  checkErmvpnRoute = route->BestPath()->GetFlags() &
1435  }
1436  if ((!is_usable && !checkErmvpnRoute) || is_deleted) {
1437  if (!dbstate)
1438  return;
1439 
1440  EvpnStatePtr evpn_state = partition->GetState(route);
1441  if (evpn_state)
1442  evpn_state->smet_routes().erase(route);
1443  EVPN_RT_LOG(route, "Processed Smet route deletion");
1444  ClearDBState(route);
1445  partition->NotifyForestNode(route, ermvpn_table());
1446  partition->DeleteMcastNode(dbstate, route);
1447  delete dbstate;
1448  return;
1449  }
1450 
1451  EvpnStatePtr evpn_state = partition->LocateState(route);
1452  assert(evpn_state);
1453  evpn_state->smet_routes().insert(route);
1454  BgpPath *path = const_cast<BgpPath *>(route->BestPath());
1455  if (path && path->CheckErmVpn()) {
1456  ErmVpnRoute *global_rt = evpn_state->global_ermvpn_tree_rt();
1457  Ip4Address address;
1458  bool nh_found = partition->GetForestNodeAddress(global_rt, &address);
1459  if (nh_found) {
1460  BgpAttrPtr attr = path->GetAttr();
1461  BgpAttrPtr new_attr = partition->server()->attr_db()->
1462  ReplaceNexthopAndLocate(attr.get(), address);
1463  path->SetAttr(new_attr, attr);
1464  path->ResetCheckErmVpn();
1465  partition->NotifyForestNode(route, ermvpn_table());
1466  }
1467  }
1468 
1469  if (!dbstate) {
1470  // Create a new DBState and associate it with the route.
1471  EvpnMcastNode *node;
1472  if (route->GetPrefix().ip_address() ==
1474  node = new EvpnLocalMcastNode(partition, route, evpn_state);
1475  } else {
1476  node = new EvpnRemoteMcastNode(partition, route, evpn_state);
1477  }
1478  SetDBState(route, node);
1479  partition->AddMcastNode(node, route);
1480  EVPN_RT_LOG(route, "Processed Smet route creation");
1481  }
1482 }
1483 
1485  ErmVpnTable *table) {
1486  const Ip4Address &source = route->GetPrefix().source().to_v4();
1487  const Ip4Address &group = route->GetPrefix().group().to_v4();
1488  if (table->tree_manager())
1489  table->tree_manager()->NotifyForestNode(part_id_, source, group);
1490 }
1491 
1492 // Set DB State and update count.
1494  route->SetState(table_, listener_id_, dbstate);
1495  db_states_count_++;
1496 }
1497 
1498 // Create DB State and update count. If there is no DB State associated in the
1499 // table, resume table deletion if the deletion was pending.
1501  route->ClearState(table_, listener_id_);
1502  assert(db_states_count_);
1503  db_states_count_--;
1504 
1505  // Retry deletion now as there is no more attached db state in the table.
1506  if (!db_states_count_ && deleter_->IsDeleted())
1507  deleter_->RetryDelete();
1508 }
1509 
1510 // Check whether an ErmVpnRoute is locally originated GlobalTreeRoute.
1512  ErmVpnRoute *ermvpn_route) const {
1513  if (!ermvpn_route || !ermvpn_route->IsUsable())
1514  return false;
1515  if (!ermvpn_table()->tree_manager())
1516  return false;
1517  if (ermvpn_table()->tree_manager()->begin() ==
1518  ermvpn_table()->tree_manager()->end())
1519  return false;
1520  ErmVpnRoute *global_rt = ermvpn_table()->tree_manager()->
1521  GetGlobalTreeRootRoute(
1522  ermvpn_route->GetPrefix().source(),
1523  ermvpn_route->GetPrefix().group());
1524  return (global_rt && global_rt == ermvpn_route);
1525 }
1526 
1527 // ErmVpnTable route listener callback function.
1528 //
1529 // Process changes (create/update/delete) to GlobalErmVpnRoute in vrf.ermvpn.0
1531  DBEntryBase *db_entry) {
1532  CHECK_CONCURRENCY("db::DBTable");
1533 
1534  ErmVpnRoute *ermvpn_route = dynamic_cast<ErmVpnRoute *>(db_entry);
1535  assert(ermvpn_route);
1536 
1537  // We only care about global tree routes for evpn stitching.
1538  if (ermvpn_route->GetPrefix().type() != ErmVpnPrefix::GlobalTreeRoute) {
1539  return;
1540  }
1541 
1542  EvpnMcastNode *dbstate = dynamic_cast<EvpnMcastNode *>(
1543  ermvpn_route->GetState(ermvpn_table(), ermvpn_listener_id()));
1544 
1545  // Handle GlobalTreeRoute route deletion.
1546  if (!IsUsableGlobalTreeRootRoute(ermvpn_route)) {
1547  // Ignore if there is no DB State associated with route.
1548  if (!dbstate)
1549  return;
1550  EvpnStatePtr evpn_state = dbstate->state();
1551  evpn_state->set_global_ermvpn_tree_rt(NULL);
1552 
1553  // Notify all received smet routes for PMSI re-computation.
1554  // Since usable global ermvpn is no longer available, any advertised
1555  // smet routes must now be withdrawn.
1556  BOOST_FOREACH(EvpnRoute *route, evpn_state->smet_routes()) {
1557  BgpPath *path = const_cast<BgpPath *>(route->BestPath());
1558  if (path && (path->GetPathId() == 0)) {
1559  path->SetCheckErmVpn();
1560  }
1561  route->Notify();
1562  }
1563  ermvpn_route->ClearState(ermvpn_table(), ermvpn_listener_id());
1564  EVPN_ERMVPN_RT_LOG(ermvpn_route,
1565  "Processed EVPN GlobalErmVpnRoute deletion");
1566  delete dbstate;
1567  return;
1568  }
1569 
1570  // Set DB State in the route if not already done so before.
1571  EvpnManagerPartition *partition = GetPartition(tpart->index());
1572  EvpnStatePtr evpn_state;
1573  if (!dbstate) {
1574  EvpnState::SG sg(ermvpn_route);
1575  evpn_state = partition->LocateState(sg);
1576  dbstate = new EvpnLocalMcastNode(partition, NULL, evpn_state);
1577  ermvpn_route->SetState(ermvpn_table(), ermvpn_listener_id(), dbstate);
1578  } else {
1579  evpn_state = dbstate->state();
1580  }
1581 
1582  // Note down current usable ermvpn route for stitching to evpn.
1583  dbstate->state()->set_global_ermvpn_tree_rt(ermvpn_route);
1584 
1585  // Notify all originated Type6 routes.
1586  BOOST_FOREACH(EvpnRoute *route, evpn_state->smet_routes()) {
1587  route->Notify();
1588  }
1589  EVPN_ERMVPN_RT_LOG(ermvpn_route,
1590  "Processed EVPN GlobalErmVpnRoute creation");
1591 }
1592 
1593 //
1594 // DBListener callback handler for the EvpnTable.
1595 //
1597  CHECK_CONCURRENCY("db::DBTable");
1598 
1599  EvpnManagerPartition *partition = GetPartition(tpart->index());
1600  EvpnRoute *route = dynamic_cast<EvpnRoute *>(db_entry);
1601  assert(route);
1602 
1603  switch (route->GetPrefix().type()) {
1606  break;
1608  if (route->GetPrefix().mac_addr().IsBroadcast()) {
1609  InclusiveMulticastRouteListener(partition, route);
1610  } else {
1611  MacAdvertisementRouteListener(partition, route);
1612  }
1613  break;
1615  InclusiveMulticastRouteListener(partition, route);
1616  break;
1618  SelectiveMulticastRouteListener(partition, route);
1619  break;
1620  default:
1621  break;
1622  }
1623 }
1624 
1625 //
1626 // Fill information for introspect command.
1627 // Note that all IM routes are always in partition 0.
1628 //
1629 void EvpnManager::FillShowInfo(ShowEvpnTable *sevt) const {
1630  CHECK_CONCURRENCY("db::DBTable");
1631 
1632  vector<string> regular_nves;
1633  vector<string> ar_replicators;
1634  vector<ShowEvpnMcastLeaf> ar_leafs;
1635  EvpnManagerPartition::EvpnMcastNodeList::const_iterator it =
1636  partitions_[0]->remote_mcast_node_list()->begin();
1637  for (; it != partitions_[0]->remote_mcast_node_list()->end(); it++) {
1638  BOOST_FOREACH(const EvpnMcastNode *node, it->second) {
1639  if (node->assisted_replication_leaf()) {
1640  ShowEvpnMcastLeaf leaf;
1641  leaf.set_address(node->address().to_string());
1642  leaf.set_replicator(node->replicator_address().to_string());
1643  ar_leafs.push_back(leaf);
1644  } else if (node->assisted_replication_supported()) {
1645  ar_replicators.push_back(node->address().to_string());
1646  } else if (node->edge_replication_not_supported()) {
1647  regular_nves.push_back(node->address().to_string());
1648  }
1649  }
1650  }
1651 
1652  sort(regular_nves.begin(), regular_nves.end());
1653  sort(ar_replicators.begin(), ar_replicators.end());
1654  sort(ar_leafs.begin(), ar_leafs.end());
1655  sevt->set_regular_nves(regular_nves);
1656  sevt->set_ar_replicators(ar_replicators);
1657  sevt->set_ar_leafs(ar_leafs);
1658 }
1659 
1660 //
1661 // Check if the EvpnManager can be deleted. This can happen only if all the
1662 // EvpnManagerPartitions are empty.
1663 //
1665  CHECK_CONCURRENCY("bgp::Config");
1666 
1667  if (!segment_map_.empty())
1668  return false;
1669 
1670  if (!segment_update_set_.empty())
1671  return false;
1672  if (segment_update_trigger_->IsSet())
1673  return false;
1674 
1675  if (!segment_delete_set_.empty())
1676  return false;
1677  if (segment_delete_trigger_->IsSet())
1678  return false;
1679 
1680  BOOST_FOREACH(const EvpnManagerPartition *partition, partitions_) {
1681  if (!partition->empty())
1682  return false;
1683  if (!partition->states().empty())
1684  return false;
1685  }
1686  if (db_states_count_)
1687  return false;
1688  return true;
1689 }
1690 
1691 //
1692 // Initiate shutdown for the EvpnManager.
1693 //
1695  CHECK_CONCURRENCY("bgp::Config");
1696 }
1697 
1698 //
1699 // Trigger deletion of the EvpnManager and propagate the delete to any
1700 // dependents.
1701 //
1703  deleter_->Delete();
1704 }
1705 
1706 //
1707 // Attempt to enqueue a delete for the EvpnManager.
1708 //
1710  if (!deleter()->IsDeleted())
1711  return;
1712  deleter()->RetryDelete();
1713 }
1714 
1715 //
1716 // Return the LifetimeActor for the EvpnManager.
1717 //
1719  return deleter_.get();
1720 }
1721 
1722 EvpnState::SG::SG(const Ip4Address &source, const Ip4Address &group) :
1723  source(IpAddress(source)), group(IpAddress(group)) {
1724 }
1725 
1727  source(route->GetPrefix().source()),
1728  group(route->GetPrefix().group()) {
1729 }
1730 
1732  source(route->GetPrefix().source()), group(route->GetPrefix().group()) {
1733 }
1734 
1735 EvpnState::SG::SG(const IpAddress &source, const IpAddress &group) :
1736  source(source), group(group) {
1737 }
1738 
1739 bool EvpnState::SG::operator<(const SG &other) const {
1740  if (source < other.source)
1741  return true;
1742  if (source > other.source)
1743  return false;
1744  if (group < other.group)
1745  return true;
1746  if (group > other.group)
1747  return false;
1748  return false;
1749 }
1750 
1752  return sg_;
1753 }
1754 
1757 }
1758 
1760  return global_ermvpn_tree_rt_;
1761 }
1762 
1764  return global_ermvpn_tree_rt_;
1765 }
void SetCheckErmVpn()
Definition: bgp_path.h:140
tbb::spin_rw_mutex segment_rw_mutex_
Definition: bgp_evpn.h:745
bool operator==(const RemotePe &rhs) const
Equality operator for EvpnSegment::RemotePe. Do not compare esi_valid and single_active fields since ...
Definition: bgp_evpn.cc:573
RemotePeList pe_list_
Definition: bgp_evpn.h:269
BgpAttrPtr ReplaceLeafOListAndLocate(const BgpAttr *attr, const BgpOListSpec *leaf_olist_spec)
Definition: bgp_attr.cc:1387
Elements elements
Definition: bgp_attr.h:694
EvpnSegment * segment()
Definition: bgp_evpn.h:297
LifetimeActor * deleter()
Return the LifetimeActor for the EvpnManager.
Definition: bgp_evpn.cc:1718
bool ProcessSegmentUpdateSet()
Process the set of EvpnSegments that need to be updated.
Definition: bgp_evpn.cc:1259
const Ip4Address identifier() const
Definition: bgp_attr.h:384
const EvpnState::StatesMap & states() const
Definition: bgp_evpn.h:514
EvpnMcastNode(EvpnManagerPartition *partition, EvpnRoute *route, uint8_t type)
Constructor for EvpnMcastNode. The type indicates whether this is a local or remote EvpnMcastNode...
Definition: bgp_evpn.cc:79
const EvpnMcastNodeList & remote_mcast_node_list() const
Definition: bgp_evpn.h:464
tbb::atomic< int > db_states_count_
Definition: bgp_evpn.h:743
void Shutdown()
Initiate shutdown for the EvpnManager.
Definition: bgp_evpn.cc:1694
EvpnSegment * segment_
Definition: bgp_evpn.h:319
const IpAddress & nexthop() const
Definition: bgp_attr.h:886
void STLDeleteValues(Container *container)
Definition: util.h:101
boost::intrusive_ptr< EvpnState > EvpnStatePtr
Definition: bgp_evpn.h:34
BgpTable * GetTable(Address::Family fmly)
bool UpdatePeList()
Update the PE list for this EvpnSegment. This should be called when the AutoDisocvery route is update...
Definition: bgp_evpn.cc:458
const BgpPath * BestPath() const
Definition: bgp_route.cc:46
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
const ErmVpnPrefix & GetPrefix() const
Definition: ermvpn_route.h:81
bool CheckErmVpn() const
Definition: bgp_path.h:136
This class represents the EvpnManager state associated with a MAC route.
Definition: bgp_evpn.h:287
RibOutAttr roattr
Definition: bgp_update.h:100
ErmVpnRoute * global_ermvpn_tree_rt_
Definition: bgp_evpn.h:399
Ip4Address replicator_address() const
Definition: bgp_evpn.h:78
void ErmVpnRouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
ErmVpnTable route listener callback function.
Definition: bgp_evpn.cc:1530
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
bool ProcessMacRouteAliasing()
Update aliased BgpPaths for the EvpnRoute based on the remote PEs for the EvpnSegment. Return true if the list of aliased paths is modified.
Definition: bgp_evpn.cc:662
BgpServer * server()
Return the BgpServer for the EvpnManagerPartition.
Definition: bgp_evpn.cc:1017
void TriggerMacRouteUpdate()
Trigger an update of all dependent MAC routes for this EvpnSegment. Note that the bgp::EvpnSegment ta...
Definition: bgp_evpn.cc:441
bool empty() const
Return true if the EvpnManagerPartition is empty i.e. it has no local or remote EvpnMcastNodes and no...
Definition: bgp_evpn.cc:1000
std::map< SG, EvpnState * > StatesMap
Definition: bgp_evpn.h:365
bool set_synchronize(const SetType *set1, const SetType *set2, AddFunctor add_fn, DelFunctor del_fn)
Definition: set_util.h:21
uint32_t tag() const
boost::scoped_ptr< DeleteActor > deleter_
Definition: bgp_evpn.h:752
SegmentSet segment_delete_set_
Definition: bgp_evpn.h:747
EvpnManager(EvpnTable *table)
Definition: bgp_evpn.cc:1031
void AddInclusiveMulticastRoute()
Add Inclusive Multicast route for this EvpnLocalMcastNode. The attributes are based on the Broadcast ...
Definition: bgp_evpn.cc:214
DBEntry * Find(const DBEntry *entry)
bool ProcessSegmentDeleteSet()
Process the set of EvpnSegments that can potentially be deleted. Remove the EvpnSegment from the map ...
Definition: bgp_evpn.cc:1205
EvpnMcastNodeList leaf_node_list_
Definition: bgp_evpn.h:526
void set_segment(EvpnSegment *segment)
Definition: bgp_evpn.h:299
void AutoDiscoveryRouteListener(EvpnRoute *route)
DBListener callback handler for AutoDisocvery routes in the EvpnTable.
Definition: bgp_evpn.cc:1297
bool RemoveMcastNodeFromList(EvpnState::SG &sg, EvpnMcastNode *node, EvpnMcastNodeList *list)
Delete an EvpnMcastNode from the EvpnManagerPartition.
Definition: bgp_evpn.cc:807
EvpnManagerPartition * GetPartition(size_t part_id)
Get the EvpnManagerPartition for the given partition id.
Definition: bgp_evpn.cc:1125
EvpnMcastNodeList local_mcast_node_list_
Definition: bgp_evpn.h:523
tbb::atomic< int > refcount_
Definition: bgp_evpn.h:403
bool MayDelete() const
Return true if it&#39;s safe to delete this EvpnSegment.
Definition: bgp_evpn.cc:540
void clear_segment()
Definition: bgp_evpn.h:300
RoutingInstance * routing_instance()
Definition: bgp_table.h:148
bool IsDeleted() const
Definition: db_entry.h:49
This class represents (in the context of an EVPN instance) a local vRouter that&#39;s connected to a cont...
Definition: bgp_evpn.h:124
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
EvpnManager * evpn_manager_
Definition: bgp_evpn.cc:72
uint8_t type() const
Definition: bgp_evpn.h:74
BgpAttrPtr attr_
Definition: bgp_evpn.h:94
const_iterator end() const
Definition: bgp_evpn.h:228
DBTablePartition * table_partition_
Definition: bgp_evpn.h:521
#define BGP_LOG_ROUTE(table, peer, route, arg)
Definition: bgp_log.h:247
virtual void Shutdown()
Definition: bgp_evpn.cc:63
EvpnRoute * route_
Definition: bgp_evpn.h:318
const uint32_t GetPathId() const
Definition: bgp_path.h:78
void DisableMacUpdateProcessing()
Disable processing of the update lists in all partitions. For testing only.
Definition: bgp_evpn.cc:1106
bool assisted_replication_leaf_
Definition: bgp_evpn.h:100
RemotePeList::const_iterator const_iterator
Definition: bgp_evpn.h:225
bool assisted_replication_supported_
Definition: bgp_evpn.h:99
void EnableMacUpdateProcessing()
Enable processing of the update lists in all partitions. For testing only.
Definition: bgp_evpn.cc:1116
void FreePartitions()
Free the EvpnManagerPartitions.
Definition: bgp_evpn.cc:1098
#define EVPN_TRACE(type,...)
Definition: bgp_evpn.h:803
void SetDBState(EvpnRoute *route, EvpnMcastNode *dbstate)
Set DB State and update count.
Definition: bgp_evpn.cc:1493
EvpnMacState(EvpnManager *evpn_manager, EvpnRoute *route)
Definition: bgp_evpn.cc:588
virtual ~EvpnState()
Definition: bgp_evpn.cc:40
const BgpPath * FindPath(BgpPath::PathSource src) const
Definition: bgp_route.cc:145
void NotifyReplicatorNodeRoutes()
Go through all replicator EvpnMcastNodes and notify associated Broadcast MAC route.
Definition: bgp_evpn.cc:749
void ManagedDelete()
Trigger deletion of the EvpnManager and propagate the delete to any dependents.
Definition: bgp_evpn.cc:1702
const ErmVpnTable * table() const
Definition: bgp_evpn.cc:45
void AddAliasedPath(AliasedPathList::const_iterator it)
Add the BgpPath specified by the iterator to the aliased path list. Also inserts the BgpPath to the B...
Definition: bgp_evpn.cc:604
void set_global_ermvpn_tree_rt(ErmVpnRoute *global_ermvpn_tree_rt)
Definition: bgp_evpn.cc:1755
void AddMacRoute(size_t part_id, EvpnRoute *route)
Add the given MAC route as a dependent of this EvpnSegment.
Definition: bgp_evpn.cc:419
bool edge_replication_not_supported() const
Definition: bgp_evpn.h:79
void clear_esi_ad_route()
Definition: bgp_evpn.h:257
void Delete(DBEntryBase *)
void AllocPartitions()
Allocate the EvpnManagerPartitions.
Definition: bgp_evpn.cc:1089
SG(const Ip4Address &source, const Ip4Address &group)
Definition: bgp_evpn.cc:1722
uint32_t GetFlags() const
Definition: bgp_path.h:100
Ip4Address address_
Definition: bgp_evpn.h:96
Definition: ipeer.h:186
int ermvpn_listener_id() const
Definition: bgp_evpn.h:611
EvpnManager * evpn_manager_
Definition: bgp_evpn.h:519
void Unregister(ListenerId listener)
Definition: db_table.cc:186
virtual void Destroy()
Definition: bgp_evpn.cc:67
void NotifyIrClientNodeRoutes(bool exclude_edge_replication_supported)
Go through all ingress replication client EvpnMcastNodes and notify the associated Broadcast MAC rout...
Definition: bgp_evpn.cc:762
EvpnTable * table_
Definition: bgp_evpn.h:739
const_iterator end() const
const EvpnTable * table() const
Return the EvpnTable for the EvpnManagerPartition.
Definition: bgp_evpn.cc:1024
void RetryDelete()
Definition: lifetime.cc:71
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
const McastTreeManager * tree_manager() const
Definition: ermvpn_table.h:64
bool IsUsable() const
Definition: bgp_route.cc:324
This class represents (in the context of an EVPN instance) a remote vRouter or PE discovered via BGP...
Definition: bgp_evpn.h:170
#define BGP_LOG_STR(obj, level, flags, arg)
Definition: bgp_log.h:89
virtual void TriggerUpdate()
Handle update of EvpnRemoteMcastNode.
Definition: bgp_evpn.cc:394
EvpnSegment * FindSegment(const EthernetSegmentId &esi)
Find the EvpnSegment for the given EthernetSegmentId.
Definition: bgp_evpn.cc:1175
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
EvpnMcastNodeList remote_mcast_node_list_
Definition: bgp_evpn.h:524
void SelectiveMulticastRouteListener(EvpnManagerPartition *partition, EvpnRoute *route)
DBListener callback handler for SelectiveMulticast routes in the EvpnTable.
Definition: bgp_evpn.cc:1423
Definition: db.h:24
DBTablePartition * GetTablePartition()
Get the DBTablePartition for the EvpnTable for our partition id.
Definition: bgp_evpn.cc:733
const SG & sg() const
Definition: bgp_evpn.cc:1751
uint32_t label() const
Definition: bgp_evpn.h:76
const IPeer * peer
Definition: bgp_evpn.h:218
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
EvpnStatePtr state()
Definition: bgp_evpn.h:71
uint8_t type() const
Definition: ermvpn_route.h:56
IpAddress source
Definition: bgp_evpn.h:361
virtual void Initialize()
Initialize the EvpnManager. We allocate the EvpnManagerPartitions and register a DBListener for the E...
Definition: bgp_evpn.cc:1058
virtual ~EvpnManager()
Definition: bgp_evpn.cc:1048
PathSource
Definition: bgp_path.h:37
RemotePe(const BgpPath *path)
Definition: bgp_evpn.cc:559
BgpServer * server()
Definition: bgp_evpn.cc:1153
const uint8_t tunnel_flags() const
Definition: bgp_attr.h:382
void DeleteMacRoute(size_t part_id, EvpnRoute *route)
Delete the given MAC route as a dependent of this EvpnSegment. Trigger deletion of the EvpnSegment if...
Definition: bgp_evpn.cc:429
EvpnState::StatesMap states_
Definition: bgp_evpn.h:521
uint8_t type
Definition: load_balance.h:109
void ClearDBState(EvpnRoute *route)
Create DB State and update count. If there is no DB State associated in the table, resume table deletion if the deletion was pending.
Definition: bgp_evpn.cc:1500
bool UpdateAttributes(EvpnRoute *route)
Update the label and attributes for a EvpnMcastNode. Return true if either of them changed...
Definition: bgp_evpn.cc:117
boost::scoped_ptr< TaskTrigger > segment_update_trigger_
Definition: bgp_evpn.h:750
const EthernetSegmentId & esi() const
Definition: bgp_evpn.h:252
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
DBListener callback handler for the EvpnTable.
Definition: bgp_evpn.cc:1596
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:187
void EnableSegmentDeleteProcessing()
Enable processing of the delete list. For testing only.
Definition: bgp_evpn.cc:1232
virtual void TriggerUpdate()
Handle update of EvpnLocalMcastNode.
Definition: bgp_evpn.cc:288
virtual void TriggerUpdate()=0
Handle update of EvpnLocalMcastNode.
void TriggerSegmentUpdate(EvpnSegment *segment)
Trigger update of the given EvpnSegment. The EvpnSegment is added to a set of EvpnSegments for which ...
Definition: bgp_evpn.cc:1246
const EthernetSegmentId & esi() const
Definition: bgp_attr.h:897
IpAddress source() const
std::map< SG, std::set< EvpnMcastNode * > > EvpnMcastNodeList
Definition: bgp_evpn.h:421
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
EvpnTable * table()
Definition: bgp_evpn.h:606
This class represents the EVPN manager for an EvpnTable in a VRF.
Definition: bgp_evpn.h:578
This class represents a remote EVPN segment that has 2 or more PEs that are multi-homed to it...
Definition: bgp_evpn.h:202
DeleteActor(EvpnManager *evpn_manager)
Definition: bgp_evpn.cc:51
void InclusiveMulticastRouteListener(EvpnManagerPartition *partition, EvpnRoute *route)
DBListener callback handler for InclusiveMulticast routes in the EvpnTable.
Definition: bgp_evpn.cc:1384
void DeleteAliasedPath(AliasedPathList::const_iterator it)
Delete the BgpPath specified by the iterator from the aliased path list. Also deletes the BgpPath fro...
Definition: bgp_evpn.cc:621
virtual const std::string & ToString() const =0
void TriggerMacRouteUpdate(EvpnRoute *route)
Add the given MAC route to the update list. This method gets called either when the MAC route itself ...
Definition: bgp_evpn.cc:884
uint8_t type() const
void EnableMacUpdateProcessing()
Enable processing of the update list. For testing only.
Definition: bgp_evpn.cc:992
#define CHECK_CONCURRENCY(...)
EvpnManager * manager_
Definition: bgp_evpn.h:402
virtual ~EvpnRemoteMcastNode()
Definition: bgp_evpn.cc:388
virtual bool MayDelete() const
Definition: bgp_evpn.cc:58
SegmentSet segment_update_set_
Definition: bgp_evpn.h:748
PartitionList partitions_
Definition: bgp_evpn.h:744
EvpnManager * evpn_manager_
Definition: bgp_evpn.h:264
IPeer * GetPeer()
Definition: bgp_path.h:76
EvpnSegment * LocateSegment(const EthernetSegmentId &esi)
Find or create the EvpnSegment for the given EthernetSegmentId.
Definition: bgp_evpn.cc:1160
void ResetCheckErmVpn()
Definition: bgp_path.h:139
uint16_t GetVrfId() const
Definition: rd.cc:52
#define EVPN_RT_LOG(rt,...)
Definition: bgp_evpn.h:787
EvpnMcastNodeList replicator_node_list_
Definition: bgp_evpn.h:525
Ip4Address replicator_address_
Definition: bgp_evpn.h:97
const std::string & name() const
Definition: db_table.h:110
virtual void Terminate()
Terminate the EvpnManager. We free the EvpnManagerPartitions and unregister from the EvpnTable...
Definition: bgp_evpn.cc:1075
EvpnManager * evpn_manager_
Definition: bgp_evpn.h:317
void AddMcastNode(EvpnMcastNode *node, EvpnRoute *route)
Add an EvpnMcastNode to the EvpnManagerPartition.
Definition: bgp_evpn.cc:780
void ClearDelete()
Definition: db_entry.h:48
uint32_t GetLabel() const
Definition: bgp_path.h:89
int listener_id() const
Definition: bgp_evpn.h:610
BgpPath * LocateAliasedPath(const EvpnSegment::RemotePe *remote_pe, uint32_t label)
Find or create the matching aliased BgpPath.
Definition: bgp_evpn.cc:637
int listener_id_
Definition: bgp_evpn.h:741
Ip4Address source() const
Definition: ermvpn_route.h:60
const EvpnMcastNodeList & leaf_node_list() const
Definition: bgp_evpn.h:470
void TriggerSegmentDelete(EvpnSegment *segment)
Trigger deletion of the given EvpnSegment. The EvpnSegment is added to a set of EvpnSegments that can...
Definition: bgp_evpn.cc:1192
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
const_iterator begin() const
Definition: bgp_evpn.h:227
void FillShowInfo(ShowEvpnTable *sevt) const
Fill information for introspect command. Note that all IM routes are always in partition 0...
Definition: bgp_evpn.cc:1629
const_iterator begin() const
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
Simple structure to hold &lt;S,G&gt;. Source as &quot;0.0.0.0&quot; can be used to encode &lt;*,G&gt; as well...
Definition: bgp_evpn.h:354
EvpnLocalMcastNode(EvpnManagerPartition *partition, EvpnRoute *route)
Constructor for EvpnLocalMcastNode.
Definition: bgp_evpn.cc:183
BgpPath::PathSource src
Definition: bgp_evpn.h:221
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
Ip4Address group() const
Definition: ermvpn_route.h:59
bool single_active() const
Definition: bgp_evpn.h:258
AliasedPathList aliased_path_list_
Definition: bgp_evpn.h:320
virtual UpdateInfo * GetUpdateInfo(EvpnRoute *route)
Construct export state for the given EvpnRoute. Note that the route only needs to be exported to the ...
Definition: bgp_evpn.cc:1140
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
SegmentMap segment_map_
Definition: bgp_evpn.h:746
BgpServer * server()
Definition: bgp_table.cc:88
bool RemovePath(BgpPath::PathSource src, const IPeer *peer=NULL, uint32_t path_id=0)
Definition: bgp_route.cc:262
const EvpnPrefix & GetPrefix() const
virtual ~EvpnLocalMcastNode()
Definition: bgp_evpn.cc:206
bool virtual_network_pbb_evpn_enable() const
void MacAdvertisementRouteListener(EvpnManagerPartition *partition, EvpnRoute *route)
DBListener callback handler for MacAdvertisement routes in the EvpnTable.
Definition: bgp_evpn.cc:1326
bool GetForestNodeAddress(ErmVpnRoute *rt, Ip4Address *address) const
Definition: bgp_evpn.cc:932
uint32_t bgp_identifier() const
Definition: bgp_server.h:208
EvpnRoute * esi_ad_route()
Definition: bgp_evpn.h:253
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
EvpnStatePtr LocateState(EvpnRoute *route)
Definition: bgp_evpn.cc:974
void DestroyEvpnManager()
Definition: evpn_table.cc:353
This class holds Evpn state for a particular &lt;S,G&gt; at any given time.
Definition: bgp_evpn.h:347
EvpnStatePtr GetState(const SG &sg)
Definition: bgp_evpn.cc:947
uint32_t GetAddress() const
Definition: rd.cc:48
EvpnManagerPartition * partition_
Definition: bgp_evpn.h:90
#define BGP_LOG_FLAG_TRACE
Definition: bgp_log.h:43
BgpAttrDB * attr_db()
Definition: bgp_server.h:181
const EthernetSegmentId & esi() const
void UpdateMcastNode(EvpnMcastNode *node, EvpnRoute *route)
Update an EvpnMcastNode in the EvpnManagerPartition. Need to remove/add EvpnMcastNode from the replic...
Definition: bgp_evpn.cc:850
BgpAttrPtr ReplaceOListAndLocate(const BgpAttr *attr, const BgpOListSpec *olist_spec)
Definition: bgp_attr.cc:1378
DBTablePartition * GetTablePartition(size_t part_id)
Get the DBTablePartition for the EvpnTable for given partition id.
Definition: bgp_evpn.cc:1132
RouteListVector route_lists_
Definition: bgp_evpn.h:268
size_t part_id() const
Definition: bgp_evpn.h:489
bool is_onlist()
Definition: db_entry.h:53
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
bool ContainsTunnelEncapVxlan() const
Definition: community.cc:655
bool HasPaths() const
Definition: bgp_route.h:27
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
ErmVpnTable * ermvpn_table_
Definition: bgp_evpn.h:740
bool ProcessMacUpdateList()
Process the MAC route update list for this EvpnManagerPartition.
Definition: bgp_evpn.cc:894
EvpnRoute * inclusive_mcast_route_
Definition: bgp_evpn.h:157
EvpnMcastNodeList regular_node_list_
Definition: bgp_evpn.h:527
#define EVPN_ERMVPN_RT_LOG(rt,...)
Definition: bgp_evpn.h:795
std::vector< std::string > GetTunnelEncap() const
Definition: community.cc:595
static const int kInvalidId
Definition: db_table.h:64
EvpnRoute * route_
Definition: bgp_evpn.h:92
uint32_t label_
Definition: bgp_evpn.h:95
IpAddress group() const
This class represents a partition in the EvpnManager.
Definition: bgp_evpn.h:418
void EnableSegmentUpdateProcessing()
Enable processing of the update list. For testing only.
Definition: bgp_evpn.cc:1290
int ermvpn_listener_id_
Definition: bgp_evpn.h:742
IpAddress ip_address() const
void DeletePath(BgpPath *path)
Definition: bgp_route.cc:126
bool assisted_replication_supported() const
Definition: bgp_evpn.h:82
boost::scoped_ptr< TaskTrigger > segment_delete_trigger_
Definition: bgp_evpn.h:749
UpdateInfo * GetUpdateInfo(EvpnRoute *route)
Definition: bgp_evpn.cc:302
void NotifyNodeRoute(EvpnMcastNode *node)
Notify the Broadcast MAC route for the given EvpnMcastNode.
Definition: bgp_evpn.cc:740
void DisableSegmentDeleteProcessing()
Disable processing of the delete list. For testing only.
Definition: bgp_evpn.cc:1224
bool IsZero() const
Definition: esi.h:43
void Notify()
Definition: db_entry.cc:127
static int PartitionCount()
Definition: db.cc:32
EvpnRemoteMcastNode(EvpnManagerPartition *partition, EvpnRoute *route)
Definition: bgp_evpn.cc:375
EvpnStatePtr CreateState(const SG &sg)
Definition: bgp_evpn.cc:958
virtual void Add(DBEntry *entry)
EvpnManagerPartition(EvpnManager *evpn_manager, size_t part_id)
Definition: bgp_evpn.cc:710
EvpnSegment(EvpnManager *evpn_manager, const EthernetSegmentId &esi)
Definition: bgp_evpn.cc:400
void DisableMacUpdateProcessing()
Disable processing of the update list. For testing only.
Definition: bgp_evpn.cc:984
boost::scoped_ptr< TaskTrigger > mac_update_trigger_
Definition: bgp_evpn.h:530
void DeleteMcastNode(EvpnMcastNode *node, EvpnRoute *route)
Delete an EvpnMcastNode from the EvpnManagerPartition.
Definition: bgp_evpn.cc:822
EvpnRoute * route()
Definition: bgp_evpn.h:73
void set_esi_ad_route(EvpnRoute *esi_ad_route)
Definition: bgp_evpn.h:254
Ip4Address address() const
Definition: bgp_evpn.h:77
IpAddress group
Definition: bgp_evpn.h:362
void Notify(DBEntryBase *entry)
const RouteDistinguisher & route_distinguisher() const
const BgpAttr * attr() const
Definition: bgp_evpn.h:75
bool operator<(const SG &other) const
Definition: bgp_evpn.cc:1739
EvpnState(const SG &sg, StatesMap *states, EvpnManager *manager)
A global MVPN state for a given &lt;S.G&gt; within a EvpnProjectManager.
Definition: bgp_evpn.cc:34
ErmVpnTable * ermvpn_table()
Definition: bgp_evpn.h:608
ErmVpnRoute * global_ermvpn_tree_rt()
Definition: bgp_evpn.cc:1759
std::set< BgpPath * > AliasedPathList
Definition: bgp_evpn.h:303
EvpnRouteList mac_update_list_
Definition: bgp_evpn.h:529
bool single_active_
Definition: bgp_evpn.h:267
bool MayDelete() const
Trigger deletion of the EvpnManager and propagate the delete to any dependents.
Definition: bgp_evpn.cc:1664
bool assisted_replication_leaf() const
Definition: bgp_evpn.h:85
virtual bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
This is the base class for a multicast node in an EVPN instance. The node could either represent a lo...
Definition: bgp_evpn.h:46
void set_state(EvpnStatePtr state)
Definition: bgp_evpn.h:72
void NotifyForestNode(EvpnRoute *route, ErmVpnTable *table)
Definition: bgp_evpn.cc:1484
void SetAttr(const BgpAttrPtr attr, const BgpAttrPtr original_attr)
Definition: bgp_path.h:82
EvpnMcastNodeList ir_client_node_list_
Definition: bgp_evpn.h:528
bool edge_replication_not_supported_
Definition: bgp_evpn.h:98
void DisableSegmentUpdateProcessing()
Disable processing of the update list. For testing only.
Definition: bgp_evpn.cc:1282
int index() const
bool IsUsableGlobalTreeRootRoute(ErmVpnRoute *ermvpn_route) const
Check whether an ErmVpnRoute is locally originated GlobalTreeRoute.
Definition: bgp_evpn.cc:1511
const PathList & GetPathList() const
Definition: route.h:46
EvpnRoute * esi_ad_route_
Definition: bgp_evpn.h:266
virtual bool IsValid() const
void DeleteInclusiveMulticastRoute()
Delete Inclusive Multicast route for this EvpnLocalMcastNode.
Definition: bgp_evpn.cc:262
void RetryDelete()
Attempt to enqueue a delete for the EvpnManager.
Definition: bgp_evpn.cc:1709
virtual std::string ToString() const