From 37edc22d1b090aa52c438e015a0e2452bc44a419 Mon Sep 17 00:00:00 2001 From: Prakash Bailkeri Date: Fri, 3 Feb 2017 18:41:46 +0530 Subject: [PATCH] PBB EVPN changes Issues fixed: 1. Avoid generating multiple olist when multiple bridge domains are linked to b-comp vn 2. Test to validate above fix. 3. Path selection to take into account sticky and etree attribute 4. Sandesh introspect display of etree community 5. Sandesh introspect to display pbb mode on RI(both config and oper data) Change-Id: I2858af0d1dfc280163da10379331a6bf1b58638a Related-bug: #1645092 --- src/bgp/bgp_attr.cc | 29 ++ src/bgp/bgp_attr.h | 2 + src/bgp/bgp_config.cc | 2 + src/bgp/bgp_config.h | 9 + src/bgp/bgp_config_ifmap.cc | 16 + src/bgp/bgp_config_parser.cc | 13 + src/bgp/bgp_evpn.cc | 10 + src/bgp/bgp_path.cc | 6 + src/bgp/bgp_peer.sandesh | 2 + src/bgp/bgp_route.cc | 6 +- src/bgp/bgp_show_config.cc | 1 + src/bgp/bgp_show_routing_instance.cc | 1 + src/bgp/routing-instance/routing_instance.cc | 11 + src/bgp/routing-instance/routing_instance.h | 2 + src/bgp/test/bgp_evpn_manager_test.cc | 344 ++++++++++++++----- src/bgp/test/bgp_route_test.cc | 223 ++++++++++++ 16 files changed, 582 insertions(+), 95 deletions(-) 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.