diff --git a/src/bgp/bgp_path.cc b/src/bgp/bgp_path.cc index 5e29d8f51af..6f8ad49a092 100644 --- a/src/bgp/bgp_path.cc +++ b/src/bgp/bgp_path.cc @@ -128,6 +128,15 @@ int BgpPath::PathCompare(const BgpPath &rhs, bool allow_ecmp) const { return 0; } +bool BgpPath::PathSameNeighborAs(const BgpPath &rhs) const { + const BgpAttr *rattr = rhs.GetAttr(); + if (!peer_ || peer_->PeerType() != BgpProto::EBGP) + return false; + if (!rhs.peer_ || rhs.peer_->PeerType() != BgpProto::EBGP) + return false; + return (attr_->neighbor_as() == rattr->neighbor_as()); +} + void BgpPath::UpdatePeerRefCount(int count) const { if (!peer_) return; diff --git a/src/bgp/bgp_path.h b/src/bgp/bgp_path.h index c5014c74b1b..653be290730 100644 --- a/src/bgp/bgp_path.h +++ b/src/bgp/bgp_path.h @@ -126,6 +126,7 @@ class BgpPath : public Path { // Select one path over other int PathCompare(const BgpPath &rhs, bool allow_ecmp) const; + bool PathSameNeighborAs(const BgpPath &rhs) const; private: const IPeer *peer_; diff --git a/src/bgp/routing-instance/rtarget_group_mgr.cc b/src/bgp/routing-instance/rtarget_group_mgr.cc index 5b6b652bfdf..4c457bdeb97 100644 --- a/src/bgp/routing-instance/rtarget_group_mgr.cc +++ b/src/bgp/routing-instance/rtarget_group_mgr.cc @@ -115,6 +115,7 @@ void RTargetGroupMgr::BuildRTargetDistributionGraph(BgpTable *table, return; } + const BgpPath *best_ebgp_path = NULL; for (Route::PathList::iterator it = rt->GetPathList().begin(); it != rt->GetPathList().end(); it++) { BgpPath *path = static_cast(it.operator->()); @@ -124,6 +125,14 @@ void RTargetGroupMgr::BuildRTargetDistributionGraph(BgpTable *table, continue; const BgpPeer *peer = static_cast(path->GetPeer()); + if (peer->PeerType() == BgpProto::EBGP) { + if (!best_ebgp_path) { + best_ebgp_path = path; + } else if (!best_ebgp_path->PathSameNeighborAs(*path)) { + continue; + } + } + std::pair ret = peer_list.insert(std::pair(peer, RtGroup::RTargetRouteList())); diff --git a/src/bgp/test/bgp_xmpp_rtarget_test.cc b/src/bgp/test/bgp_xmpp_rtarget_test.cc index 376ffdbb9af..3914246f604 100644 --- a/src/bgp/test/bgp_xmpp_rtarget_test.cc +++ b/src/bgp/test/bgp_xmpp_rtarget_test.cc @@ -3382,6 +3382,36 @@ TEST_F(BgpXmppRTargetTest, PathSelection5) { DeleteInetRoute(mx_.get(), NULL, "blue", BuildPrefix()); } +// +// If RTargetRoute is received from EBGP peers in different ASes, VPN routes +// should be sent to peers in AS of the best EBGP path. +// +TEST_F(BgpXmppRTargetTest, PathSelection6) { + Unconfigure(); + task_util::WaitForIdle(); + Configure(64496, 64497, 64498); + agent_a_1_->Subscribe("blue", 1); + + AddRouteTarget(cn1_.get(), "blue", "target:1:1001"); + AddRouteTarget(cn2_.get(), "blue", "target:1:1001"); + task_util::WaitForIdle(); + + RTargetRoute *rtgt_rt = + VerifyRTargetRouteExists(mx_.get(), "64496:target:1:1001"); + TASK_UTIL_EXPECT_EQ(2, rtgt_rt->count()); + VerifyRTargetRouteNoExists(mx_.get(), "64497:target:1:1001"); + + AddInetRoute(mx_.get(), NULL, "blue", BuildPrefix()); + + BgpRoute *inet_rt = + VerifyInetRouteExists(cn1_.get(), "blue", BuildPrefix()); + usleep(50000); + TASK_UTIL_EXPECT_EQ(1, inet_rt->count()); + VerifyInetRouteNoExists(cn2_.get(), "blue", BuildPrefix()); + + DeleteInetRoute(mx_.get(), NULL, "blue", BuildPrefix()); +} + // // Local AS is different than the global AS. // Verify that RTarget route prefixes use local AS while the route target