diff --git a/src/bgp/bgp_attr.cc b/src/bgp/bgp_attr.cc index 6a70ed711e5..ded63b2e1ed 100644 --- a/src/bgp/bgp_attr.cc +++ b/src/bgp/bgp_attr.cc @@ -8,6 +8,7 @@ #include #include "bgp/bgp_server.h" +#include "bgp/extended-community/etree.h" #include "bgp/extended-community/mac_mobility.h" #include "bgp/extended-community/router_mac.h" #include "net/bgp_af.h" @@ -967,6 +968,34 @@ uint32_t BgpAttr::sequence_number() const { return 0; } +bool BgpAttr::sticky() const { + if (!ext_community_) + return 0; + for (ExtCommunity::ExtCommunityList::const_iterator it = + ext_community_->communities().begin(); + it != ext_community_->communities().end(); ++it) { + if (ExtCommunity::is_mac_mobility(*it)) { + MacMobility mm(*it); + return mm.sticky(); + } + } + return 0; +} + +bool BgpAttr::leaf() const { + if (!ext_community_) + return 0; + for (ExtCommunity::ExtCommunityList::const_iterator it = + ext_community_->communities().begin(); + it != ext_community_->communities().end(); ++it) { + if (ExtCommunity::is_etree(*it)) { + ETree etree(*it); + return etree.leaf(); + } + } + return 0; +} + MacAddress BgpAttr::mac_address() const { if (!ext_community_) return MacAddress::kZeroMac; diff --git a/src/bgp/bgp_attr.h b/src/bgp/bgp_attr.h index 4c329943b35..80e52a8c34a 100644 --- a/src/bgp/bgp_attr.h +++ b/src/bgp/bgp_attr.h @@ -853,6 +853,8 @@ class BgpAttr { BgpOListPtr leaf_olist() const { return leaf_olist_; } BgpAttrDB *attr_db() const { return attr_db_; } uint32_t sequence_number() const; + bool sticky() const; + bool leaf() const; MacAddress mac_address() const; private: diff --git a/src/bgp/bgp_config.cc b/src/bgp/bgp_config.cc index fe1e92e9989..c157ac24267 100644 --- a/src/bgp/bgp_config.cc +++ b/src/bgp/bgp_config.cc @@ -284,6 +284,7 @@ BgpInstanceConfig::BgpInstanceConfig(const string &name) has_pnf_(false), virtual_network_index_(0), virtual_network_allow_transit_(false), + virtual_network_pbb_evpn_enable_(false), vxlan_id_(0), last_change_at_(UTCTimestampUsec()) { } @@ -298,6 +299,7 @@ void BgpInstanceConfig::Clear() { virtual_network_.clear(); virtual_network_index_ = 0; virtual_network_allow_transit_ = false; + virtual_network_pbb_evpn_enable_ = false; vxlan_id_ = 0; inet_static_routes_.clear(); inet6_static_routes_.clear(); diff --git a/src/bgp/bgp_config.h b/src/bgp/bgp_config.h index 5902cd98d4f..c281861b408 100644 --- a/src/bgp/bgp_config.h +++ b/src/bgp/bgp_config.h @@ -429,6 +429,14 @@ class BgpInstanceConfig { virtual_network_allow_transit_ = allow_transit; } + bool virtual_network_pbb_evpn_enable() const { + return virtual_network_pbb_evpn_enable_; + } + void set_virtual_network_pbb_evpn_enable(bool pbb_evpn) { + virtual_network_pbb_evpn_enable_ = pbb_evpn; + } + + int vxlan_id() const { return vxlan_id_; } void set_vxlan_id(int vxlan_id) { vxlan_id_ = vxlan_id; } @@ -469,6 +477,7 @@ class BgpInstanceConfig { std::string virtual_network_; int virtual_network_index_; bool virtual_network_allow_transit_; + bool virtual_network_pbb_evpn_enable_; int vxlan_id_; mutable uint64_t last_change_at_; StaticRouteList inet_static_routes_; diff --git a/src/bgp/bgp_config_ifmap.cc b/src/bgp/bgp_config_ifmap.cc index 2596c4b3e40..3efe3fc06dd 100644 --- a/src/bgp/bgp_config_ifmap.cc +++ b/src/bgp/bgp_config_ifmap.cc @@ -856,6 +856,20 @@ static bool GetVirtualNetworkAllowTransit(DBGraph *graph, IFMapNode *node) { return false; } + +// +// Check if a virtual-network has pbb-evpn enabled. +// The input IFMapNode represents the virtual-network. +// +static bool GetVirtualNetworkPbbEvpnEnable(DBGraph *graph, IFMapNode *node) { + const autogen::VirtualNetwork *vn = + static_cast(node->GetObject()); + if (vn && vn->IsPropertySet(autogen::VirtualNetwork::PBB_EVPN_ENABLE)) + return vn->pbb_evpn_enable(); + return false; +} + + // // Get the vxlan id for a virtual-network. The input IFMapNode represents // the virtual-network. @@ -1088,6 +1102,8 @@ void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager, data_.set_virtual_network_allow_transit( GetVirtualNetworkAllowTransit(graph, adj)); data_.set_vxlan_id(GetVirtualNetworkVxlanId(graph, adj)); + data_.set_virtual_network_pbb_evpn_enable( + GetVirtualNetworkPbbEvpnEnable(graph, adj)); } } diff --git a/src/bgp/bgp_config_parser.cc b/src/bgp/bgp_config_parser.cc index dae6d6864b2..eb1eb366565 100644 --- a/src/bgp/bgp_config_parser.cc +++ b/src/bgp/bgp_config_parser.cc @@ -557,6 +557,15 @@ bool BgpConfigParser::ParseVirtualNetwork(const xml_node &node, string vn_name(node.attribute("name").value()); assert(!vn_name.empty()); + auto_ptr pbb_property( + new autogen::VirtualNetwork::OolProperty); + pbb_property->data = false; + + if (node.attribute("pbb-evpn-enable")) { + pbb_property->data = + (string(node.attribute("pbb-evpn-enable").value()) == "true"); + } + auto_ptr property( new autogen::VirtualNetworkType()); assert(property->XmlParse(node)); @@ -564,9 +573,13 @@ bool BgpConfigParser::ParseVirtualNetwork(const xml_node &node, if (add_change) { MapObjectSetProperty("virtual-network", vn_name, "virtual-network-properties", property.release(), requests); + MapObjectSetProperty("virtual-network", vn_name, + "pbb-evpn-enable", pbb_property.release(), requests); } else { MapObjectClearProperty("virtual-network", vn_name, "virtual-network-properties", requests); + MapObjectClearProperty("virtual-network", vn_name, + "pbb-evpn-enable", requests); } return true; diff --git a/src/bgp/bgp_evpn.cc b/src/bgp/bgp_evpn.cc index 1ae15d78218..76927e40449 100644 --- a/src/bgp/bgp_evpn.cc +++ b/src/bgp/bgp_evpn.cc @@ -15,6 +15,7 @@ #include "bgp/bgp_server.h" #include "bgp/bgp_update.h" #include "bgp/evpn/evpn_table.h" +#include "bgp/routing-instance/routing_instance.h" using std::sort; using std::string; @@ -232,9 +233,15 @@ UpdateInfo *EvpnLocalMcastNode::GetUpdateInfo() { if (assisted_replication_leaf_) return NULL; + const RoutingInstance *rti = partition_->table()->routing_instance(); + bool pbb_evpn_enable = rti->virtual_network_pbb_evpn_enable(); + uint32_t local_ethernet_tag = route_->GetPrefix().tag(); + // Go through list of EvpnRemoteMcastNodes and build the BgpOList. BgpOListSpec olist_spec(BgpAttribute::OList); BOOST_FOREACH(EvpnMcastNode *node, partition_->remote_mcast_node_list()) { + uint32_t remote_ethernet_tag = node->route()->GetPrefix().tag(); + if (node->address() == address_) continue; if (node->assisted_replication_leaf()) @@ -242,6 +249,9 @@ UpdateInfo *EvpnLocalMcastNode::GetUpdateInfo() { if (!edge_replication_not_supported_ && !node->edge_replication_not_supported()) continue; + if (pbb_evpn_enable && remote_ethernet_tag && + (local_ethernet_tag != remote_ethernet_tag)) + continue; const ExtCommunity *extcomm = node->attr()->ext_community(); BgpOListElem elem(node->address(), node->label(), diff --git a/src/bgp/bgp_path.cc b/src/bgp/bgp_path.cc index e2a96c056f2..a833374938b 100644 --- a/src/bgp/bgp_path.cc +++ b/src/bgp/bgp_path.cc @@ -61,6 +61,12 @@ int BgpPath::PathCompare(const BgpPath &rhs, bool allow_ecmp) const { // Compare local_pref in reverse order as larger is better. KEY_COMPARE(rattr->local_pref(), attr_->local_pref()); + // ETree Root path first [compare in reverse order] + BOOL_COMPARE(rattr->leaf(), attr_->leaf()); + + // Sticky paths first + BOOL_COMPARE(rattr->sticky(), attr_->sticky()); + // Compare sequence_number in reverse order as larger is better. KEY_COMPARE(rattr->sequence_number(), attr_->sequence_number()); diff --git a/src/bgp/bgp_peer.sandesh b/src/bgp/bgp_peer.sandesh index d5e3e8806d5..26743c49f70 100644 --- a/src/bgp/bgp_peer.sandesh +++ b/src/bgp/bgp_peer.sandesh @@ -326,6 +326,7 @@ struct ShowRoutingInstance { 5: list export_target; // Export Route targets 10: bool always_subscribe; // Always subscribe for RTF 12: bool allow_transit; // Allow transit + 13: bool pbb_evpn_enable; // PBB EVPN enabled 7: bool deleted; // Deletion in progress 9: string deleted_at; // Delete timestamp 2: optional list tables; @@ -575,6 +576,7 @@ struct ShowBgpInstanceConfig { 4: list export_target; 10: bool has_pnf; 13: bool allow_transit; + 14: bool pbb_evpn_enable; 9: string last_change_at; 5: list service_chain_infos; 6: list static_routes; diff --git a/src/bgp/bgp_route.cc b/src/bgp/bgp_route.cc index 45c5d02aecd..bf64bf87426 100644 --- a/src/bgp/bgp_route.cc +++ b/src/bgp/bgp_route.cc @@ -10,6 +10,7 @@ #include "bgp/extended-community/default_gateway.h" #include "bgp/extended-community/es_import.h" #include "bgp/extended-community/esi_label.h" +#include "bgp/extended-community/etree.h" #include "bgp/extended-community/load_balance.h" #include "bgp/extended-community/mac_mobility.h" #include "bgp/extended-community/router_mac.h" @@ -353,7 +354,10 @@ static void FillRoutePathExtCommunityInfo(const BgpTable *table, } else if (ExtCommunity::is_mac_mobility(*it)) { MacMobility mm(*it); communities->push_back(mm.ToString()); - show_path->set_sequence_no(mm.ToString()); + show_path->set_sequence_no(integerToString(mm.sequence_number())); + } else if (ExtCommunity::is_etree(*it)) { + ETree etree(*it); + communities->push_back(etree.ToString()); } else if (ExtCommunity::is_router_mac(*it)) { RouterMac router_mac(*it); communities->push_back(router_mac.ToString()); diff --git a/src/bgp/bgp_show_config.cc b/src/bgp/bgp_show_config.cc index a3ebd52618b..0f57bfee8a4 100644 --- a/src/bgp/bgp_show_config.cc +++ b/src/bgp/bgp_show_config.cc @@ -38,6 +38,7 @@ static void FillBgpInstanceConfigInfo(ShowBgpInstanceConfig *sbic, sbic->set_export_target(export_list); sbic->set_has_pnf(instance->has_pnf()); sbic->set_allow_transit(instance->virtual_network_allow_transit()); + sbic->set_pbb_evpn_enable(instance->virtual_network_pbb_evpn_enable()); sbic->set_last_change_at(UTCUsecToString(instance->last_change_at())); vector sbscc_list; diff --git a/src/bgp/bgp_show_routing_instance.cc b/src/bgp/bgp_show_routing_instance.cc index 9e29af84088..3f01f5f5b92 100644 --- a/src/bgp/bgp_show_routing_instance.cc +++ b/src/bgp/bgp_show_routing_instance.cc @@ -65,6 +65,7 @@ static void FillRoutingInstanceInfo(ShowRoutingInstance *sri, sri->set_export_target(export_rt); sri->set_always_subscribe(rtinstance->always_subscribe()); sri->set_allow_transit(rtinstance->virtual_network_allow_transit()); + sri->set_pbb_evpn_enable(rtinstance->virtual_network_pbb_evpn_enable()); if (!summary) { const BgpMembershipManager *bmm = bsc->bgp_server->membership_mgr(); diff --git a/src/bgp/routing-instance/routing_instance.cc b/src/bgp/routing-instance/routing_instance.cc index b4d1853597f..ac074339242 100644 --- a/src/bgp/routing-instance/routing_instance.cc +++ b/src/bgp/routing-instance/routing_instance.cc @@ -767,6 +767,7 @@ RoutingInstance::RoutingInstance(string name, BgpServer *server, : name_(name), index_(-1), server_(server), mgr_(mgr), config_(config), is_master_(false), always_subscribe_(false), virtual_network_index_(0), virtual_network_allow_transit_(false), + virtual_network_pbb_evpn_enable_(false), vxlan_id_(0), deleter_(new DeleteActor(server, this)), manager_delete_ref_(this, NULL) { @@ -940,6 +941,8 @@ void RoutingInstance::ProcessConfig() { virtual_network_ = config_->virtual_network(); virtual_network_index_ = config_->virtual_network_index(); virtual_network_allow_transit_ = config_->virtual_network_allow_transit(); + virtual_network_pbb_evpn_enable_ = + config_->virtual_network_pbb_evpn_enable(); vxlan_id_ = config_->vxlan_id(); // Always subscribe (using RTF) for RTs of PNF service chain instances. @@ -1013,6 +1016,9 @@ void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) { bool notify_routes = false; if (virtual_network_allow_transit_ != cfg->virtual_network_allow_transit()) notify_routes = true; + if (virtual_network_pbb_evpn_enable_ != + cfg->virtual_network_pbb_evpn_enable()) + notify_routes = true; if (virtual_network_ != cfg->virtual_network()) notify_routes = true; if (virtual_network_index_ != cfg->virtual_network_index()) @@ -1043,6 +1049,7 @@ void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) { virtual_network_index_ = cfg->virtual_network_index(); virtual_network_allow_transit_ = cfg->virtual_network_allow_transit(); + virtual_network_pbb_evpn_enable_ = cfg->virtual_network_pbb_evpn_enable(); vxlan_id_ = cfg->vxlan_id(); // Master routing instance doesn't have import & export list @@ -1155,6 +1162,10 @@ bool RoutingInstance::virtual_network_allow_transit() const { return virtual_network_allow_transit_; } +bool RoutingInstance::virtual_network_pbb_evpn_enable() const { + return virtual_network_pbb_evpn_enable_; +} + int RoutingInstance::vxlan_id() const { return vxlan_id_; } diff --git a/src/bgp/routing-instance/routing_instance.h b/src/bgp/routing-instance/routing_instance.h index 69865fecbe4..dfb6be7e442 100644 --- a/src/bgp/routing-instance/routing_instance.h +++ b/src/bgp/routing-instance/routing_instance.h @@ -120,6 +120,7 @@ class RoutingInstance { const BgpInstanceConfig *config() const { return config_; } int virtual_network_index() const; bool virtual_network_allow_transit() const; + bool virtual_network_pbb_evpn_enable() const; int vxlan_id() const; const RoutingInstanceMgr *manager() const { return mgr_; } @@ -219,6 +220,7 @@ class RoutingInstance { std::string virtual_network_; int virtual_network_index_; bool virtual_network_allow_transit_; + bool virtual_network_pbb_evpn_enable_; int vxlan_id_; boost::scoped_ptr deleter_; LifetimeRef manager_delete_ref_; diff --git a/src/bgp/test/bgp_evpn_manager_test.cc b/src/bgp/test/bgp_evpn_manager_test.cc index fcdc33cf23d..bc65ccda263 100644 --- a/src/bgp/test/bgp_evpn_manager_test.cc +++ b/src/bgp/test/bgp_evpn_manager_test.cc @@ -3,6 +3,7 @@ */ #include +#include #include "base/task_annotations.h" #include "bgp/bgp_factory.h" @@ -18,6 +19,9 @@ #include "io/test/event_manager_test.h" using namespace std; +using boost::assign::list_of; + +typedef vector TagList; class PeerMock : public IPeer { public: @@ -144,7 +148,7 @@ static const char *config_template = "\ 192.168.0.1\
127.0.0.1
\ \ - \ + \ 1\ \ \ @@ -161,19 +165,26 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { static const int kVrfId = 1; static const int kVnIndex = 1; - BgpEvpnManagerTest() + BgpEvpnManagerTest(bool pbb_evpn = false) : thread_(&evm_), blue_(NULL), master_(NULL), blue_manager_(NULL), blue_ribout_(NULL), - tag_(0) { + tag_(0), pbb_evpn_(pbb_evpn) { } virtual void SetUp() { server_.reset(new BgpServerTest(&evm_, "local")); thread_.Start(); - server_->Configure(config_template); + char config[4096]; + if (pbb_evpn_) { + snprintf(config, sizeof(config), config_template, "true"); + } else { + snprintf(config, sizeof(config), config_template, "false"); + } + + server_->Configure(config); task_util::WaitForIdle(); DB *db = server_->database(); @@ -238,6 +249,16 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { return found; } + TagList GetTagList(const TagList &tag_list) const { + TagList temp_tag_list; + if (tag_list.empty()) { + temp_tag_list.push_back(tag_); + } else { + temp_tag_list = tag_list; + } + return temp_tag_list; + } + bool VerifyPeerInOList(PeerMock *peer, UpdateInfoPtr uinfo) { return VerifyPeerInOListCommon(peer, uinfo, false); } @@ -268,10 +289,10 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { } bool VerifyPeerUpdateInfoCommon(PeerMock *peer, bool odd, bool even, - bool include_xmpp, bool include_leaf = false) { + uint32_t tag, bool include_xmpp, bool include_leaf = false) { ConcurrencyScope scope("db::DBTable"); RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, MacAddress::BroadcastMac(), IpAddress()); + EvpnPrefix prefix(rd, tag, MacAddress::BroadcastMac(), IpAddress()); EvpnTable::RequestKey key(prefix, peer); EvpnRoute *rt = dynamic_cast(blue_->Find(&key)); if (rt == NULL) @@ -327,10 +348,10 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { return true; } - bool VerifyPeerNoUpdateInfo(PeerMock *peer) { + bool VerifyPeerNoUpdateInfo(PeerMock *peer, uint32_t tag) { ConcurrencyScope scope("db::DBTable"); RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, MacAddress::BroadcastMac(), IpAddress()); + EvpnPrefix prefix(rd, tag, MacAddress::BroadcastMac(), IpAddress()); EvpnTable::RequestKey key(prefix, peer); EvpnRoute *rt = dynamic_cast(blue_->Find(&key)); if (rt == NULL) @@ -401,11 +422,11 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { ChangeXmppPeersEncapCommon(true, true, encap); } - void AddXmppPeerBroadcastMacRoute(PeerMock *peer, string nexthop_str = "", - uint32_t label = 0) { + void AddXmppPeerBroadcastMacRoute(PeerMock *peer, uint32_t tag, + string nexthop_str = "", uint32_t label = 0) { EXPECT_TRUE(peer->IsXmppPeer()); RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, MacAddress::BroadcastMac(), IpAddress()); + EvpnPrefix prefix(rd, tag, MacAddress::BroadcastMac(), IpAddress()); BgpAttrSpec attr_spec; ExtCommunitySpec ext_comm; @@ -446,31 +467,35 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { task_util::WaitForIdle(); } - void AddXmppPeersBroadcastMacRouteCommon(bool odd, bool even) { + void AddXmppPeersBroadcastMacRouteCommon(TagList tag_list, + bool odd, bool even) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { if ((odd && peer->index() % 2 != 0) || (even && peer->index() % 2 == 0)) { - AddXmppPeerBroadcastMacRoute(peer); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + AddXmppPeerBroadcastMacRoute(peer, tag); } } } - void AddOddXmppPeersBroadcastMacRoute() { - AddXmppPeersBroadcastMacRouteCommon(true, false); + void AddOddXmppPeersBroadcastMacRoute(TagList tag_list = TagList()) { + AddXmppPeersBroadcastMacRouteCommon(tag_list, true, false); } - void AddEvenXmppPeersBroadcastMacRoute() { - AddXmppPeersBroadcastMacRouteCommon(false, true); + void AddEvenXmppPeersBroadcastMacRoute(TagList tag_list = TagList()) { + AddXmppPeersBroadcastMacRouteCommon(tag_list, false, true); } - void AddAllXmppPeersBroadcastMacRoute() { - AddXmppPeersBroadcastMacRouteCommon(true, true); + void AddAllXmppPeersBroadcastMacRoute(TagList tag_list = TagList()) { + AddXmppPeersBroadcastMacRouteCommon(tag_list, true, true); } - void DelXmppPeerBroadcastMacRoute(PeerMock *peer) { + void DelXmppPeerBroadcastMacRoute(PeerMock *peer, uint32_t tag) { EXPECT_TRUE(peer->IsXmppPeer()); + RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, MacAddress::BroadcastMac(), IpAddress()); + EvpnPrefix prefix(rd, tag, MacAddress::BroadcastMac(), IpAddress()); DBRequest delReq; delReq.key.reset(new EvpnTable::RequestKey(prefix, peer)); @@ -479,16 +504,18 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { task_util::WaitForIdle(); } - void DelAllXmppPeersBroadcastMacRoute() { + void DelAllXmppPeersBroadcastMacRoute(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - DelXmppPeerBroadcastMacRoute(peer); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + DelXmppPeerBroadcastMacRoute(peer, tag); } } - void VerifyXmppPeerInclusiveMulticastRoute(PeerMock *peer) { + void VerifyXmppPeerInclusiveMulticastRoute(PeerMock *peer, uint32_t tag) { EXPECT_TRUE(peer->IsXmppPeer()); RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, peer->address()); + EvpnPrefix prefix(rd, tag, peer->address()); EvpnTable::RequestKey key(prefix, peer); TASK_UTIL_EXPECT_TRUE(master_->Find(&key) != NULL); EvpnRoute *rt = dynamic_cast(master_->Find(&key)); @@ -512,50 +539,64 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { TASK_UTIL_EXPECT_TRUE(peer->encap() == encap); } - void VerifyAllXmppPeersInclusiveMulticastRoute() { + void VerifyAllXmppPeersInclusiveMulticastRoute(TagList tag_list = + TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - VerifyXmppPeerInclusiveMulticastRoute(peer); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + VerifyXmppPeerInclusiveMulticastRoute(peer, tag); } } - void VerifyXmppPeerNoInclusiveMulticastRoute(PeerMock *peer) { + void VerifyXmppPeerNoInclusiveMulticastRoute(PeerMock *peer, uint32_t tag) { EXPECT_TRUE(peer->IsXmppPeer()); RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, peer->address()); + EvpnPrefix prefix(rd, tag, peer->address()); EvpnTable::RequestKey key(prefix, peer); TASK_UTIL_EXPECT_TRUE(blue_->Find(&key) == NULL); } - void VerifyAllXmppPeersNoInclusiveMulticastRoute() { + void VerifyAllXmppPeersNoInclusiveMulticastRoute(TagList tag_list = + TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - VerifyXmppPeerNoInclusiveMulticastRoute(peer); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + VerifyXmppPeerNoInclusiveMulticastRoute(peer, tag); } } - void VerifyAllXmppPeersOddUpdateInfo() { + void VerifyAllXmppPeersOddUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, true, false, false)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, true, false, tag, false)); } } - void VerifyAllXmppPeersEvenUpdateInfo() { + void VerifyAllXmppPeersEvenUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, false, true, false)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, false, true, tag, false)); } } - void VerifyAllXmppPeersAllUpdateInfo() { + void VerifyAllXmppPeersAllUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, true, true, false)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, true, true, tag, false)); } } - void VerifyAllXmppPeersNoUpdateInfo() { + void VerifyAllXmppPeersNoUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, xmpp_peers_) { - TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer, tag)); } } @@ -752,10 +793,11 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { } void AddBgpPeerInclusiveMulticastRoute(PeerMock *peer, + uint32_t tag, string rtarget_str = "target:64512:1") { EXPECT_FALSE(peer->IsXmppPeer()); RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, peer->address()); + EvpnPrefix prefix(rd, tag, peer->address()); BgpAttrSpec attr_spec; ExtCommunitySpec ext_comm; @@ -789,58 +831,66 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { task_util::WaitForIdle(); } - void AddBgpPeerInclusiveMulticastRouteCommon(bool odd, bool even) { + void AddBgpPeerInclusiveMulticastRouteCommon(TagList tag_list, + bool odd, bool even) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, bgp_peers_) { if ((odd && peer->index() % 2 != 0) || (even && peer->index() % 2 == 0)) { - AddBgpPeerInclusiveMulticastRoute(peer); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + AddBgpPeerInclusiveMulticastRoute(peer, tag); } } } - void AddOddBgpPeersInclusiveMulticastRoute() { - AddBgpPeerInclusiveMulticastRouteCommon(true, false); + void AddOddBgpPeersInclusiveMulticastRoute(TagList tag_list = TagList()) { + AddBgpPeerInclusiveMulticastRouteCommon(tag_list, true, false); } - void AddEvenBgpPeersInclusiveMulticastRoute() { - AddBgpPeerInclusiveMulticastRouteCommon(false, true); + void AddEvenBgpPeersInclusiveMulticastRoute(TagList tag_list = TagList()) { + AddBgpPeerInclusiveMulticastRouteCommon(tag_list, false, true); } - void AddAllBgpPeersInclusiveMulticastRoute() { - AddBgpPeerInclusiveMulticastRouteCommon(true, true); + void AddAllBgpPeersInclusiveMulticastRoute(TagList tag_list = TagList()) { + AddBgpPeerInclusiveMulticastRouteCommon(tag_list, true, true); } - void DelBgpPeerInclusiveMulticastRoute(PeerMock *peer) { + void DelBgpPeerInclusiveMulticastRoute(PeerMock *peer, uint32_t tag) { EXPECT_FALSE(peer->IsXmppPeer()); + RouteDistinguisher rd(peer->address().to_ulong(), kVrfId); - EvpnPrefix prefix(rd, tag_, peer->address()); + EvpnPrefix prefix(rd, tag, peer->address()); DBRequest delReq; delReq.key.reset(new EvpnTable::RequestKey(prefix, peer)); delReq.oper = DBRequest::DB_ENTRY_DELETE; master_->Enqueue(&delReq); + task_util::WaitForIdle(); } - void DelBgpPeerInclusiveMulticastRouteCommon(bool odd, bool even) { + void DelBgpPeerInclusiveMulticastRouteCommon(TagList tag_list, + bool odd, bool even) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, bgp_peers_) { if ((odd && peer->index() % 2 != 0) || (even && peer->index() % 2 == 0)) { - DelBgpPeerInclusiveMulticastRoute(peer); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + DelBgpPeerInclusiveMulticastRoute(peer, tag); } } task_util::WaitForIdle(); } - void DelOddBgpPeersInclusiveMulticastRoute() { - DelBgpPeerInclusiveMulticastRouteCommon(true, false); + void DelOddBgpPeersInclusiveMulticastRoute(TagList tag_list = TagList()) { + DelBgpPeerInclusiveMulticastRouteCommon(tag_list, true, false); } - void DelEvenBgpPeersInclusiveMulticastRoute() { - DelBgpPeerInclusiveMulticastRouteCommon(false, true); + void DelEvenBgpPeersInclusiveMulticastRoute(TagList tag_list = TagList()) { + DelBgpPeerInclusiveMulticastRouteCommon(tag_list, false, true); } - void DelAllBgpPeersInclusiveMulticastRoute() { - DelBgpPeerInclusiveMulticastRouteCommon(true, true); + void DelAllBgpPeersInclusiveMulticastRoute(TagList tag_list = TagList()) { + DelBgpPeerInclusiveMulticastRouteCommon(tag_list, true, true); } void AddBgpPeerBroadcastMacRoute(PeerMock *peer) { @@ -937,23 +987,29 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { DelBgpPeerBroadcastMacRouteCommon(true, true); } - void VerifyAllBgpPeersBgpUpdateInfo() { + void VerifyAllBgpPeersBgpUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, bgp_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, true, true, false)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, true, true, tag, false)); } } - void VerifyAllBgpPeersAllUpdateInfo() { + void VerifyAllBgpPeersAllUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, bgp_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, true, true, true)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, true, true, tag, true)); } } - void VerifyAllBgpPeersNoUpdateInfo() { + void VerifyAllBgpPeersNoUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, bgp_peers_) { - TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer, tag)); } } @@ -1261,9 +1317,11 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { } } - void VerifyAllLeafPeersNoUpdateInfo() { + void VerifyAllLeafPeersNoUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, leaf_peers_) { - TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer, tag)); } } @@ -1421,63 +1479,73 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { } } - void VerifyReplicatorPeersLeafUpdateInfoCommon(bool odd, bool even) { + void VerifyReplicatorPeersLeafUpdateInfoCommon(TagList tag_list, + bool odd, bool even) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, replicator_peers_) { if (!odd && peer->index() % 2 != 0) continue; if (!even && peer->index() % 2 == 0) continue; - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, false, false, false, true)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, false, false, tag, false, true)); } } - void VerifyOddReplicatorPeersLeafUpdateInfo() { - VerifyReplicatorPeersLeafUpdateInfoCommon(true, false); + void VerifyOddReplicatorPeersLeafUpdateInfo(TagList tag_list = TagList()) { + VerifyReplicatorPeersLeafUpdateInfoCommon(tag_list, true, false); } - void VerifyEvenReplicatorPeersLeafUpdateInfo() { - VerifyReplicatorPeersLeafUpdateInfoCommon(false, true); + void VerifyEvenReplicatorPeersLeafUpdateInfo(TagList tag_list = TagList()) { + VerifyReplicatorPeersLeafUpdateInfoCommon(tag_list, false, true); } - void VerifyAllReplicatorPeersLeafUpdateInfo() { - VerifyReplicatorPeersLeafUpdateInfoCommon(true, true); + void VerifyAllReplicatorPeersLeafUpdateInfo(TagList tag_list = TagList()) { + VerifyReplicatorPeersLeafUpdateInfoCommon(tag_list, true, true); } - void VerifyAllReplicatorPeersNonLeafUpdateInfo() { + void VerifyAllReplicatorPeersNonLeafUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, replicator_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, true, true, false, false)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, true, true, tag, false, false)); } } - void VerifyAllReplicatorPeersAllUpdateInfo() { + void VerifyAllReplicatorPeersAllUpdateInfo(TagList tag_list = TagList()) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, replicator_peers_) { - TASK_UTIL_EXPECT_TRUE( - VerifyPeerUpdateInfoCommon(peer, true, true, false, true)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE( + VerifyPeerUpdateInfoCommon(peer, true, true, tag, false, true)); } } - void VerifyReplicatorPeersNoUpdateInfoCommon(bool odd, bool even) { + void VerifyReplicatorPeersNoUpdateInfoCommon(TagList tag_list, + bool odd, bool even) { + TagList temp_tag_list = GetTagList(tag_list); BOOST_FOREACH(PeerMock *peer, replicator_peers_) { if (!odd && peer->index() % 2 != 0) continue; if (!even && peer->index() % 2 == 0) continue; - TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer)); + BOOST_FOREACH(uint32_t tag, temp_tag_list) + TASK_UTIL_EXPECT_TRUE(VerifyPeerNoUpdateInfo(peer, tag)); } } - void VerifyOddReplicatorPeersNoUpdateInfo() { - VerifyReplicatorPeersNoUpdateInfoCommon(true, false); + void VerifyOddReplicatorPeersNoUpdateInfo(TagList tag_list = TagList()) { + VerifyReplicatorPeersNoUpdateInfoCommon(tag_list, true, false); } - void VerifyEvenReplicatorPeersNoUpdateInfo() { - VerifyReplicatorPeersNoUpdateInfoCommon(false, true); + void VerifyEvenReplicatorPeersNoUpdateInfo(TagList tag_list = TagList()) { + VerifyReplicatorPeersNoUpdateInfoCommon(tag_list, false, true); } - void VerifyAllReplicatorPeersNoUpdateInfo() { - VerifyReplicatorPeersNoUpdateInfoCommon(true, true); + void VerifyAllReplicatorPeersNoUpdateInfo(TagList tag_list = TagList()) { + VerifyReplicatorPeersNoUpdateInfoCommon(tag_list, true, true); } size_t GetPartitionLocalSize(uint32_t tag) { @@ -1516,6 +1584,13 @@ class BgpEvpnManagerTest : public ::testing::TestWithParam { vector leaf_peers_; vector replicator_peers_; int tag_; + bool pbb_evpn_; +}; + +class BgpPbbEvpnManagerTest : public BgpEvpnManagerTest { +protected: + BgpPbbEvpnManagerTest() : BgpEvpnManagerTest(true) { + } }; // Add Broadcast MAC routes from all XMPP peers. @@ -1630,6 +1705,86 @@ TEST_P(BgpEvpnManagerTest, Basic4) { VerifyAllXmppPeersNoInclusiveMulticastRoute(); } +// Add Broadcast MAC routes from all XMPP peers with ISID value as tag. +// Verify generated Inclusive Multicast routes in bgp.evpn.0. +// Add Inclusive Multicast route from all BGP peers. In this test, the BGP peer +// sends IM route with ISID value as tag +// Verify UpdateInfo for Broadcast MAC routes from all XMPP peers. +TEST_P(BgpPbbEvpnManagerTest, PbbEvpnBasic1) { + TagList isid_list = list_of(200200); + AddAllXmppPeersBroadcastMacRoute(isid_list); + TASK_UTIL_EXPECT_EQ(xmpp_peers_.size(), GetPartitionLocalSize(tag_)); + VerifyAllXmppPeersInclusiveMulticastRoute(isid_list); + VerifyAllXmppPeersNoUpdateInfo(); + AddAllBgpPeersInclusiveMulticastRoute(isid_list); + TASK_UTIL_EXPECT_EQ(bgp_peers_.size() + xmpp_peers_.size(), + GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersAllUpdateInfo(isid_list); + + DelAllBgpPeersInclusiveMulticastRoute(isid_list); + TASK_UTIL_EXPECT_EQ(xmpp_peers_.size(), GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersNoUpdateInfo(isid_list); + DelAllXmppPeersBroadcastMacRoute(isid_list); + TASK_UTIL_EXPECT_EQ(0, GetPartitionLocalSize(tag_)); + TASK_UTIL_EXPECT_EQ(0, GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersNoInclusiveMulticastRoute(isid_list); +} + +// Add Broadcast MAC routes from all XMPP peers with ISID value as tag. +// In this test, XMPP peer sends broadcast routes for each ISID associated with +// B-Component. +// Verify generated Inclusive Multicast routes in bgp.evpn.0. +// Add Inclusive Multicast route from all BGP peers. In this test, the BGP peer +// sends multiple IM routes each with unique ISID value as tag. +// Verify UpdateInfo for Broadcast MAC routes from all XMPP peers. +TEST_P(BgpPbbEvpnManagerTest, PbbEvpnBasic2) { + TagList isid_list = list_of(200200)(300300); + size_t size = isid_list.size(); + AddAllXmppPeersBroadcastMacRoute(isid_list); + TASK_UTIL_EXPECT_EQ(size * xmpp_peers_.size(), GetPartitionLocalSize(tag_)); + VerifyAllXmppPeersInclusiveMulticastRoute(isid_list); + VerifyAllXmppPeersNoUpdateInfo(); + AddAllBgpPeersInclusiveMulticastRoute(isid_list); + TASK_UTIL_EXPECT_EQ(size * (bgp_peers_.size() + xmpp_peers_.size()), + GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersAllUpdateInfo(isid_list); + + DelAllBgpPeersInclusiveMulticastRoute(isid_list); + TASK_UTIL_EXPECT_EQ(size * xmpp_peers_.size(), GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersNoUpdateInfo(isid_list); + DelAllXmppPeersBroadcastMacRoute(isid_list); + TASK_UTIL_EXPECT_EQ(0, GetPartitionLocalSize(tag_)); + TASK_UTIL_EXPECT_EQ(0, GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersNoInclusiveMulticastRoute(isid_list); +} + +// Add Broadcast MAC routes from all XMPP peers with ISID value as tag. +// Verify generated Inclusive Multicast routes in bgp.evpn.0. +// Add Inclusive Multicast route from all BGP peers. In this test, the BGP peer +// sends IM route with 0 tag. To test the case where Mx sends IM route with 0 +// tag when only single I-Component is configured. +// Verify UpdateInfo for Broadcast MAC routes from all XMPP peers. +TEST_P(BgpPbbEvpnManagerTest, PbbEvpnBasic3) { + TagList isid_list = list_of(200200); + AddAllXmppPeersBroadcastMacRoute(isid_list); + TASK_UTIL_EXPECT_EQ(xmpp_peers_.size(), GetPartitionLocalSize(tag_)); + VerifyAllXmppPeersInclusiveMulticastRoute(isid_list); + VerifyAllXmppPeersNoUpdateInfo(); + TagList mx_isid_list = list_of(0); + AddAllBgpPeersInclusiveMulticastRoute(mx_isid_list); + TASK_UTIL_EXPECT_EQ(bgp_peers_.size() + xmpp_peers_.size(), + GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersAllUpdateInfo(isid_list); + + DelAllBgpPeersInclusiveMulticastRoute(mx_isid_list); + TASK_UTIL_EXPECT_EQ(xmpp_peers_.size(), GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersNoUpdateInfo(isid_list); + DelAllXmppPeersBroadcastMacRoute(isid_list); + TASK_UTIL_EXPECT_EQ(0, GetPartitionLocalSize(tag_)); + TASK_UTIL_EXPECT_EQ(0, GetPartitionRemoteSize(tag_)); + VerifyAllXmppPeersNoInclusiveMulticastRoute(isid_list); +} + // Add Broadcast MAC routes from all XMPP peers. // Verify generated Inclusive Multicast routes in bgp.evpn.0. // Add Inclusive Multicast route from odd BGP peers. @@ -3849,6 +4004,7 @@ TEST_P(BgpEvpnManagerTest, UnicastAndMulticast6) { } INSTANTIATE_TEST_CASE_P(Default, BgpEvpnManagerTest, ::testing::Values(0, 4094)); +INSTANTIATE_TEST_CASE_P(Default, BgpPbbEvpnManagerTest, ::testing::Values(0, 4094)); class TestEnvironment : public ::testing::Environment { virtual ~TestEnvironment() { } diff --git a/src/bgp/test/bgp_route_test.cc b/src/bgp/test/bgp_route_test.cc index 92573d45537..e88e0dc5ee8 100644 --- a/src/bgp/test/bgp_route_test.cc +++ b/src/bgp/test/bgp_route_test.cc @@ -6,6 +6,8 @@ #include "base/test/task_test_util.h" #include "bgp/bgp_log.h" #include "bgp/bgp_server.h" +#include "bgp/extended-community/etree.h" +#include "bgp/extended-community/mac_mobility.h" #include "bgp/inet/inet_route.h" #include "bgp/origin-vn/origin_vn.h" #include "control-node/control_node.h" @@ -610,6 +612,227 @@ TEST_F(BgpRouteTest, PathCompareMed3) { EXPECT_EQ(0, path2.PathCompare(path1, true)); } +// +// Paths with sticky bit is chosen +// Test with path having same seq no and different sticky bit +// +TEST_F(BgpRouteTest, PathCompareSticky1) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + MacMobility mm1(100, true); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(mm1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + MacMobility mm2(100, false); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(mm2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(1, path1.PathCompare(path2, false)); + EXPECT_EQ(-1, path2.PathCompare(path1, false)); + EXPECT_EQ(1, path1.PathCompare(path2, true)); + EXPECT_EQ(-1, path2.PathCompare(path1, true)); +} + +// +// Paths with sticky bit is chosen. +// Test with path having different seq no and sticky bit +// +TEST_F(BgpRouteTest, PathCompareSticky2) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + MacMobility mm1(200, true); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(mm1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + MacMobility mm2(100, false); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(mm2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(1, path1.PathCompare(path2, false)); + EXPECT_EQ(-1, path2.PathCompare(path1, false)); + EXPECT_EQ(1, path1.PathCompare(path2, true)); + EXPECT_EQ(-1, path2.PathCompare(path1, true)); +} + +// +// Path with latest seq no is chosen +// +TEST_F(BgpRouteTest, PathCompareSeqNo) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + MacMobility mm1(100, true); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(mm1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + MacMobility mm2(200, true); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(mm2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(1, path1.PathCompare(path2, false)); + EXPECT_EQ(-1, path2.PathCompare(path1, false)); + EXPECT_EQ(1, path1.PathCompare(path2, true)); + EXPECT_EQ(-1, path2.PathCompare(path1, true)); +} + +// +// ECMP Test with seq no. +// With same seq-no and sticky route +// +TEST_F(BgpRouteTest, PathCompareSeqNo1) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + MacMobility mm1(100, true); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(mm1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + MacMobility mm2(100, true); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(mm2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(0, path1.PathCompare(path2, false)); + EXPECT_EQ(0, path2.PathCompare(path1, false)); + EXPECT_EQ(0, path1.PathCompare(path2, true)); + EXPECT_EQ(0, path2.PathCompare(path1, true)); +} + +// +// ECMP Test with seq no. +// With same seq-no and non-sticky route +// +TEST_F(BgpRouteTest, PathCompareSeqNo2) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + MacMobility mm1(100, false); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(mm1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + MacMobility mm2(100, false); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(mm2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(0, path1.PathCompare(path2, false)); + EXPECT_EQ(0, path2.PathCompare(path1, false)); + EXPECT_EQ(0, path1.PathCompare(path2, true)); + EXPECT_EQ(0, path2.PathCompare(path1, true)); +} +// +// ETree root Path is chosen +// +TEST_F(BgpRouteTest, PathCompareETree) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + ETree etree1(true, 100); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(etree1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + ETree etree2(false, 100); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(etree2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(1, path1.PathCompare(path2, false)); + EXPECT_EQ(-1, path2.PathCompare(path1, false)); + EXPECT_EQ(1, path1.PathCompare(path2, true)); + EXPECT_EQ(-1, path2.PathCompare(path1, true)); +} + +// +// ETree root ECMP test +// Both path being root path +// +TEST_F(BgpRouteTest, PathCompareETree1) { + boost::system::error_code ec; + BgpAttrDB *db = server_.attr_db(); + + ETree etree1(true, 100); + ExtCommunitySpec ext_spec1; + ext_spec1.communities.push_back(get_value(etree1.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec1; + spec1.push_back(&ext_spec1); + BgpAttrPtr attr1 = db->Locate(spec1); + PeerMock peer1(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path1(&peer1, BgpPath::BGP_XMPP, attr1, 0, 0); + + ETree etree2(true, 100); + ExtCommunitySpec ext_spec2; + ext_spec2.communities.push_back(get_value(etree2.GetExtCommunity().begin(), 8)); + BgpAttrSpec spec2; + spec2.push_back(&ext_spec2); + BgpAttrPtr attr2 = db->Locate(spec2); + PeerMock peer2(BgpProto::IBGP, Ip4Address::from_string("10.1.1.2", ec)); + BgpPath path2(&peer2, BgpPath::BGP_XMPP, attr2, 0, 0); + + EXPECT_EQ(0, path1.PathCompare(path2, false)); + EXPECT_EQ(0, path2.PathCompare(path1, false)); + EXPECT_EQ(0, path1.PathCompare(path2, true)); + EXPECT_EQ(0, path2.PathCompare(path1, true)); +} + // // Paths with 0 neighbor as are not compared w.r.t med. // Path with higher med happens to win since it has lower router id.