Skip to content

Commit

Permalink
xmpp message encoding for sticky and leaf flag
Browse files Browse the repository at this point in the history
Add support for rxing Mobility info and etree-leaf flag
Add support for seding (xmpp_msg_builder) for Mobility and etree-flag
Add tests for tx/rx of mobility info and etree-leaf in xmpp evpn UT

Change-Id: I5b2e5847f17b0686ab7ece2325c9cb795c82f413
Related-bug: #1645092
  • Loading branch information
bailkeri committed Dec 16, 2016
1 parent ca0a8eb commit f15fba4
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 28 deletions.
22 changes: 19 additions & 3 deletions src/bgp/bgp_xmpp_channel.cc
Expand Up @@ -22,6 +22,7 @@
#include "bgp/bgp_xmpp_peer_close.h"
#include "bgp/inet/inet_table.h"
#include "bgp/inet6/inet6_table.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"
Expand Down Expand Up @@ -1107,7 +1108,11 @@ bool BgpXmppChannel::ProcessItem(string vrf_name,
ext.communities.push_back(sg.GetExtCommunityValue());
}

if (item.entry.sequence_number) {
if (item.entry.mobility.seqno) {
MacMobility mm(item.entry.mobility.seqno,
item.entry.mobility.sticky);
ext.communities.push_back(mm.GetExtCommunityValue());
} else if (item.entry.sequence_number) {
MacMobility mm(item.entry.sequence_number);
ext.communities.push_back(mm.GetExtCommunityValue());
}
Expand Down Expand Up @@ -1386,7 +1391,11 @@ bool BgpXmppChannel::ProcessInet6Item(string vrf_name,
ext.communities.push_back(sg.GetExtCommunityValue());
}

if (item.entry.sequence_number) {
if (item.entry.mobility.seqno) {
MacMobility mm(item.entry.mobility.seqno,
item.entry.mobility.sticky);
ext.communities.push_back(mm.GetExtCommunityValue());
} else if (item.entry.sequence_number) {
MacMobility mm(item.entry.sequence_number);
ext.communities.push_back(mm.GetExtCommunityValue());
}
Expand Down Expand Up @@ -1646,11 +1655,18 @@ bool BgpXmppChannel::ProcessEnetItem(string vrf_name,
ext.communities.push_back(sg.GetExtCommunityValue());
}

if (item.entry.sequence_number) {
if (item.entry.mobility.seqno) {
MacMobility mm(item.entry.mobility.seqno,
item.entry.mobility.sticky);
ext.communities.push_back(mm.GetExtCommunityValue());
} else if (item.entry.sequence_number) {
MacMobility mm(item.entry.sequence_number);
ext.communities.push_back(mm.GetExtCommunityValue());
}

ETree etree(item.entry.etree_leaf);
ext.communities.push_back(etree.GetExtCommunityValue());

if (!ext.communities.empty())
attrs.push_back(&ext);

Expand Down
10 changes: 10 additions & 0 deletions src/bgp/community.h
Expand Up @@ -217,6 +217,16 @@ class ExtCommunity {
(val[1] == BgpExtendedCommunityEvpnSubType::MacMobility);
}


static bool is_etree(const ExtCommunityValue &val) {
//
// ETree extended community
//
return (val[0] == BgpExtendedCommunityType::Evpn) &&
(val[1] == BgpExtendedCommunityEvpnSubType::ETree);
}


static bool is_router_mac(const ExtCommunityValue &val) {
//
// Router MAC extended community
Expand Down
173 changes: 168 additions & 5 deletions src/bgp/test/bgp_xmpp_evpn_test.cc
Expand Up @@ -1426,17 +1426,21 @@ class BgpXmppEvpnTest2 : public ::testing::Test {
return true;
}

bool CheckRouteLocalPrefSequence(test::NetworkAgentMockPtr agent,
bool CheckRouteLocalPrefMobilityETreeLeaf(test::NetworkAgentMockPtr agent,
const string &network, const string &prefix,
int local_pref, int sequence) {
int local_pref, int sequence, bool sticky, bool leaf) {
task_util::TaskSchedulerLock lock;
const autogen::EnetItemType *rt =
agent->EnetRouteLookup(network, prefix);
if (!rt)
return false;
if (rt->entry.local_preference != local_pref)
return false;
if (rt->entry.sequence_number != sequence)
if (rt->entry.mobility.seqno != sequence)
return false;
if (rt->entry.mobility.sticky != sticky)
return false;
if (rt->entry.etree_leaf != leaf)
return false;
return true;
}
Expand All @@ -1455,10 +1459,20 @@ class BgpXmppEvpnTest2 : public ::testing::Test {
void VerifyRouteLocalPrefSequence(test::NetworkAgentMockPtr agent,
const string &network, const string &prefix,
int local_pref, uint32_t sequence) {
TASK_UTIL_EXPECT_TRUE(CheckRouteLocalPrefSequence(
agent, network, prefix, local_pref, sequence));
TASK_UTIL_EXPECT_TRUE(CheckRouteLocalPrefMobilityETreeLeaf(
agent, network, prefix, local_pref, sequence,
test::RouteAttributes::kDefaultSticky,
test::RouteAttributes::kDefaultETreeLeaf));
}

void VerifyRouteLocalPrefMobilityETreeLeaf(test::NetworkAgentMockPtr agent,
const string &network, const string &prefix,
int local_pref, uint32_t sequence, bool sticky, bool etree_leaf) {
TASK_UTIL_EXPECT_TRUE(CheckRouteLocalPrefMobilityETreeLeaf(
agent, network, prefix, local_pref, sequence, sticky, etree_leaf));
}


EventManager evm_;
ServerThread thread_;
BgpServerTestPtr bs_x_;
Expand Down Expand Up @@ -1766,6 +1780,155 @@ TEST_F(BgpXmppEvpnTest2, RouteAddWithLocalPrefSequence) {
agent_b_->SessionDown();
}

//
// Routes with mobility info from 2 agents are advertised to each other.
//
TEST_F(BgpXmppEvpnTest2, RouteAddWithStickyBit) {
Configure();
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_->EnetSubscribe("blue", 1);
agent_b_->EnetSubscribe("blue", 1);

// Add route from agent A with sticky bit and ETree Leaf mode
stringstream eroute_a;
eroute_a << "aa:00:00:00:00:01,10.1.1.1/32";
test::NextHop nexthop1("192.168.1.1");
test::RouteAttributes attr1(100, 100, 99, true);
agent_a_->AddEnetRoute("blue", eroute_a.str(), nexthop1, attr1);
task_util::WaitForIdle();

// Add route from agent B with non-sticky bit and ETree Root mode
stringstream eroute_b;
eroute_b << "bb:00:00:00:00:01,10.1.2.1/32";
test::NextHop nexthop2("192.168.1.2");
test::RouteAttributes attr2(100, 100, 88, false);
agent_b_->AddEnetRoute("blue", eroute_b.str(), nexthop2, attr2);
task_util::WaitForIdle();

// Verify that routes showed up on the agents.
TASK_UTIL_EXPECT_EQ(2, agent_a_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(2, agent_a_->EnetRouteCount("blue"));
TASK_UTIL_EXPECT_EQ(2, agent_b_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(2, agent_b_->EnetRouteCount("blue"));

// Verify local pref and sequence on A.
VerifyRouteLocalPrefMobilityETreeLeaf(agent_a_, "blue", eroute_a.str(),
100, 99, true, test::RouteAttributes::kDefaultETreeLeaf);
VerifyRouteLocalPrefMobilityETreeLeaf(agent_a_, "blue", eroute_b.str(),
100, 88, false, test::RouteAttributes::kDefaultETreeLeaf);

// Verify local pref and sequence on B.
VerifyRouteLocalPrefMobilityETreeLeaf(agent_b_, "blue", eroute_a.str(),
100, 99, true, test::RouteAttributes::kDefaultETreeLeaf);
VerifyRouteLocalPrefMobilityETreeLeaf(agent_b_, "blue", eroute_b.str(),
100, 88, false, test::RouteAttributes::kDefaultETreeLeaf);

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

// Delete route from agent B.
agent_b_->DeleteEnetRoute("blue", eroute_b.str());
task_util::WaitForIdle();

// Verify that there are no routes on the agents.
TASK_UTIL_EXPECT_EQ(0, agent_a_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(0, agent_a_->EnetRouteCount("blue"));
TASK_UTIL_EXPECT_EQ(0, agent_b_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(0, agent_b_->EnetRouteCount("blue"));

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

//
// Routes with mobility info and etree-leaf info from 2 agents are
// advertised to each other.
//
TEST_F(BgpXmppEvpnTest2, RouteAddWithETreeLeaf) {
Configure();
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_->EnetSubscribe("blue", 1);
agent_b_->EnetSubscribe("blue", 1);

// Add route from agent A with sticky bit and ETree Leaf mode
stringstream eroute_a;
eroute_a << "aa:00:00:00:00:01,10.1.1.1/32";
test::NextHop nexthop1("192.168.1.1");
test::RouteAttributes attr1(202, 202, 2002, true, true);
agent_a_->AddEnetRoute("blue", eroute_a.str(), nexthop1, attr1);
task_util::WaitForIdle();

// Add route from agent B with non-sticky bit and ETree Root mode
stringstream eroute_b;
eroute_b << "bb:00:00:00:00:01,10.1.2.1/32";
test::NextHop nexthop2("192.168.1.2");
test::RouteAttributes attr2(202, 202, 2002, false, false);
agent_b_->AddEnetRoute("blue", eroute_b.str(), nexthop2, attr2);
task_util::WaitForIdle();

// Verify that routes showed up on the agents.
TASK_UTIL_EXPECT_EQ(2, agent_a_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(2, agent_a_->EnetRouteCount("blue"));
TASK_UTIL_EXPECT_EQ(2, agent_b_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(2, agent_b_->EnetRouteCount("blue"));

// Verify local pref and sequence on A.
VerifyRouteLocalPrefMobilityETreeLeaf(agent_a_, "blue", eroute_a.str(), 202, 2002, true, true);
VerifyRouteLocalPrefMobilityETreeLeaf(agent_a_, "blue", eroute_b.str(), 202, 2002, false, false);

// Verify local pref and sequence on B.
VerifyRouteLocalPrefMobilityETreeLeaf(agent_b_, "blue", eroute_a.str(), 202, 2002, true, true);
VerifyRouteLocalPrefMobilityETreeLeaf(agent_b_, "blue", eroute_b.str(), 202, 2002, false, false);

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

// Delete route from agent B.
agent_b_->DeleteEnetRoute("blue", eroute_b.str());
task_util::WaitForIdle();

// Verify that there are no routes on the agents.
TASK_UTIL_EXPECT_EQ(0, agent_a_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(0, agent_a_->EnetRouteCount("blue"));
TASK_UTIL_EXPECT_EQ(0, agent_b_->EnetRouteCount());
TASK_UTIL_EXPECT_EQ(0, agent_b_->EnetRouteCount("blue"));

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

//
// Route from 1 agent shows up on the other.
// Update route and verify the next hop and label.
Expand Down
23 changes: 18 additions & 5 deletions src/bgp/xmpp_message_builder.cc
Expand Up @@ -11,6 +11,7 @@
#include "bgp/ipeer.h"
#include "bgp/bgp_server.h"
#include "bgp/bgp_table.h"
#include "bgp/extended-community/etree.h"
#include "bgp/extended-community/mac_mobility.h"
#include "bgp/ermvpn/ermvpn_route.h"
#include "bgp/evpn/evpn_route.h"
Expand Down Expand Up @@ -70,7 +71,8 @@ BgpXmppMessage::BgpXmppMessage()
is_reachable_(false),
cache_routes_(false),
repr_valid_(false),
sequence_number_(0) {
mobility_(0, false),
etree_leaf_(false) {
msg_begin_.reserve(kMaxFromToLength);
}

Expand Down Expand Up @@ -191,7 +193,9 @@ void BgpXmppMessage::AddIpReach(const BgpRoute *route,
item.entry.virtual_network = GetVirtualNetwork(route, roattr);
item.entry.local_preference = roattr->attr()->local_pref();
item.entry.med = roattr->attr()->med();
item.entry.sequence_number = sequence_number_;
item.entry.sequence_number = mobility_.sequence_number;
item.entry.mobility.seqno = mobility_.sequence_number;
item.entry.mobility.sticky = mobility_.sticky;

assert(!roattr->nexthop_list().empty());

Expand Down Expand Up @@ -299,7 +303,10 @@ void BgpXmppMessage::AddEnetReach(const BgpRoute *route,
item.entry.virtual_network = GetVirtualNetwork(route, roattr);
item.entry.local_preference = roattr->attr()->local_pref();
item.entry.med = roattr->attr()->med();
item.entry.sequence_number = sequence_number_;
item.entry.sequence_number = mobility_.sequence_number;
item.entry.mobility.seqno = mobility_.sequence_number;
item.entry.mobility.sticky = mobility_.sticky;
item.entry.etree_leaf = etree_leaf_;

for (vector<int>::const_iterator it = security_group_list_.begin();
it != security_group_list_.end(); ++it) {
Expand Down Expand Up @@ -477,7 +484,9 @@ void BgpXmppMessage::ProcessCommunity(const Community *community) {
}

void BgpXmppMessage::ProcessExtCommunity(const ExtCommunity *ext_community) {
sequence_number_ = 0;
mobility_.sequence_number = 0;
mobility_.sticky = false;
etree_leaf_ = false;
security_group_list_.clear();
load_balance_attribute_ = LoadBalance::LoadBalanceAttribute();
if (ext_community == NULL)
Expand All @@ -494,10 +503,14 @@ void BgpXmppMessage::ProcessExtCommunity(const ExtCommunity *ext_community) {
security_group_list_.push_back(sg.security_group_id());
} else if (ExtCommunity::is_mac_mobility(*iter)) {
MacMobility mm(*iter);
sequence_number_ = mm.sequence_number();
mobility_.sequence_number = mm.sequence_number();
mobility_.sticky = mm.sticky();
} else if (ExtCommunity::is_load_balance(*iter)) {
LoadBalance load_balance(*iter);
load_balance.FillAttribute(&load_balance_attribute_);
} else if (ExtCommunity::is_etree(*iter)) {
ETree etree(*iter);
etree_leaf_ = etree.leaf();
}
}
}
Expand Down
13 changes: 12 additions & 1 deletion src/bgp/xmpp_message_builder.h
Expand Up @@ -58,6 +58,15 @@ class BgpXmppMessage : public Message {
std::string *repr_;
};

struct MobilityInfo {
public:
MobilityInfo(uint32_t seqno, bool sticky)
: sequence_number(seqno), sticky(sticky) {
}
uint32_t sequence_number;
bool sticky;
};

virtual void Reset();
void EncodeNextHop(const BgpRoute *route,
const RibOutAttr::NextHop &nexthop,
Expand Down Expand Up @@ -93,7 +102,9 @@ class BgpXmppMessage : public Message {
std::string msg_begin_;
std::string repr_;
pugi::xml_document doc_;
uint32_t sequence_number_;
MobilityInfo mobility_;
bool etree_leaf_;

std::vector<int> security_group_list_;
std::vector<std::string> community_list_;
LoadBalance::LoadBalanceAttribute load_balance_attribute_;
Expand Down

0 comments on commit f15fba4

Please sign in to comment.