7 #include <boost/foreach.hpp>
16 #include "bgp/bgp_peer_types.h"
24 #include "bgp/routing-instance/routing_instance_analytics_types.h"
35 sg_(sg), global_ermvpn_tree_rt_(NULL), states_(states),
81 : partition_(partition),
86 edge_replication_not_supported_(false),
87 assisted_replication_supported_(false),
88 assisted_replication_leaf_(false) {
94 : partition_(partition),
99 edge_replication_not_supported_(false),
100 assisted_replication_supported_(false),
101 assisted_replication_leaf_(false) {
118 bool changed =
false;
186 inclusive_mcast_route_(NULL) {
195 inclusive_mcast_route_(NULL) {
245 ReplaceMFlagsAndLocate(
attr_->ext_community(), mcastFlags);
247 attr_.get(), ext_community);
256 route,
"Insert new Local path");
329 if (pbb_evpn_enable && remote_ethernet_tag &&
330 (local_ethernet_tag != remote_ethernet_tag))
336 olist_spec.
elements.push_back(elem);
352 leaf_olist_spec.
elements.push_back(elem);
401 : evpn_manager_(manager),
404 single_active_(true),
405 route_lists_(
DB::PartitionCount()) {
420 pair<RouteList::iterator, bool> ret =
route_lists_[part_id].insert(route);
444 for (
size_t part_id = 0; part_id <
route_lists_.size(); ++part_id) {
462 for (RemotePeList::iterator it =
pe_list_.begin();
464 it->esi_valid =
false;
470 bool changed =
false;
471 for (Route::PathList::const_iterator path_it =
475 static_cast<const BgpPath *
>(path_it.operator->());
486 for (RemotePeList::iterator it =
pe_list_.begin();
489 if (it->attr->nexthop() != remote_pe.
attr->nexthop())
500 if (*it == remote_pe) {
501 it->esi_valid =
true;
515 for (RemotePeList::iterator it =
pe_list_.begin(), next = it;
518 if (!it->esi_valid) {
526 for (RemotePeList::iterator it =
pe_list_.begin();
528 if (it->single_active) {
548 for (
size_t part_id = 0; part_id <
route_lists_.size(); ++part_id) {
561 single_active(path->GetAttr()->evpn_single_active()),
562 peer(path->GetPeer()),
563 attr(path->GetAttr()),
564 flags(path->GetFlags()),
565 src(path->GetSource()) {
574 if (peer != rhs.
peer)
576 if (attr != rhs.
attr)
578 if (flags != rhs.
flags)
589 :
evpn_manager_(evpn_manager), route_(route), segment_(NULL) {
611 " peer " << (peer ? peer->
ToString() :
"None") <<
626 " peer " << (peer ? peer->
ToString() :
"None") <<
654 return (
new BgpPath(peer, src, attr, flags, label));
668 bool found_primary_pe =
false;
676 found_primary_pe =
true;
685 for (; found_primary_pe && path &&
segment_ &&
695 future_aliased_path_list.insert(aliased_path);
701 &future_aliased_path_list,
712 : evpn_manager_(evpn_manager),
763 bool exclude_edge_replication_supported) {
768 if (exclude_edge_replication_supported &&
811 if (list->count(sg)) {
812 deleted = (*list)[sg].erase(node);
813 if ((*list)[sg].size() == 0)
816 return (deleted > 0);
939 rt, &label, address, &te);
943 EvpnState::StatesMap::const_iterator iter =
states_.find(sg);
944 return iter !=
states_.end() ? iter->second : NULL;
948 EvpnState::StatesMap::iterator iter =
states_.find(sg);
949 return iter !=
states_.end() ? iter->second : NULL;
960 assert(
states_.insert(make_pair(sg, state.get())).second);
1033 listener_id_(
DBTable::kInvalidId),
1036 TaskScheduler::GetInstance()->GetTaskId(
"bgp::EvpnSegment"), 0)),
1039 TaskScheduler::GetInstance()->GetTaskId(
"bgp::EvpnSegment"), 0)),
1040 table_delete_ref_(this, table->
deleter()) {
1108 partitions_[part_id]->DisableMacUpdateProcessing();
1118 partitions_[part_id]->EnableMacUpdateProcessing();
1179 return (loc !=
segment_map_.end()) ? loc->second : NULL;
1267 if (!esi_ad_route->
IsValid()) {
1370 }
else if (segment && segment->
esi() != path->
GetAttr()->
esi()) {
1429 bool is_usable = route->
IsUsable();
1431 bool checkErmvpnRoute =
false;
1436 if ((!is_usable && !checkErmvpnRoute) || is_deleted) {
1442 evpn_state->smet_routes().erase(route);
1443 EVPN_RT_LOG(route,
"Processed Smet route deletion");
1453 evpn_state->smet_routes().insert(route);
1456 ErmVpnRoute *global_rt = evpn_state->global_ermvpn_tree_rt();
1462 ReplaceNexthopAndLocate(attr.get(), address);
1463 path->
SetAttr(new_attr, attr);
1480 EVPN_RT_LOG(route,
"Processed Smet route creation");
1488 if (
table->tree_manager())
1489 table->tree_manager()->NotifyForestNode(
part_id_, source, group);
1513 if (!ermvpn_route || !ermvpn_route->
IsUsable())
1521 GetGlobalTreeRootRoute(
1524 return (global_rt && global_rt == ermvpn_route);
1535 assert(ermvpn_route);
1551 evpn_state->set_global_ermvpn_tree_rt(NULL);
1556 BOOST_FOREACH(
EvpnRoute *route, evpn_state->smet_routes()) {
1565 "Processed EVPN GlobalErmVpnRoute deletion");
1579 evpn_state = dbstate->
state();
1583 dbstate->
state()->set_global_ermvpn_tree_rt(ermvpn_route);
1586 BOOST_FOREACH(
EvpnRoute *route, evpn_state->smet_routes()) {
1590 "Processed EVPN GlobalErmVpnRoute creation");
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++) {
1640 ShowEvpnMcastLeaf leaf;
1641 leaf.set_address(node->
address().to_string());
1643 ar_leafs.push_back(leaf);
1645 ar_replicators.push_back(node->
address().to_string());
1647 regular_nves.push_back(node->
address().to_string());
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);
1681 if (!partition->
empty())
1683 if (!partition->
states().empty())
1727 source(route->GetPrefix().source()),
1728 group(route->GetPrefix().group()) {
1732 source(route->GetPrefix().source()), group(route->GetPrefix().group()) {
1736 source(source), group(group) {
1740 if (source < other.
source)
1742 if (source > other.
source)
1744 if (group < other.
group)
1746 if (group > other.
group)
boost::asio::ip::address IpAddress
boost::asio::ip::address_v4 Ip4Address
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
#define EVPN_RT_LOG(rt,...)
#define EVPN_ERMVPN_RT_LOG(rt,...)
boost::intrusive_ptr< EvpnState > EvpnStatePtr
#define EVPN_TRACE(type,...)
#define BGP_LOG_FLAG_TRACE
#define BGP_LOG_ROUTE(table, peer, route, arg)
#define BGP_LOG_STR(obj, level, flags, arg)
BgpAttrPtr ReplaceOListAndLocate(const BgpAttr *attr, const BgpOListSpec *olist_spec)
BgpAttrPtr ReplaceLeafOListAndLocate(const BgpAttr *attr, const BgpOListSpec *leaf_olist_spec)
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
const IpAddress & nexthop() const
const ExtCommunity * ext_community() const
const EthernetSegmentId & esi() const
uint32_t GetLabel() const
void SetAttr(const BgpAttrPtr attr, const BgpAttrPtr original_attr)
uint32_t GetFlags() const
const uint32_t GetPathId() const
const BgpAttr * GetAttr() const
const BgpPath * FindPath(BgpPath::PathSource src) const
bool RemovePath(BgpPath::PathSource src, const IPeer *peer=NULL, uint32_t path_id=0)
const BgpPath * BestPath() const
void DeletePath(BgpPath *path)
void InsertPath(BgpPath *path)
ExtCommunityDB * extcomm_db()
uint32_t bgp_identifier() const
RoutingInstance * routing_instance()
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
void ClearState(DBTableBase *tbl_base, ListenerId listener)
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
static const int kInvalidId
void Unregister(ListenerId listener)
const std::string & name() const
void Notify(DBEntryBase *entry)
void Delete(DBEntryBase *)
virtual void Add(DBEntry *entry)
DBEntry * Find(const DBEntry *entry)
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
static int PartitionCount()
Ip4Address source() const
const ErmVpnPrefix & GetPrefix() const
const McastTreeManager * tree_manager() const
This class represents (in the context of an EVPN instance) a local vRouter that's connected to a cont...
virtual ~EvpnLocalMcastNode()
EvpnRoute * inclusive_mcast_route_
EvpnLocalMcastNode(EvpnManagerPartition *partition, EvpnRoute *route)
Constructor for EvpnLocalMcastNode.
UpdateInfo * GetUpdateInfo(EvpnRoute *route)
virtual void TriggerUpdate()
Handle update of EvpnLocalMcastNode.
void DeleteInclusiveMulticastRoute()
Delete Inclusive Multicast route for this EvpnLocalMcastNode.
void AddInclusiveMulticastRoute()
Add Inclusive Multicast route for this EvpnLocalMcastNode. The attributes are based on the Broadcast ...
This class represents the EvpnManager state associated with a MAC route.
BgpPath * LocateAliasedPath(const EvpnSegment::RemotePe *remote_pe, uint32_t label)
Find or create the matching aliased BgpPath.
std::set< BgpPath * > AliasedPathList
void set_segment(EvpnSegment *segment)
void DeleteAliasedPath(AliasedPathList::const_iterator it)
Delete the BgpPath specified by the iterator from the aliased path list. Also deletes the BgpPath fro...
bool ProcessMacRouteAliasing()
Update aliased BgpPaths for the EvpnRoute based on the remote PEs for the EvpnSegment....
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...
EvpnMacState(EvpnManager *evpn_manager, EvpnRoute *route)
EvpnManager * evpn_manager_
AliasedPathList aliased_path_list_
This class represents a partition in the EvpnManager.
void NotifyIrClientNodeRoutes(bool exclude_edge_replication_supported)
Go through all ingress replication client EvpnMcastNodes and notify the associated Broadcast MAC rout...
const EvpnMcastNodeList & leaf_node_list() const
std::map< SG, std::set< EvpnMcastNode * > > EvpnMcastNodeList
void NotifyReplicatorNodeRoutes()
Go through all replicator EvpnMcastNodes and notify associated Broadcast MAC route.
void TriggerMacRouteUpdate(EvpnRoute *route)
Add the given MAC route to the update list. This method gets called either when the MAC route itself ...
EvpnManagerPartition(EvpnManager *evpn_manager, size_t part_id)
EvpnMcastNodeList leaf_node_list_
EvpnMcastNodeList local_mcast_node_list_
bool RemoveMcastNodeFromList(EvpnState::SG &sg, EvpnMcastNode *node, EvpnMcastNodeList *list)
Delete an EvpnMcastNode from the EvpnManagerPartition.
bool ProcessMacUpdateList()
Process the MAC route update list for this EvpnManagerPartition.
void UpdateMcastNode(EvpnMcastNode *node, EvpnRoute *route)
Update an EvpnMcastNode in the EvpnManagerPartition. Need to remove/add EvpnMcastNode from the replic...
EvpnManager * evpn_manager_
EvpnState::StatesMap states_
void AddMcastNode(EvpnMcastNode *node, EvpnRoute *route)
Add an EvpnMcastNode to the EvpnManagerPartition.
EvpnRouteList mac_update_list_
void NotifyNodeRoute(EvpnMcastNode *node)
Notify the Broadcast MAC route for the given EvpnMcastNode.
EvpnMcastNodeList replicator_node_list_
void EnableMacUpdateProcessing()
Enable processing of the update list. For testing only.
EvpnMcastNodeList regular_node_list_
boost::scoped_ptr< TaskTrigger > mac_update_trigger_
EvpnStatePtr GetState(const SG &sg)
void DisableMacUpdateProcessing()
Disable processing of the update list. For testing only.
void NotifyForestNode(EvpnRoute *route, ErmVpnTable *table)
EvpnMcastNodeList ir_client_node_list_
bool GetForestNodeAddress(ErmVpnRoute *rt, Ip4Address *address) const
EvpnStatePtr CreateState(const SG &sg)
DBTablePartition * GetTablePartition()
Get the DBTablePartition for the EvpnTable for our partition id.
DBTablePartition * table_partition_
void DeleteMcastNode(EvpnMcastNode *node, EvpnRoute *route)
Delete an EvpnMcastNode from the EvpnManagerPartition.
const EvpnState::StatesMap & states() const
const EvpnMcastNodeList & remote_mcast_node_list() const
bool empty() const
Return true if the EvpnManagerPartition is empty i.e. it has no local or remote EvpnMcastNodes and no...
BgpServer * server()
Return the BgpServer for the EvpnManagerPartition.
EvpnMcastNodeList remote_mcast_node_list_
EvpnStatePtr LocateState(EvpnRoute *route)
const EvpnTable * table() const
Return the EvpnTable for the EvpnManagerPartition.
DeleteActor(EvpnManager *evpn_manager)
virtual bool MayDelete() const
EvpnManager * evpn_manager_
This class represents the EVPN manager for an EvpnTable in a VRF.
void ErmVpnRouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
ErmVpnTable route listener callback function.
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
DBListener callback handler for the EvpnTable.
bool ProcessSegmentUpdateSet()
Process the set of EvpnSegments that need to be updated.
LifetimeActor * deleter()
Return the LifetimeActor for the EvpnManager.
ErmVpnTable * ermvpn_table_
void Shutdown()
Initiate shutdown for the EvpnManager.
void DisableMacUpdateProcessing()
Disable processing of the update lists in all partitions. For testing only.
SegmentSet segment_delete_set_
EvpnManager(EvpnTable *table)
void AllocPartitions()
Allocate the EvpnManagerPartitions.
virtual UpdateInfo * GetUpdateInfo(EvpnRoute *route)
Construct export state for the given EvpnRoute. Note that the route only needs to be exported to the ...
int ermvpn_listener_id() const
void RetryDelete()
Attempt to enqueue a delete for the EvpnManager.
boost::scoped_ptr< TaskTrigger > segment_delete_trigger_
EvpnSegment * FindSegment(const EthernetSegmentId &esi)
Find the EvpnSegment for the given EthernetSegmentId.
void DisableSegmentUpdateProcessing()
Disable processing of the update list. For testing only.
virtual void Initialize()
Initialize the EvpnManager. We allocate the EvpnManagerPartitions and register a DBListener for the E...
tbb::atomic< int > db_states_count_
bool MayDelete() const
Trigger deletion of the EvpnManager and propagate the delete to any dependents.
void TriggerSegmentDelete(EvpnSegment *segment)
Trigger deletion of the given EvpnSegment. The EvpnSegment is added to a set of EvpnSegments that can...
EvpnManagerPartition * GetPartition(size_t part_id)
Get the EvpnManagerPartition for the given partition id.
ErmVpnTable * ermvpn_table()
void MacAdvertisementRouteListener(EvpnManagerPartition *partition, EvpnRoute *route)
DBListener callback handler for MacAdvertisement routes in the EvpnTable.
boost::scoped_ptr< DeleteActor > deleter_
SegmentSet segment_update_set_
EvpnSegment * LocateSegment(const EthernetSegmentId &esi)
Find or create the EvpnSegment for the given EthernetSegmentId.
PartitionList partitions_
void FillShowInfo(ShowEvpnTable *sevt) const
Fill information for introspect command. Note that all IM routes are always in partition 0.
void FreePartitions()
Free the EvpnManagerPartitions.
void InclusiveMulticastRouteListener(EvpnManagerPartition *partition, EvpnRoute *route)
DBListener callback handler for InclusiveMulticast routes in the EvpnTable.
bool ProcessSegmentDeleteSet()
Process the set of EvpnSegments that can potentially be deleted. Remove the EvpnSegment from the map ...
void AutoDiscoveryRouteListener(EvpnRoute *route)
DBListener callback handler for AutoDisocvery routes in the EvpnTable.
void EnableMacUpdateProcessing()
Enable processing of the update lists in all partitions. For testing only.
virtual void Terminate()
Terminate the EvpnManager. We free the EvpnManagerPartitions and unregister from the EvpnTable.
boost::scoped_ptr< TaskTrigger > segment_update_trigger_
void SelectiveMulticastRouteListener(EvpnManagerPartition *partition, EvpnRoute *route)
DBListener callback handler for SelectiveMulticast routes in the EvpnTable.
void SetDBState(EvpnRoute *route, EvpnMcastNode *dbstate)
Set DB State and update count.
void ClearDBState(EvpnRoute *route)
Create DB State and update count. If there is no DB State associated in the table,...
void TriggerSegmentUpdate(EvpnSegment *segment)
Trigger update of the given EvpnSegment. The EvpnSegment is added to a set of EvpnSegments for which ...
void EnableSegmentUpdateProcessing()
Enable processing of the update list. For testing only.
DBTablePartition * GetTablePartition(size_t part_id)
Get the DBTablePartition for the EvpnTable for given partition id.
void DisableSegmentDeleteProcessing()
Disable processing of the delete list. For testing only.
bool IsUsableGlobalTreeRootRoute(ErmVpnRoute *ermvpn_route) const
Check whether an ErmVpnRoute is locally originated GlobalTreeRoute.
void ManagedDelete()
Trigger deletion of the EvpnManager and propagate the delete to any dependents.
tbb::spin_rw_mutex segment_rw_mutex_
void EnableSegmentDeleteProcessing()
Enable processing of the delete list. For testing only.
This is the base class for a multicast node in an EVPN instance. The node could either represent a lo...
bool edge_replication_not_supported_
bool assisted_replication_leaf() const
bool assisted_replication_supported() const
Ip4Address replicator_address_
EvpnMcastNode(EvpnManagerPartition *partition, EvpnRoute *route, uint8_t type)
Constructor for EvpnMcastNode. The type indicates whether this is a local or remote EvpnMcastNode.
bool assisted_replication_supported_
EvpnManagerPartition * partition_
void set_state(EvpnStatePtr state)
Ip4Address address() const
bool edge_replication_not_supported() const
bool assisted_replication_leaf_
virtual void TriggerUpdate()=0
Handle update of EvpnLocalMcastNode.
bool UpdateAttributes(EvpnRoute *route)
Update the label and attributes for a EvpnMcastNode. Return true if either of them changed.
const BgpAttr * attr() const
Ip4Address replicator_address() const
IpAddress ip_address() const
const EthernetSegmentId & esi() const
const RouteDistinguisher & route_distinguisher() const
const MacAddress & mac_addr() const
@ InclusiveMulticastRoute
@ SelectiveMulticastRoute
This class represents (in the context of an EVPN instance) a remote vRouter or PE discovered via BGP....
EvpnRemoteMcastNode(EvpnManagerPartition *partition, EvpnRoute *route)
virtual ~EvpnRemoteMcastNode()
virtual void TriggerUpdate()
Handle update of EvpnRemoteMcastNode.
const EvpnPrefix & GetPrefix() const
virtual bool IsValid() const
virtual std::string ToString() const
bool operator==(const RemotePe &rhs) const
Equality operator for EvpnSegment::RemotePe. Do not compare esi_valid and single_active fields since ...
RemotePe(const BgpPath *path)
This class represents a remote EVPN segment that has 2 or more PEs that are multi-homed to it....
EvpnRoute * esi_ad_route()
EvpnRoute * esi_ad_route_
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...
const_iterator begin() const
void AddMacRoute(size_t part_id, EvpnRoute *route)
Add the given MAC route as a dependent of this EvpnSegment.
void set_esi_ad_route(EvpnRoute *esi_ad_route)
RouteListVector route_lists_
EvpnManager * evpn_manager_
EvpnSegment(EvpnManager *evpn_manager, const EthernetSegmentId &esi)
const EthernetSegmentId & esi() const
bool MayDelete() const
Return true if it's safe to delete this EvpnSegment.
bool single_active() const
bool UpdatePeList()
Update the PE list for this EvpnSegment. This should be called when the AutoDisocvery route is update...
void TriggerMacRouteUpdate()
Trigger an update of all dependent MAC routes for this EvpnSegment. Note that the bgp::EvpnSegment ta...
const_iterator end() const
RemotePeList::const_iterator const_iterator
void clear_esi_ad_route()
This class holds Evpn state for a particular <S,G> at any given time.
const ErmVpnTable * table() const
void set_global_ermvpn_tree_rt(ErmVpnRoute *global_ermvpn_tree_rt)
EvpnState(const SG &sg, StatesMap *states, EvpnManager *manager)
A global MVPN state for a given <S.G> within a EvpnProjectManager.
ErmVpnRoute * global_ermvpn_tree_rt_
ErmVpnRoute * global_ermvpn_tree_rt()
tbb::atomic< int > refcount_
std::map< SG, EvpnState * > StatesMap
void DestroyEvpnManager()
virtual const std::string & ToString() const =0
virtual bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
const uint8_t tunnel_flags() const
const Ip4Address identifier() const
uint16_t GetVrfId() const
uint32_t GetAddress() const
const PathList & GetPathList() const
bool virtual_network_pbb_evpn_enable() const
BgpTable * GetTable(Address::Family fmly)
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
bool set_synchronize(const SetType *set1, const SetType *set2, AddFunctor add_fn, DelFunctor del_fn)
Simple structure to hold <S,G>. Source as "0.0.0.0" can be used to encode <*,G> as well.
bool operator<(const SG &other) const
SG(const Ip4Address &source, const Ip4Address &group)
@ AssistedReplicationType
@ EdgeReplicationSupported
#define CHECK_CONCURRENCY(...)
void STLDeleteValues(Container *container)