Skip to content

Commit

Permalink
Merge "* Handle RPF check failure for floating-ip ecmp." into R3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Apr 9, 2016
2 parents 0b22387 + 9751eaf commit ecf90a7
Show file tree
Hide file tree
Showing 6 changed files with 1,045 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/vnsw/agent/pkt/flow_entry.cc
Expand Up @@ -1639,7 +1639,7 @@ void FlowEntry::SetComponentIndex(const NextHopKey *nh_key,
const IpAddress dip = rflow->key().src_addr;
InetUnicastRouteEntry *rt =
static_cast<InetUnicastRouteEntry *>(FlowEntry::GetUcRoute(vrf, dip));
if (!rt || rt->GetActiveNextHop()->GetType() != NextHop::COMPOSITE) {
if (!rt ) {
rflow->set_ecmp_rpf_nh(0);
return;
}
Expand Down
7 changes: 7 additions & 0 deletions src/vnsw/agent/pkt/test/SConscript
Expand Up @@ -43,6 +43,13 @@ test_sg_flowv6 = AgentEnv.MakeTestCmd(env, 'test_sg_flowv6', pkt_test_suite)
test_sg_tcp_flow = AgentEnv.MakeTestCmd(env, 'test_sg_tcp_flow', pkt_flaky_test_suite)
test_vrf_assign_acl = AgentEnv.MakeTestCmd(env, 'test_vrf_assign_acl',
pkt_flaky_test_suite)
test_ecmp_mx = AgentEnv.MakeTestCmd(env, 'test_ecmp_mx', pkt_test_suite)
test_fip_dst_ecmp = AgentEnv.MakeTestCmd(env, 'test_fip_dst_ecmp',
pkt_test_suite)
test_fip_src_ecmp = AgentEnv.MakeTestCmd(env, 'test_fip_src_ecmp',
pkt_test_suite)
test_ecmp_local = AgentEnv.MakeTestCmd(env, 'test_ecmp_local',
pkt_test_suite)

test_xml_packet_ut = AgentEnv.MakeTestCmdSrc(env, 'test_xml_packet_ut',
[
Expand Down
148 changes: 148 additions & 0 deletions src/vnsw/agent/pkt/test/test_ecmp_local.cc
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
*/
#include "base/os.h"
#include "test/test_cmn_util.h"
#include "test_pkt_util.h"
#include "pkt/flow_proto.h"

#define AGE_TIME 10*1000

void RouterIdDepInit(Agent *agent) {
}

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:01:01:01", 1, 2}
};

class EcmpTest : public ::testing::Test {
virtual void SetUp() {
agent_ = Agent::GetInstance();

boost::system::error_code ec;
bgp_peer = CreateBgpPeer(Ip4Address::from_string("0.0.0.1", ec),
"xmpp channel");
client->WaitForIdle();

flow_proto_ = agent_->pkt()->get_flow_proto();
CreateVmportWithEcmp(input1, 2);
AddVn("vn2", 2);
AddVrf("vrf2");
client->WaitForIdle();
strcpy(router_id, agent_->router_id().to_string().c_str());
strcpy(MX_0, "100.1.1.1");
strcpy(MX_1, "100.1.1.2");
strcpy(MX_2, "100.1.1.3");
strcpy(MX_3, "100.1.1.4");

const VmInterface *vmi = static_cast<const VmInterface *>(VmPortGet(1));
vm1_label = vmi->label();
vmi = static_cast<const VmInterface *>(VmPortGet(2));
vm2_label = vmi->label();
eth_intf_id = EthInterfaceGet("vnet0")->id();
}

virtual void TearDown() {
DeleteVmportEnv(input1, 2, true);
DelVn("vn2");
DelVrf("vrf2");
client->WaitForIdle();
DeleteBgpPeer(bgp_peer);
client->WaitForIdle();
EXPECT_FALSE(VrfFind("vrf1", true));
EXPECT_FALSE(VrfFind("vrf2", true));
WAIT_FOR(1000, 1000, (flow_proto_->FlowCount() == 0));
client->WaitForIdle();
}
public:
void AddRemoteEcmpRoute(const string vrf_name, const string ip,
uint32_t plen, const string vn, int count, bool reverse = false,
bool same_label = false) {
//If there is a local route, include that always
Ip4Address vm_ip = Ip4Address::from_string(ip);

ComponentNHKeyList comp_nh_list;
int remote_server_ip = 0x64010101;
int label = 16;
SecurityGroupList sg_id_list;

for(int i = 0; i < count; i++) {
ComponentNHKeyPtr comp_nh(new ComponentNHKey(
label, Agent::GetInstance()->fabric_vrf_name(),
Agent::GetInstance()->router_id(),
Ip4Address(remote_server_ip++),
false, TunnelType::AllType()));
comp_nh_list.push_back(comp_nh);
if (!same_label) {
label++;
}
}
if (reverse) {
std::reverse(comp_nh_list.begin(), comp_nh_list.end());
}

EcmpTunnelRouteAdd(bgp_peer, vrf_name, vm_ip, plen,
comp_nh_list, -1, vn, sg_id_list,
PathPreference());
}

FlowProto *get_flow_proto() const { return flow_proto_; }
Agent *agent_;
Peer *bgp_peer;
FlowProto *flow_proto_;
AgentXmppChannel *channel;
char router_id[80];
char MX_0[80];
char MX_1[80];
char MX_2[80];
char MX_3[80];
int vm1_label;
int vm2_label;
int agg_label;
int eth_intf_id;
};

//Send packet from ECMP VM to ECMP MX
//Verify component index is set and correspnding
//rpf nexthop
TEST_F(EcmpTest, EcmpTest_1) {
AddRemoteEcmpRoute("vrf1", "0.0.0.0", 0, "vn1", 4);
AddRemoteEcmpRoute("vrf1", "1.1.1.1", 32, "vn1", 4);

TxIpPacket(VmPortGetId(1), "1.1.1.1", "2.1.1.1", 1);
client->WaitForIdle();

AgentRoute *rt = RouteGet("vrf1", Ip4Address::from_string("0.0.0.0"), 0);
InetUnicastRouteEntry *src_rt = static_cast<InetUnicastRouteEntry *>(
RouteGet("vrf1", Ip4Address::from_string("1.1.1.1"), 32));

FlowEntry *entry = FlowGet(VrfGet("vrf1")->vrf_id(),
"1.1.1.1", "2.1.1.1", 1, 0, 0, GetFlowKeyNH(1));
EXPECT_TRUE(entry != NULL);
EXPECT_TRUE(entry->data().component_nh_idx !=
CompositeNH::kInvalidComponentNHIdx);
EXPECT_TRUE(entry->data().nh.get() == src_rt->GetLocalNextHop());

//Reverse flow is no ECMP
FlowEntry *rev_entry = entry->reverse_flow_entry();
EXPECT_TRUE(rev_entry->data().component_nh_idx !=
CompositeNH::kInvalidComponentNHIdx);
EXPECT_TRUE(rev_entry->data().nh.get() == rt->GetActiveNextHop());

DeleteRoute("vrf1", "0.0.0.0", 0, bgp_peer);
client->WaitForIdle();
sleep(1);
client->WaitForIdle();
WAIT_FOR(1000, 1000, (get_flow_proto()->FlowCount() == 0));
}

int main(int argc, char *argv[]) {
GETUSERARGS();
client = TestInit(init_file, ksync_init, true, true, true, 100*1000);
int ret = RUN_ALL_TESTS();
client->WaitForIdle();
TestShutdown();
delete client;
return ret;
}

0 comments on commit ecf90a7

Please sign in to comment.