From d0414d2e6eeae350ecf4189f894c475e0ef00d21 Mon Sep 17 00:00:00 2001 From: Naveen N Date: Fri, 27 Feb 2015 01:58:02 -0800 Subject: [PATCH] * In a scenario where there are 2 vgw exporting same subnet route, and traffic session gets initiated from external domain to VM, then for setting reverse flow agent was trying to get policy enabled interface nexthop for vgw, and for vgw we would only create policy disabled nh. Fixing the same to pick policy disabled nexthop for vgw destination Closes-bug:#1425856 Change-Id: I23462aec80cc7fc351c376705f2fb2dc062acf16 --- src/vnsw/agent/pkt/pkt_flow_info.cc | 15 ++++++- src/vnsw/agent/pkt/test/test_ecmp.cc | 61 ++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/pkt/pkt_flow_info.cc b/src/vnsw/agent/pkt/pkt_flow_info.cc index 1da90143877..34cd176e556 100644 --- a/src/vnsw/agent/pkt/pkt_flow_info.cc +++ b/src/vnsw/agent/pkt/pkt_flow_info.cc @@ -206,7 +206,20 @@ static bool NhDecode(const NextHop *nh, const PktInfo *pkt, PktFlowInfo *info, const InetUnicastRouteEntry *rt = static_cast(in->rt_); if (rt != NULL && rt->GetLocalNextHop()) { - out->nh_ = GetPolicyEnabledNH(rt->GetLocalNextHop())->id(); + const NextHop *local_nh = rt->GetLocalNextHop(); + out->nh_ = local_nh->id(); + if (local_nh->GetType() == NextHop::INTERFACE) { + const Interface *local_intf = + static_cast(local_nh)->GetInterface(); + //Get policy enabled nexthop only for + //vm interface, in case of vgw or service interface in + //transparent mode we should still + //use policy disabled interface + if (local_intf && + local_intf->type() == Interface::VM_INTERFACE) { + out->nh_ = GetPolicyEnabledNH(local_nh)->id(); + } + } } else { out->nh_ = in->nh_; } diff --git a/src/vnsw/agent/pkt/test/test_ecmp.cc b/src/vnsw/agent/pkt/test/test_ecmp.cc index 18d7ba30cb5..aab5255159d 100644 --- a/src/vnsw/agent/pkt/test/test_ecmp.cc +++ b/src/vnsw/agent/pkt/test/test_ecmp.cc @@ -2257,6 +2257,67 @@ TEST_F(EcmpTest, TrapFlag) { client->WaitForIdle(); } +//Send a packet from vgw to ecmp destination +TEST_F(EcmpTest, VgwFlag) { + Agent *agent = Agent::GetInstance(); + InetInterface::CreateReq(agent->interface_table(), "vgw1", + InetInterface::SIMPLE_GATEWAY, "vrf2", + Ip4Address(0), 0, Ip4Address(0), Agent::NullString(), + ""); + client->WaitForIdle(); + + InetInterfaceKey *intf_key = new InetInterfaceKey("vgw1"); + std::auto_ptr nh_key(new InterfaceNHKey(intf_key, false, + InterfaceNHFlags::INET4)); + + Ip4Address remote_server_ip1 = Ip4Address::from_string("10.10.10.100"); + ComponentNHKeyPtr nh_data1(new ComponentNHKey(16, nh_key)); + ComponentNHKeyPtr nh_data2(new ComponentNHKey(20, agent->fabric_vrf_name(), + agent->router_id(), + remote_server_ip1, + false, + TunnelType::DefaultType())); + Ip4Address ip = Ip4Address::from_string("0.0.0.0"); + ComponentNHKeyList comp_nh_list; + comp_nh_list.push_back(nh_data1); + comp_nh_list.push_back(nh_data2); + EcmpTunnelRouteAdd(bgp_peer, "vrf2", ip, 0, + comp_nh_list, false, "vn2", + SecurityGroupList(), PathPreference()); + client->WaitForIdle(); + + InetInterfaceKey tmp_key("vgw1"); + Interface *intf = + static_cast(agent->interface_table()-> + FindActiveEntry(&tmp_key)); + + //Send packet on vgw interface + TxIpPacket(intf->id(), "100.1.1.1", "2.2.2.2", 1); + client->WaitForIdle(); + + FlowEntry *entry; + FlowEntry *rev_entry; + entry = FlowGet(VrfGet("vrf2")->vrf_id(), + "2.2.2.2", "100.1.1.1", 1, 0, 0, intf->flow_key_nh()->id()); + EXPECT_TRUE(entry != NULL); + EXPECT_TRUE(entry->data().component_nh_idx == + CompositeNH::kInvalidComponentNHIdx); + + rev_entry = FlowGet(VrfGet("vrf2")->vrf_id(), + "100.1.1.1", "2.2.2.2", 1, 0, 0, intf->flow_key_nh()->id()); + EXPECT_TRUE(rev_entry != NULL); + EXPECT_TRUE(rev_entry->data().component_nh_idx == + CompositeNH::kInvalidComponentNHIdx); + + client->WaitForIdle(); + agent->fabric_inet4_unicast_table()->DeleteReq(bgp_peer, "vrf2", + ip, 0, NULL); + InetInterface::DeleteReq(agent->interface_table(), "vgw1"); + client->WaitForIdle(); + WAIT_FOR(1000, 1000, (Agent::GetInstance()->pkt()-> + flow_table()->Size() == 0)); +} + int main(int argc, char *argv[]) { GETUSERARGS(); client = TestInit(init_file, ksync_init, true, true, true, 100*1000);