Skip to content

Commit

Permalink
Merge "Translate med to local pref for routes learnt from eBGP CNs"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Apr 4, 2017
2 parents 9e15306 + 501a657 commit d2c1e19
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 8 deletions.
37 changes: 35 additions & 2 deletions src/bgp/bgp_peer.cc
Expand Up @@ -39,6 +39,7 @@ using boost::tie;
using std::copy;
using std::dec;
using std::map;
using std::numeric_limits;
using std::ostringstream;
using std::string;
using std::vector;
Expand Down Expand Up @@ -442,6 +443,13 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
oss2 << peer_name();
uve_key_str_ = oss2.str();

if (router_type_ == "control-node" ||
router_type_ == "external-control-node") {
peer_is_control_node_ = true;
} else {
peer_is_control_node_ = false;
}

membership_req_pending_ = 0;
BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
BGP_PEER_DIR_NA, "Created");
Expand Down Expand Up @@ -720,9 +728,15 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
if (router_type_ != config->router_type()) {
router_type_ = config->router_type();
peer_info.set_router_type(router_type_);
resolve_paths_ = (config->router_type() == "bgpaas-client"),
resolve_paths_ = (config->router_type() == "bgpaas-client");
clear_session = true;
}
if (router_type_ == "control-node" ||
router_type_ == "external-control-node") {
peer_is_control_node_ = true;
} else {
peer_is_control_node_ = false;
}

// Check if there is any change in the peer address.
// If the peer address is changing, remove the key for the older address.
Expand Down Expand Up @@ -774,7 +788,6 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
}

peer_type_ = (peer_as_ == local_as_) ? BgpProto::IBGP : BgpProto::EBGP;

if (old_type != PeerType()) {
peer_info.set_peer_type(
PeerType() == BgpProto::IBGP ? "internal" : "external");
Expand Down Expand Up @@ -1637,9 +1650,29 @@ uint32_t BgpPeer::GetPathFlags(Address::Family family,
return flags;
}

uint32_t BgpPeer::GetLocalPrefFromMed(uint32_t med) const {
if (peer_type_ != BgpProto::EBGP)
return 0;
if (!peer_is_control_node_)
return 0;
if (med == 0)
return 0;
if (med == 100)
return 200;
if (med == 200)
return 100;
return numeric_limits<uint32_t>::max() - med;
}

void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);

uint32_t local_pref = GetLocalPrefFromMed(attr->med());
if (local_pref) {
attr = server_->attr_db()->ReplaceLocalPreferenceAndLocate(attr.get(),
local_pref);
}

uint32_t reach_count = 0, unreach_count = 0;
RoutingInstance *instance = GetRoutingInstance();
if (msg->nlri.size() || msg->withdrawn_routes.size()) {
Expand Down
2 changes: 2 additions & 0 deletions src/bgp/bgp_peer.h
Expand Up @@ -376,6 +376,7 @@ class BgpPeer : public IPeer {
virtual bool MembershipPathCallback(DBTablePartBase *tpart,
BgpRoute *route, BgpPath *path);
uint32_t GetPathFlags(Address::Family family, const BgpAttr *attr) const;
uint32_t GetLocalPrefFromMed(uint32_t med) const;
virtual bool MpNlriAllowed(uint16_t afi, uint8_t safi);
BgpAttrPtr GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr);
template <typename TableT, typename PrefixT>
Expand Down Expand Up @@ -410,6 +411,7 @@ class BgpPeer : public IPeer {
std::string peer_name_;
std::string peer_basename_;
std::string router_type_; // bgp_schema.xsd:BgpRouterType
bool peer_is_control_node_;
mutable std::string to_str_;
mutable std::string uve_key_str_;
const BgpNeighborConfig *config_;
Expand Down
76 changes: 70 additions & 6 deletions src/bgp/test/bgp_xmpp_inetvpn_test.cc
Expand Up @@ -262,6 +262,7 @@ static const char *config_2_control_nodes_different_asn = "\
<identifier>192.168.0.1</identifier>\
<address>127.0.0.1</address>\
<port>%d</port>\
<router-type>external-control-node</router-type>\
<session to=\'Y\'>\
<address-families>\
<family>route-target</family>\
Expand All @@ -274,6 +275,7 @@ static const char *config_2_control_nodes_different_asn = "\
<identifier>192.168.0.2</identifier>\
<address>127.0.0.2</address>\
<port>%d</port>\
<router-type>external-control-node</router-type>\
<session to=\'X\'>\
<address-families>\
<family>route-target</family>\
Expand Down Expand Up @@ -939,16 +941,15 @@ TEST_F(BgpXmppInetvpn2ControlNodeTest, RouteExplicitMed) {
agent_a_->Subscribe("blue", 1);
agent_b_->Subscribe("blue", 1);

// Add route from agent A with local preference 100 and med 500.
// Add route from agent A with med 500.
stringstream route_a;
route_a << "10.1.1.1/32";
agent_a_->AddRoute("blue", route_a.str(), "192.168.1.1", 100, 500);
agent_a_->AddRoute("blue", route_a.str(), "192.168.1.1", 0, 500);
task_util::WaitForIdle();

// Verify that route showed up on agents A and B with local preference 100
// and med 500.
VerifyRouteExists(agent_a_, "blue", route_a.str(), "192.168.1.1", 100, 500);
VerifyRouteExists(agent_b_, "blue", route_a.str(), "192.168.1.1", 100, 500);
// Verify that route showed up on agents A and B with med 500.
VerifyRouteExists(agent_a_, "blue", route_a.str(), "192.168.1.1", 0, 500);
VerifyRouteExists(agent_b_, "blue", route_a.str(), "192.168.1.1", 0, 500);

// Delete route from agent A.
agent_a_->DeleteRoute("blue", route_a.str());
Expand Down Expand Up @@ -1027,6 +1028,69 @@ TEST_F(BgpXmppInetvpn2ControlNodeTest, RouteLocalPrefToMed) {
agent_b_->SessionDown();
}

//
// Route added with local preference has auto calculated local preference
// (via med) in the other AS.
//
TEST_F(BgpXmppInetvpn2ControlNodeTest, RouteLocalPrefToLocalPref) {
Configure(config_2_control_nodes_different_asn);
task_util::WaitForIdle();

// Create XMPP Agent A connected to XMPP server X.
agent_a_.reset(
new test::NetworkAgentMock(&evm_, "agent-a", xs_x_->GetPort(),
"127.0.0.1", "127.0.0.1"));
TASK_UTIL_EXPECT_TRUE(agent_a_->IsEstablished());

// Create XMPP Agent B connected to XMPP server Y.
agent_b_.reset(
new test::NetworkAgentMock(&evm_, "agent-b", xs_y_->GetPort(),
"127.0.0.2", "127.0.0.2"));
TASK_UTIL_EXPECT_TRUE(agent_b_->IsEstablished());

// Register to blue instance
agent_a_->Subscribe("blue", 1);
agent_b_->Subscribe("blue", 1);

// Add route from agent A with local preference 100.
stringstream route_a;
route_a << "10.1.1.1/32";
agent_a_->AddRoute("blue", route_a.str(), "192.168.1.1", 100);
task_util::WaitForIdle();

// Verify that route showed up on agents A and B with local preference 100.
VerifyRouteExists(agent_a_, "blue", route_a.str(), "192.168.1.1", 100);
VerifyRouteExists(agent_b_, "blue", route_a.str(), "192.168.1.1", 100);

// Change route from agent A to local preference 200.
agent_a_->AddRoute("blue", route_a.str(), "192.168.1.1", 200);
task_util::WaitForIdle();

// Verify that route showed up on agents A and B with local preference 200.
VerifyRouteExists(agent_a_, "blue", route_a.str(), "192.168.1.1", 200);
VerifyRouteExists(agent_b_, "blue", route_a.str(), "192.168.1.1", 200);

// Change route from agent A to local preference 400.
agent_a_->AddRoute("blue", route_a.str(), "192.168.1.1", 400);
task_util::WaitForIdle();

// Verify that route showed up on agents A and B with local preference 400.
VerifyRouteExists(agent_a_, "blue", route_a.str(), "192.168.1.1", 400);
VerifyRouteExists(agent_b_, "blue", route_a.str(), "192.168.1.1", 400);

// Delete route from agent A.
agent_a_->DeleteRoute("blue", route_a.str());
task_util::WaitForIdle();

// Verify that route is deleted at agents A and B.
VerifyRouteNoExists(agent_a_, "blue", route_a.str());
VerifyRouteNoExists(agent_b_, "blue", route_a.str());

// Close the sessions.
agent_a_->SessionDown();
agent_b_->SessionDown();
}

//
// Route is not advertised to agent that subscribed with no-ribout.
//
Expand Down

0 comments on commit d2c1e19

Please sign in to comment.