9 #include <boost/foreach.hpp>
22 #include "bgp/routing-instance/routing_instance_analytics_types.h"
28 using std::ostringstream;
35 sg_(sg), global_ermvpn_tree_rt_(NULL), spmsi_rt_(NULL),
36 source_active_rt_(NULL), states_(states), project_manager_(pm) {
58 lifetime_manager()),
manager_(manager) {
84 listener_id_(
DBTable::kInvalidId),
85 table_delete_ref_(this, table->
deleter()) {
96 if (!partition->
states().empty()) {
98 "MvpnProjectManager::MayDelete() paused due to pending " +
124 "MvpnProjectManager");
125 MVPN_LOG(MvpnProjectManagerCreate,
"Initialized MvpnProjectManager");
133 MVPN_LOG(MvpnProjectManagerDelete,
"Terminated MvpnProjectManager");
142 for (
size_t part_id = 0; part_id <
partitions_.size(); part_id++) {
181 : manager_(manager), part_id_(part_id) {
190 assert(
states_.insert(make_pair(sg, state.get())).second);
205 MvpnState::StatesMap::const_iterator iter =
states_.find(sg);
206 return iter !=
states_.end() ? iter->second : NULL;
210 MvpnState::StatesMap::iterator iter =
states_.find(sg);
211 return iter !=
states_.end() ? iter->second : NULL;
219 rd_(rd), originator_(originator), source_as_(0) {
242 NeighborMap::const_iterator iter =
neighbors_.find(rd);
266 source(route->GetPrefix().source()),
267 group(route->GetPrefix().group()) {
271 source(route->GetPrefix().source()), group(route->GetPrefix().group()) {
275 source(source), group(group) {
279 if (source < other.
source)
281 if (source > other.
source)
283 if (group < other.
group)
285 if (group > other.
group)
373 lifetime_manager()),
manager_(manager) {
399 ermvpn_table_(ermvpn_table),
400 listener_id_(
DBTable::kInvalidId),
401 identifier_listener_id_(-1),
402 table_delete_ref_(this, table->
deleter()),
403 ermvpn_table_delete_ref_(this, ermvpn_table->
deleter()) {
451 MVPN_LOG(MvpnManagerDelete,
"Terminated MvpnManager");
464 for (
size_t part_id = 0; part_id <
partitions_.size(); part_id++) {
475 "MvpnManager::MayDelete() paused due to pending " +
507 : manager_(manager), part_id_(part_id) {
540 assert(project_manager_partition);
549 if (!project_manager_partition)
553 return project_manager_partition->
GetState(sg);
578 if (
table()->tree_manager())
590 uint32_t *label,
Ip4Address *address, vector<string> *enc)
const {
591 if (!
table()->tree_manager())
597 Ip4Address *address, vector<string> *encap)
const {
622 MVPN_LOG(MvpnManagerCreate,
"Initialized MvpnManager");
648 attr_spec.push_back(&nexthop);
731 if (found && old_neighbor == neighbor)
738 MVPN_LOG(MvpnNeighborCreate, neighbor.rd().ToString(),
739 neighbor.originator().to_string(), neighbor.source_as());
745 if (!ermvpn_route || !ermvpn_route->
IsUsable())
751 return (global_rt && global_rt == ermvpn_route);
768 assert(ermvpn_route);
783 mvpn_state->set_global_ermvpn_tree_rt(NULL);
788 BOOST_FOREACH(
MvpnRoute *route, mvpn_state->spmsi_routes_received()) {
793 "Processed MVPN GlobalErmVpnRoute deletion");
806 mvpn_state = mvpn_dbstate->
state();
810 mvpn_dbstate->
state()->set_global_ermvpn_tree_rt(ermvpn_route);
813 BOOST_FOREACH(
MvpnRoute *route, mvpn_state->spmsi_routes_received()) {
818 "Processed MVPN GlobalErmVpnRoute creation");
834 mvpn_dbstate->
state() ? mvpn_dbstate->
state()->spmsi_rt() : NULL;
835 if (spmsi_rt && spmsi_rt->
IsUsable()) {
842 mvpn_dbstate->
state()->set_source_active_rt(NULL);
843 mvpn_dbstate->
state()->set_spmsi_rt(NULL);
847 MVPN_RT_LOG(rt,
"Processed MVPN Source Active route deletion");
858 state->set_source_active_rt(rt);
871 if (!join_rt || !join_rt->
IsUsable() ||
876 assert(!state->spmsi_rt() || spmsi_rt == state->spmsi_rt());
877 state->set_spmsi_rt(NULL);
881 MVPN_RT_LOG(spmsi_rt,
"Deleted already originated SPMSI path");
892 state->set_spmsi_rt(spmsi_rt);
893 if (!mvpn_dbstate->
route()) {
896 assert(spmsi_rt == mvpn_dbstate->
route());
917 MVPN_RT_LOG(rt,
"Processed MVPN Source Active route creation");
933 if (mvpn_dbstate->
state()->source_active_rt())
934 mvpn_dbstate->
state()->source_active_rt()->Notify();
936 MVPN_RT_LOG(join_rt,
"Processed Type 7 Join route deletion");
953 if (state->source_active_rt()) {
954 state->source_active_rt()->Notify();
955 MVPN_RT_LOG(join_rt,
"Processed Type 7 Join route creation and "
956 "notified Source Active route");
958 MVPN_RT_LOG(join_rt,
"Processed Type 7 Join route creation");
970 assert(mvpn_dbstate->
state()->leafad_routes_attr_received().
972 MvpnRoute *sa_active_rt = mvpn_dbstate->
state()->source_active_rt();
976 if (sa_active_rt && sa_active_rt->IsUsable()) {
977 sa_active_rt->Notify();
978 MVPN_RT_LOG(leaf_ad,
"Processed Type 4 LeafAD route deletion"
979 " and notified type5 source active route");
981 MVPN_RT_LOG(leaf_ad,
"Processed Type 4 LeafAD route deletion");
999 pair<MvpnState::RoutesMap::iterator, bool> result =
1000 state->leafad_routes_attr_received().insert(make_pair(leaf_ad,
1004 if (!result.second) {
1012 MvpnRoute *sa_active_rt = mvpn_dbstate->
state()->source_active_rt();
1013 if (sa_active_rt && sa_active_rt->
IsUsable()) {
1015 MVPN_RT_LOG(sa_active_rt,
"Processed Type 4 Leaf AD route creation"
1016 " and Type-5 source active route was notified");
1018 MVPN_RT_LOG(sa_active_rt,
"Processed Type 4 Leaf AD route creation");
1036 assert(mvpn_dbstate->
state() == mvpn_state);
1040 leaf_ad_route = mvpn_dbstate->
route();
1041 if (leaf_ad_route) {
1044 leaf_ad_route->DeletePath(path);
1048 assert(mvpn_state->spmsi_routes_received().erase(spmsi_rt));
1050 delete mvpn_dbstate;
1051 if (leaf_ad_route) {
1052 leaf_ad_route->NotifyOrDelete();
1058 MVPN_RT_LOG(spmsi_rt,
"Processed Type 3 S-PMSI route deletion"
1059 " and notified local ForestNode");
1061 MVPN_RT_LOG(spmsi_rt,
"Processed Type 3 S-PMSI route deletion");
1072 if (!join_rt || !join_rt->
IsUsable())
1081 if (!mvpn_dbstate) {
1084 assert(mvpn_state->spmsi_routes_received().insert(spmsi_rt).second);
1086 leaf_ad_route = mvpn_dbstate->
route();
1093 MVPN_RT_LOG(spmsi_rt,
"No need to process Type 3 S-PMSI route as"
1094 " LeafInfoRequired bit is not set");
1098 ErmVpnRoute *global_rt = mvpn_state->global_ermvpn_tree_rt();
1101 vector<string> tunnel_encaps;
1109 if (leaf_ad_route) {
1117 MVPN_RT_LOG(spmsi_rt,
"Processed Type 3 S-PMSI route as deletion"
1118 " and notified local ForestNode due to missing PMSI");
1123 if (!leaf_ad_route) {
1135 ReplaceRTargetAndLocate(attrp->ext_community(), rtarget);
1138 BOOST_FOREACH(
string encap, tunnel_encaps) {
1139 tunnel_encaps_list.push_back(
TunnelEncap(encap).GetExtCommunity());
1143 ReplaceTunnelEncapsulationAndLocate(ext_community.get(),
1144 tunnel_encaps_list);
1147 attrp.get(), ext_community);
1153 pmsi_spec.
SetLabel(label, ext_community.get());
1165 if (old_path && old_path->
GetAttr() == new_attrp.get())
1175 MVPN_RT_LOG(spmsi_rt,
"Processed Type 3 S-PMSI route creation");
1190 if (!state || !state->spmsi_rt() || !state->spmsi_rt()->IsUsable())
1195 state->spmsi_rt()->get_table_partition()->parent());
1202 secondary_tables->insert(table);
1203 MVPN_RT_LOG(mvpn_rt,
"Updated tables for replication with table " +
1221 if (!state->global_ermvpn_tree_rt() ||
1222 !state->global_ermvpn_tree_rt()->IsUsable()) {
1227 if (state->spmsi_routes_received().empty())
1231 *addrp = (*(state->spmsi_routes_received().begin()))->
1232 GetPrefix().originator();
1234 addrp->to_string());
1254 if (!state || state->leafad_routes_attr_received().empty())
1259 BOOST_FOREACH(MvpnState::RoutesMap::value_type &iter,
1260 state->leafad_routes_attr_received()) {
1268 uint32_t label = attr->pmsi_tunnel()->GetLabel(extcomm);
1273 olist_spec.
elements.push_back(elem);
virtual ErmVpnRoute * GetGlobalTreeRootRoute(const Ip4Address &source, const Ip4Address &group) const
ErmVpnRoute * global_ermvpn_tree_rt()
MvpnProjectManager(ErmVpnTable *table)
const NeighborMap & neighbors() const
MvpnStatePtr GetState(MvpnRoute *route) const
const Ip4Address identifier() const
const MvpnState::StatesMap & states() const
tbb::reader_writer_lock neighbors_mutex_
const RouteDistinguisher & rd() const
virtual void Initialize()
MvpnProjectManagerPartition * GetProjectManagerPartition()
const BgpPath * BestPath() const
TypePtr Locate(Type *attr)
const ErmVpnPrefix & GetPrefix() const
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
void set_global_ermvpn_tree_rt(ErmVpnRoute *global_ermvpn_tree_rt)
MvpnManagerPartition(MvpnManager *manager, int part_id)
std::map< RouteDistinguisher, MvpnNeighbor > NeighborMap
IpAddress groupIpAddress() const
void ReOriginateType1Route(const Ip4Address &old_identifier)
void NotifyForestNode(const Ip4Address &source, const Ip4Address &group)
void SetDBState(MvpnRoute *route, MvpnDBState *mvpn_dbstate)
MvpnProjectManager * project_manager_
boost::scoped_ptr< DeleteActor > deleter_
RoutesSet spmsi_routes_received_
MvpnStatePtr LocateState(const SG &sg)
virtual ~MvpnProjectManagerPartition()
DeleteActor(MvpnProjectManager *manager)
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
void NotifyForestNode(int part_id, const Ip4Address &source, const Ip4Address &group)
boost::asio::ip::address IpAddress
MvpnRoute * source_active_rt()
RoutesSet & spmsi_routes_received()
void set_spmsi_rt(MvpnRoute *spmsi_rt)
const uint8_t tunnel_type() const
MvpnManager(MvpnTable *table, ErmVpnTable *ermvpn_table)
MvpnRoute * LocateType4LeafADRoute(const MvpnRoute *type3_spmsi_rt)
void ProcessType5SourceActiveRoute(MvpnRoute *join_rt)
std::vector< BgpAttribute * > BgpAttrSpec
const BgpPath * FindPath(BgpPath::PathSource src) const
ErmVpnRoute * global_ermvpn_tree_rt_
tbb::atomic< int > db_states_count_
boost::scoped_ptr< DeleteActor > deleter_
uint32_t source_as() const
MvpnProjectManager * GetProjectManager()
void ProcessType4LeafADRoute(MvpnRoute *leaf_ad)
virtual void UpdateSecondaryTablesForReplication(MvpnRoute *rt, BgpTable::TableSet *secondary_tables) const
void Unregister(ListenerId listener)
UpdateInfo * GetType7UpdateInfo(MvpnRoute *route)
virtual void Initialize()
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
const McastTreeManager * tree_manager() const
void GetMvpnSourceAddress(ErmVpnRoute *ermvpn_route, Ip4Address *address) const
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
bool FindNeighbor(const RouteDistinguisher &rd, MvpnNeighbor *nbr) const
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
const LifetimeActor * deleter() const
const uint8_t tunnel_flags() const
int RegisterIdentifierUpdateCallback(IdentifierUpdateCb callback)
boost::intrusive_ptr< MvpnState > MvpnStatePtr
PartitionList partitions_
MvpnRoute * FindType1ADRoute(const Ip4Address &originator_ip)
static const std::string integerToString(const NumberType &num)
DeleteActor(MvpnManager *manager)
const MvpnRoute * FindType7SourceTreeJoinRoute(MvpnRoute *rt) const
bool operator<(const SG &other) const
void RouteListener(DBEntryBase *db_entry)
ExtCommunityDB * extcomm_db()
bool operator==(const MvpnNeighbor &rhs) const
MvpnProjectManagerPartition(MvpnProjectManager *manager, int part_id)
std::map< SG, MvpnState * > StatesMap
bool mvpn_ipv4_enable() const
void SetIdentifier(Ip4Address identifier)
#define CHECK_CONCURRENCY(...)
std::set< BgpTable * > TableSet
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
const LifetimeActor * deleter() const
IpAddress sourceIpAddress() const
MvpnStatePtr GetState(const SG &sg)
MvpnState::StatesMap states_
MvpnProjectManagerPartition * GetPartition(int part_id)
const std::string & name() const
bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
RoutesMap & leafad_routes_attr_received()
virtual std::string ToString() const
Ip4Address source() const
void ClearState(DBTableBase *tbl_base, ListenerId listener)
void ProcessType3SPMSIRoute(MvpnRoute *spmsi_rt)
void SetLabel(uint32_t label, const ExtCommunity *ext)
BgpAttrPtr ReplacePmsiTunnelAndLocate(const BgpAttr *attr, const PmsiTunnelSpec *pmsi_spec)
boost::asio::ip::address_v4 Ip4Address
UpdateInfo * GetUpdateInfo(MvpnRoute *route)
#define MVPN_TRACE(type,...)
void InsertPath(BgpPath *path)
virtual int PartitionCount() const
size_t neighbors_count() const
std::set< MvpnRoute * > RoutesSet
MvpnStatePtr CreateState(const SG &sg)
void set_source_active_rt(MvpnRoute *source_active_rt)
uint32_t bgp_identifier() const
MvpnStatePtr GetState(MvpnRoute *route)
const MvpnProjectManager * GetProjectManager() const
void DestroyMvpnProjectManager()
void set_route(MvpnRoute *route)
const MvpnProjectManagerPartition * GetProjectManagerPartition(BgpRoute *route) const
BgpAttrPtr ReplaceOListAndLocate(const BgpAttr *attr, const BgpOListSpec *olist_spec)
void ProcessType1ADRoute(MvpnRoute *route)
void ProcessType7SourceTreeJoinRoute(MvpnRoute *join_rt)
const BgpAttr * GetAttr() const
virtual bool MayDelete() const
static const int kInvalidId
std::string ToString() const
bool IsUsableGlobalTreeRootRoute(ErmVpnRoute *ermvpn_route) const
MvpnStatePtr LocateState(MvpnRoute *route)
void OriginateType1Route()
const PmsiTunnelSpec & pmsi_tunnel() const
virtual ~MvpnProjectManager()
RoutesMap leafad_routes_attr_received_
tbb::atomic< int > refcount_
void DeletePath(BgpPath *path)
MvpnDBState(MvpnStatePtr state)
int identifier_listener_id_
const ErmVpnTable * table() const
MvpnProjectManager * manager_
MvpnState(const SG &sg, StatesMap *states, MvpnProjectManager *pm)
void ClearDBState(MvpnRoute *route)
virtual bool MayDelete() const
DBTablePartBase * get_table_partition() const
const IpAddress & originator() const
#define MVPN_LOG(type,...)
Ip4Address source() const
const MvpnPrefix & GetPrefix() const
void NotifyForestNode(const Ip4Address &source, const Ip4Address &group)
const PmsiTunnel * pmsi_tunnel() const
MvpnRoute * source_active_rt_
const RouteDistinguisher & route_distinguisher() const
#define MVPN_ERMVPN_RT_LOG(rt,...)
Ip4Address originator() const
MvpnRoute * LocateType3SPMSIRoute(const MvpnRoute *type7_join_rt)
virtual bool IsReplicated() const
PartitionList partitions_
void UnregisterIdentifierUpdateCallback(int listener)
std::map< MvpnRoute *, BgpAttrPtr > RoutesMap
virtual int PartitionCount() const
bool IsProjectManagerUsable() const
#define MVPN_RT_LOG(rt,...)
virtual ~MvpnManagerPartition()
virtual bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
MvpnProjectManager * manager_
MvpnRoute * LocateType1ADRoute()
void set_state(MvpnStatePtr state)
SG(const Ip4Address &source, const Ip4Address &group)
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)