Skip to content

Commit

Permalink
Merge "Update CompositeNH on VMI policy status change." into R3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Jul 20, 2016
2 parents 41fae12 + 3151aa2 commit 16a4aa2
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 16 deletions.
57 changes: 57 additions & 0 deletions src/vnsw/agent/oper/inet_unicast_route.cc
Expand Up @@ -761,10 +761,14 @@ bool InetUnicastRouteEntry::EcmpAddPath(AgentPath *path) {
ret = true;
} else if (ecmp) {
AgentPath *ecmp_path = FindPath(agent->ecmp_peer());
bool updated = UpdateComponentNH(agent, ecmp_path, path);
ret = SyncEcmpPath(ecmp_path, path->sg_list(),
path->communities(), path->path_preference(),
path->tunnel_bmap(),
path->ecmp_load_balance());
if (updated) {
ret = true;
}
}

return ret;
Expand Down Expand Up @@ -813,6 +817,59 @@ void InetUnicastRouteEntry::AppendEcmpPath(Agent *agent,
GETPEERNAME(agent->ecmp_peer()));
}

/* When label of VMI changes and if that VMI (ie VMI's InterfaceNH) is part of
* ECMP, then update the CompositeNH for ECMP route to point to right label for
* that VMI. Label of VMI can change when policy-status of VMI changes */
bool InetUnicastRouteEntry::UpdateComponentNH(Agent *agent,
AgentPath *ecmp_path,
AgentPath *path) {
if (!ecmp_path) {
return false;
}
//Build ComponentNHKey for new path
DBEntryBase::KeyPtr key = path->ComputeNextHop(agent)->GetDBRequestKey();
NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
nh_key->SetPolicy(false);

ComponentNHKeyList component_nh_key_list;
const CompositeNH *comp_nh =
static_cast<const CompositeNH *>(ecmp_path->ComputeNextHop(agent));
bool updated = comp_nh->UpdateComponentNHKey(path->label(), nh_key,
component_nh_key_list);

if (!updated) {
return false;
}

// Form the request for Inet4UnicastEcmpRoute and invoke AddChangePath
DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
nh_req.key.reset(new CompositeNHKey(Composite::LOCAL_ECMP,
false, component_nh_key_list,
vrf()->GetName()));
nh_req.data.reset(new CompositeNHData());

InetUnicastRouteEntry::ModifyEcmpPath(addr_, plen_,
ecmp_path->dest_vn_list(),
ecmp_path->label(), true, vrf()->GetName(),
ecmp_path->sg_list(), ecmp_path->communities(),
ecmp_path->path_preference(),
ecmp_path->tunnel_bmap(),
ecmp_path->ecmp_load_balance(),
nh_req, agent, ecmp_path);

//Make MPLS label point to updated composite NH
MplsLabel::CreateEcmpLabel(agent, ecmp_path->label(), Composite::LOCAL_ECMP,
component_nh_key_list, vrf()->GetName());

RouteInfo rt_info;
FillTrace(rt_info, AgentRoute::CHANGE_PATH, path);
AgentRouteTable *table = static_cast<AgentRouteTable *>(get_table());
OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info);
AGENT_ROUTE_LOG(table, "Path Update", ToString(), vrf()->GetName(),
GETPEERNAME(agent->ecmp_peer()));
return true;
}

void InetUnicastRouteEntry::DeleteComponentNH(Agent *agent, AgentPath *path) {
AgentPath *ecmp_path = FindPath(agent->ecmp_peer());

Expand Down
1 change: 1 addition & 0 deletions src/vnsw/agent/oper/inet_unicast_route.h
Expand Up @@ -73,6 +73,7 @@ class InetUnicastRouteEntry : public AgentRoute {
virtual bool EcmpDeletePath(AgentPath *path);
void AppendEcmpPath(Agent *agent, AgentPath *path);
void DeleteComponentNH(Agent *agent, AgentPath *path);
bool UpdateComponentNH(Agent *agent, AgentPath *ecmp_path, AgentPath *path);

AgentPath *AllocateEcmpPath(Agent *agent, const AgentPath *path1,
const AgentPath *path2);
Expand Down
19 changes: 19 additions & 0 deletions src/vnsw/agent/oper/nexthop.cc
Expand Up @@ -1828,6 +1828,25 @@ void CompositeNHKey::erase(ComponentNHKeyPtr nh_key) {
}
}

bool CompositeNH::UpdateComponentNHKey(uint32_t label, NextHopKey *nh_key,
ComponentNHKeyList &component_nh_key_list) const {
bool ret = false;
ComponentNHKeyList::const_iterator it = component_nh_key_list_.begin();
for (;it != component_nh_key_list_.end(); it++) {
const NextHopKey *lhs = (*it)->nh_key();
uint32_t new_label = (*it)->label();
if((*it) && (*it)->label() != label && lhs->IsEqual(*nh_key)) {
new_label = label;
ret = true;
}
std::auto_ptr<const NextHopKey> nh_akey(lhs->Clone());
ComponentNHKeyPtr comp_nh_key_ptr(new ComponentNHKey(new_label,
nh_akey));
component_nh_key_list.push_back(comp_nh_key_ptr);
}
return ret;
}

ComponentNHKeyList CompositeNH::AddComponentNHKey(ComponentNHKeyPtr cnh) const {
Agent *agent = static_cast<NextHopTable *>(get_table())->agent();
const NextHop *nh = static_cast<const NextHop *>(agent->nexthop_table()->
Expand Down
2 changes: 2 additions & 0 deletions src/vnsw/agent/oper/nexthop.h
Expand Up @@ -1359,6 +1359,8 @@ class CompositeNH : public NextHop {
component_nh_key) const;
ComponentNHKeyList DeleteComponentNHKey(ComponentNHKeyPtr
component_nh_key) const;
bool UpdateComponentNHKey(uint32_t label, NextHopKey *nh_key,
ComponentNHKeyList &component_nh_key_list) const;
ComponentNHList& component_nh_list() {
return component_nh_list_;
}
Expand Down
101 changes: 85 additions & 16 deletions src/vnsw/agent/oper/test/test_intf_policy.cc
Expand Up @@ -3,22 +3,6 @@
*/

#include "base/os.h"
#if 0
#include <sys/socket.h>

#include <net/if.h>

#ifdef __linux__
#include <linux/netlink.h>
#include <linux/if_tun.h>
#include <linux/if_packet.h>
#endif

#ifdef __FreeBSD__
#include <sys/sockio.h>
#include <ifaddrs.h>
#endif
#endif
#include "testing/gunit.h"

#include <base/logging.h>
Expand Down Expand Up @@ -54,6 +38,10 @@
#define vm1_ip "11.1.1.1"
#define vm2_ip "11.1.1.2"

IpamInfo ipam_info[] = {
{"1.1.1.0", 24, "1.1.1.10"},
};

void RouterIdDepInit(Agent *agent) {
}

Expand Down Expand Up @@ -199,6 +187,15 @@ class PolicyTest : public ::testing::Test {
flow_proto_ = agent_->pkt()->get_flow_proto();
}

void SetUp() {
AddIPAM("vn1", ipam_info, 1);
client->WaitForIdle();
}
void TearDown() {
WAIT_FOR(1000, 1000, agent_->vrf_table()->Size() == 1);
DelIPAM("vn1");
client->WaitForIdle();
}
void SetPolicyDisabledStatus(struct PortInfo *input, bool status) {
ostringstream str;

Expand Down Expand Up @@ -697,6 +694,78 @@ TEST_F(PolicyTest, IntfPolicyDisable_Flow) {
EXPECT_EQ(0U, flow_proto_->FlowCount());
}

TEST_F(PolicyTest, EcmpNH_1) {
//Create mutliple VM interface with same IP
struct PortInfo input1[] = {
{"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1},
{"vnet2", 2, "1.1.1.1", "00:00:00:02:02:01", 1, 2},
};

CreateVmportWithEcmp(input1, 2, 1);
client->WaitForIdle();

EXPECT_TRUE(VmPortActive(input1, 0));
EXPECT_TRUE(VmPortActive(input1, 1));
const VmInterface *intf1 = VmInterfaceGet(input1[0].intf_id);
EXPECT_TRUE(intf1 != NULL);
const VmInterface *intf2 = VmInterfaceGet(input1[1].intf_id);
EXPECT_TRUE(intf2 != NULL);
//Check that route points to composite NH,
//with 2 members
Ip4Address ip = Ip4Address::from_string("1.1.1.1");
InetUnicastRouteEntry *rt = RouteGet("vrf1", ip, 32);
EXPECT_TRUE(rt != NULL);
const NextHop *nh = rt->GetActiveNextHop();
EXPECT_TRUE(nh->GetType() == NextHop::COMPOSITE);
const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
EXPECT_TRUE(comp_nh->ComponentNHCount() == 2);

//Get the MPLS label corresponding to this path and verify
//that mpls label also has 2 component NH
uint32_t mpls_label = rt->GetActiveLabel();
EXPECT_TRUE(FindMplsLabel(MplsLabel::VPORT_NH, mpls_label));
EXPECT_TRUE(nh->GetType() == NextHop::COMPOSITE);
comp_nh = static_cast<const CompositeNH *>(nh);
EXPECT_TRUE(comp_nh->ComponentNHCount() == 2);
EXPECT_TRUE(comp_nh->PolicyEnabled() == false);

uint32_t label1 = comp_nh->Get(0)->label();
uint32_t label2 = comp_nh->Get(1)->label();
uint32_t vnet1_label = intf1->label();

EXPECT_TRUE(label1 == intf1->label());
EXPECT_TRUE(label2 == intf2->label());

WAIT_FOR(100, 1000, ((VmPortPolicyEnabled(input1, 0)) == true));

//Disable policy on vnet1 VMI
SetPolicyDisabledStatus(&input1[0], true);
client->WaitForIdle();

//Verify that policy status of interfaces
WAIT_FOR(100, 1000, ((VmPortPolicyEnabled(input1, 0)) == false));

//Verify that vnet1's label has changed after disabling policy on it.
EXPECT_TRUE(vnet1_label != intf1->label());

nh = rt->GetActiveNextHop();
EXPECT_TRUE(nh->GetType() == NextHop::COMPOSITE);
comp_nh = static_cast<const CompositeNH *>(nh);
//Verify that Component NH part of CompositeNH has its label updated after
//policy status change on vnet1
EXPECT_TRUE(label1 != comp_nh->Get(0)->label());
EXPECT_TRUE(comp_nh->Get(0)->label() == intf1->label());


DeleteVmportEnv(input1, 2, true, 1);
client->WaitForIdle();
WAIT_FOR(100, 1000, (VrfFind("vrf1") == false));
EXPECT_FALSE(RouteFind("vrf1", ip, 32));

//Expect MPLS label to be not present
EXPECT_FALSE(FindMplsLabel(MplsLabel::VPORT_NH, mpls_label));
}

int main(int argc, char **argv) {
GETUSERARGS();

Expand Down

0 comments on commit 16a4aa2

Please sign in to comment.