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)
 
  745     if (!ermvpn_route || !ermvpn_route->
IsUsable())
 
  747     if (!
table()->tree_manager())
 
  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()) {
 
  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) {
 
 1048         assert(mvpn_state->spmsi_routes_received().erase(spmsi_rt));
 
 1050         delete mvpn_dbstate;
 
 1051         if (leaf_ad_route) {
 
 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);
 
boost::asio::ip::address IpAddress
boost::asio::ip::address_v4 Ip4Address
std::vector< BgpAttribute * > BgpAttrSpec
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
#define MVPN_TRACE(type,...)
#define MVPN_ERMVPN_RT_LOG(rt,...)
#define MVPN_LOG(type,...)
#define MVPN_RT_LOG(rt,...)
boost::intrusive_ptr< MvpnState > MvpnStatePtr
BgpAttrPtr ReplaceOListAndLocate(const BgpAttr *attr, const BgpOListSpec *olist_spec)
BgpAttrPtr ReplacePmsiTunnelAndLocate(const BgpAttr *attr, const PmsiTunnelSpec *pmsi_spec)
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
const PmsiTunnel * pmsi_tunnel() const
TypePtr Locate(Type *attr)
virtual bool IsReplicated() const
const BgpAttr * GetAttr() const
const BgpPath * FindPath(BgpPath::PathSource src) const
const BgpPath * BestPath() const
void DeletePath(BgpPath *path)
void InsertPath(BgpPath *path)
ExtCommunityDB * extcomm_db()
int RegisterIdentifierUpdateCallback(IdentifierUpdateCb callback)
uint32_t bgp_identifier() const
bool mvpn_ipv4_enable() const
void UnregisterIdentifierUpdateCallback(int listener)
std::set< BgpTable * > TableSet
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
void ClearState(DBTableBase *tbl_base, ListenerId listener)
DBTablePartBase * get_table_partition() const
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
Ip4Address source() const
const ErmVpnPrefix & GetPrefix() const
const McastTreeManager * tree_manager() const
void DestroyMvpnProjectManager()
virtual int PartitionCount() const
void NotifyForestNode(int part_id, const Ip4Address &source, const Ip4Address &group)
virtual bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
virtual ErmVpnRoute * GetGlobalTreeRootRoute(const Ip4Address &source, const Ip4Address &group) const
bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
void ProcessType7SourceTreeJoinRoute(MvpnRoute *join_rt)
void ProcessType4LeafADRoute(MvpnRoute *leaf_ad)
MvpnManagerPartition(MvpnManager *manager, int part_id)
MvpnStatePtr GetState(MvpnRoute *route)
void ProcessType3SPMSIRoute(MvpnRoute *spmsi_rt)
MvpnStatePtr LocateState(MvpnRoute *route)
virtual ~MvpnManagerPartition()
void NotifyForestNode(const Ip4Address &source, const Ip4Address &group)
void ProcessType5SourceActiveRoute(MvpnRoute *join_rt)
MvpnProjectManagerPartition * GetProjectManagerPartition()
virtual bool MayDelete() const
DeleteActor(MvpnManager *manager)
boost::scoped_ptr< DeleteActor > deleter_
void SetDBState(MvpnRoute *route, MvpnDBState *mvpn_dbstate)
virtual void Initialize()
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
MvpnProjectManager * GetProjectManager()
void ReOriginateType1Route(const Ip4Address &old_identifier)
void ProcessType1ADRoute(MvpnRoute *route)
MvpnManager(MvpnTable *table, ErmVpnTable *ermvpn_table)
PartitionList partitions_
std::map< RouteDistinguisher, MvpnNeighbor > NeighborMap
void ClearDBState(MvpnRoute *route)
const NeighborMap & neighbors() const
void OriginateType1Route()
bool FindNeighbor(const RouteDistinguisher &rd, MvpnNeighbor *nbr) const
const LifetimeActor * deleter() const
tbb::reader_writer_lock neighbors_mutex_
tbb::atomic< int > db_states_count_
int identifier_listener_id_
size_t neighbors_count() const
virtual void UpdateSecondaryTablesForReplication(MvpnRoute *rt, BgpTable::TableSet *secondary_tables) const
Ip4Address source() const
IpAddress sourceIpAddress() const
Ip4Address originator() const
const RouteDistinguisher & route_distinguisher() const
IpAddress groupIpAddress() const
MvpnProjectManagerPartition(MvpnProjectManager *manager, int part_id)
void RouteListener(DBEntryBase *db_entry)
MvpnState::StatesMap states_
MvpnStatePtr GetState(const SG &sg)
bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label, Ip4Address *address, std::vector< std::string > *encap) const
const MvpnState::StatesMap & states() const
virtual ~MvpnProjectManagerPartition()
MvpnStatePtr CreateState(const SG &sg)
bool IsUsableGlobalTreeRootRoute(ErmVpnRoute *ermvpn_route) const
void NotifyForestNode(const Ip4Address &source, const Ip4Address &group)
MvpnStatePtr LocateState(const SG &sg)
MvpnProjectManager * manager_
DeleteActor(MvpnProjectManager *manager)
virtual bool MayDelete() const
MvpnProjectManager * manager_
const LifetimeActor * deleter() const
MvpnProjectManagerPartition * GetPartition(int part_id)
boost::scoped_ptr< DeleteActor > deleter_
UpdateInfo * GetUpdateInfo(MvpnRoute *route)
MvpnStatePtr GetState(MvpnRoute *route) const
PartitionList partitions_
void GetMvpnSourceAddress(ErmVpnRoute *ermvpn_route, Ip4Address *address) const
MvpnProjectManager(ErmVpnTable *table)
UpdateInfo * GetType7UpdateInfo(MvpnRoute *route)
void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry)
virtual void Initialize()
virtual ~MvpnProjectManager()
const MvpnPrefix & GetPrefix() const
RoutesSet spmsi_routes_received_
RoutesMap & leafad_routes_attr_received()
std::set< MvpnRoute * > RoutesSet
const ErmVpnTable * table() const
MvpnState(const SG &sg, StatesMap *states, MvpnProjectManager *pm)
ErmVpnRoute * global_ermvpn_tree_rt()
void set_source_active_rt(MvpnRoute *source_active_rt)
std::map< MvpnRoute *, BgpAttrPtr > RoutesMap
tbb::atomic< int > refcount_
ErmVpnRoute * global_ermvpn_tree_rt_
std::map< SG, MvpnState * > StatesMap
MvpnRoute * source_active_rt_
RoutesSet & spmsi_routes_received()
RoutesMap leafad_routes_attr_received_
MvpnRoute * source_active_rt()
void set_spmsi_rt(MvpnRoute *spmsi_rt)
MvpnProjectManager * project_manager_
void set_global_ermvpn_tree_rt(ErmVpnRoute *global_ermvpn_tree_rt)
bool IsProjectManagerUsable() const
const MvpnProjectManager * GetProjectManager() const
MvpnRoute * LocateType4LeafADRoute(const MvpnRoute *type3_spmsi_rt)
MvpnRoute * LocateType3SPMSIRoute(const MvpnRoute *type7_join_rt)
MvpnRoute * LocateType1ADRoute()
virtual int PartitionCount() const
const MvpnRoute * FindType7SourceTreeJoinRoute(MvpnRoute *rt) const
const MvpnProjectManagerPartition * GetProjectManagerPartition(BgpRoute *route) const
MvpnRoute * FindType1ADRoute(const Ip4Address &originator_ip)
const uint8_t tunnel_flags() const
const PmsiTunnelSpec & pmsi_tunnel() const
const uint8_t tunnel_type() const
const Ip4Address identifier() const
std::string ToString() const
static const std::string integerToString(const NumberType &num)
MvpnDBState(MvpnStatePtr state)
void set_state(MvpnStatePtr state)
void set_route(MvpnRoute *route)
const IpAddress & originator() const
uint32_t source_as() const
bool operator==(const MvpnNeighbor &rhs) const
const RouteDistinguisher & rd() const
bool operator<(const SG &other) const
SG(const Ip4Address &source, const Ip4Address &group)
virtual std::string ToString() const
void SetIdentifier(Ip4Address identifier)
void SetLabel(uint32_t label, const ExtCommunity *ext)
#define CHECK_CONCURRENCY(...)