Skip to content

Commit

Permalink
* Dont apply interface VRF assign rule when packet gets NATed
Browse files Browse the repository at this point in the history
Interface VRF assign rules are ysed to steer traffic thru service
instances in service chain. If a packet gets NATed then destination
VRF should be set to native VRF of interface to which the floating
ip belong, and in this case there is no need to apply VRF translation
rule. Test case to verify the same.
Closes-bug:#1465728

Change-Id: I0a0319d028d08fc4751fbf9fa5f986692f0e8ac8
  • Loading branch information
naveen-n committed Jul 21, 2015
1 parent b9c8004 commit 5ebca65
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 15 deletions.
6 changes: 5 additions & 1 deletion src/vnsw/agent/pkt/flow_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,11 @@ void FlowEntry::GetVrfAssignAcl() {
//If interface has a VRF assign rule, choose the acl and match the
//packet, else get the acl attached to VN and try matching the packet to
//network acl
const AclDBEntry* acl = intf->vrf_assign_acl();
const AclDBEntry* acl = NULL;
if (is_flags_set(FlowEntry::NatFlow) == false) {
acl = intf->vrf_assign_acl();
}

if (acl == NULL) {
acl = data_.vn_entry.get()->GetAcl();
}
Expand Down
25 changes: 18 additions & 7 deletions src/vnsw/agent/pkt/pkt_flow_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,12 @@ void PktFlowInfo::FloatingIpSNat(const PktInfo *pkt, PktControlInfo *in,
return;
}

if (VrfTranslate(pkt, in, out) == false) {
if (VrfTranslate(pkt, in, out, fip_it->floating_ip_, true) == false) {
return;
}
if (out->rt_ == NULL || in->rt_ == NULL) {
//If After VRF translation, ingress route or
//egress route is NULL, mark the flow as short flow
return;
}

Expand Down Expand Up @@ -781,7 +786,8 @@ void PktFlowInfo::FloatingIpSNat(const PktInfo *pkt, PktControlInfo *in,
}

bool PktFlowInfo::VrfTranslate(const PktInfo *pkt, PktControlInfo *in,
PktControlInfo *out) {
PktControlInfo *out, const IpAddress &src_ip,
bool nat_flow) {
const Interface *intf = NULL;
if (ingress) {
intf = in->intf_;
Expand All @@ -796,7 +802,12 @@ bool PktFlowInfo::VrfTranslate(const PktInfo *pkt, PktControlInfo *in,
//If interface has a VRF assign rule, choose the acl and match the
//packet, else get the acl attached to VN and try matching the packet to
//network acl
const AclDBEntry *acl = vm_intf->vrf_assign_acl();
const AclDBEntry *acl = NULL;
if (nat_flow == false) {
acl = vm_intf->vrf_assign_acl();
}
//In case of floating IP translation, dont apply
//interface VRF assign rule
if (acl == NULL) {
if (ingress && in->vn_) {
//Check if the network ACL is present
Expand All @@ -812,7 +823,7 @@ bool PktFlowInfo::VrfTranslate(const PktInfo *pkt, PktControlInfo *in,

PacketHeader hdr;
hdr.vrf = pkt->vrf;
hdr.src_ip = pkt->ip_saddr;
hdr.src_ip = src_ip;
hdr.dst_ip = pkt->ip_daddr;
hdr.protocol = pkt->ip_proto;
if (hdr.protocol == IPPROTO_UDP || hdr.protocol == IPPROTO_TCP) {
Expand Down Expand Up @@ -852,7 +863,7 @@ bool PktFlowInfo::VrfTranslate(const PktInfo *pkt, PktControlInfo *in,
}
out->vrf_ = vrf;
UpdateRoute(&out->rt_, vrf, pkt->ip_daddr, flow_dest_plen_map);
UpdateRoute(&in->rt_, vrf, pkt->ip_saddr, flow_source_plen_map);
UpdateRoute(&in->rt_, vrf, hdr.src_ip, flow_source_plen_map);
}

return true;
Expand All @@ -879,7 +890,7 @@ void PktFlowInfo::IngressProcess(const PktInfo *pkt, PktControlInfo *in,
//exact same route with different nexthop, hence if both ingress
//route and egress route are present in native vrf, acl match condition
//can be applied
if (VrfTranslate(pkt, in, out) == false) {
if (VrfTranslate(pkt, in, out, pkt->ip_saddr, false) == false) {
return;
}

Expand Down Expand Up @@ -961,7 +972,7 @@ void PktFlowInfo::EgressProcess(const PktInfo *pkt, PktControlInfo *in,
}

//Apply vrf translate ACL to get ingress route
if (VrfTranslate(pkt, in, out) == false) {
if (VrfTranslate(pkt, in, out, pkt->ip_saddr, false) == false) {
return;
}

Expand Down
3 changes: 2 additions & 1 deletion src/vnsw/agent/pkt/pkt_flow_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ class PktFlowInfo {
MatchPolicy *m_policy);
void RewritePktInfo(uint32_t index);
bool VrfTranslate(const PktInfo *pkt, PktControlInfo *ctrl,
PktControlInfo *rev_flow);
PktControlInfo *rev_flow, const IpAddress &src_ip,
bool nat_flow);
uint32_t LinkLocalBindPort(const VmEntry *vm, uint8_t proto);
void UpdateFipStatsInfo(FlowEntry *flow, FlowEntry *rflow, const PktInfo *p,
const PktControlInfo *in, const PktControlInfo *o);
Expand Down
75 changes: 70 additions & 5 deletions src/vnsw/agent/pkt/test/test_vrf_assign_acl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ TEST_F(TestVrfAssignAclFlow, VrfAssignAcl8) {

TunnelRouteAdd("10.1.1.2", "2.1.1.1", "default-project:vn1:vn1",
16, "default-project:vn2");
client->WaitForIdle();

TestFlow flow[] = {
{ TestFlowPkt(Address::INET, "1.1.1.1", "2.1.1.1", IPPROTO_TCP, 10, 20,
Expand Down Expand Up @@ -455,11 +456,13 @@ TEST_F(TestVrfAssignAclFlow, FloatingIp) {
DelLink("floating-ip-pool", "fip-pool1", "virtual-network", "default:vn4");
DelFloatingIp("fip1");
DelFloatingIpPool("fip-pool1");
DelLink("virtual-network", "default-project:vn1", "access-control-list", "Acl");
DeleteVmportEnv(input, 1, true);
client->WaitForIdle();
}

TEST_F(TestVrfAssignAclFlow, FloatingIp_1) {
//Verify flow becomes short flow, when
//vrf assigned ACL doesnt have the routes
TEST_F(TestVrfAssignAclFlow, FloatingIp1) {
struct PortInfo input[] = {
{"intf7", 7, "4.1.1.1", "00:00:00:01:01:01", 4, 7},
};
Expand All @@ -475,12 +478,14 @@ TEST_F(TestVrfAssignAclFlow, FloatingIp_1) {
false, PathPreference(), Ip4Address(0));
client->WaitForIdle();

AddVrf("vrf9");
client->WaitForIdle();
//Add an ACL, such that for traffic from vn4:vn4 to default-project:vn2,
//route lookup happens in internal VRF, in this case VRF doesnt exist
//and hence flow should be short flow
//route lookup happens in internal VRF
//(assume default-project:vn3 in test case)
AddVrfAssignNetworkAcl("Acl", 10, "default-project:vn1",
"default-project:vn2", "pass",
"default-project:vn3:xyz");
"vrf9");
AddLink("virtual-network", "default-project:vn1", "access-control-list", "Acl");
client->WaitForIdle();

Expand All @@ -506,9 +511,69 @@ TEST_F(TestVrfAssignAclFlow, FloatingIp_1) {

DelLink("floating-ip", "fip1", "floating-ip-pool", "fip-pool1");
DelLink("floating-ip-pool", "fip-pool1", "virtual-network", "default:vn4");
DelLink("virtual-network", "default-project:vn1", "access-control-list", "Acl");
DelFloatingIp("fip1");
DelFloatingIpPool("fip-pool1");
DeleteVmportEnv(input, 1, true);
DelVrf("vrf9");
client->WaitForIdle();
}

//Verify Interface VRF assign rule doesnt get applied for
//floating IP traslation
TEST_F(TestVrfAssignAclFlow, FloatingIp2) {
struct PortInfo input[] = {
{"intf7", 7, "4.1.1.1", "00:00:00:01:01:01", 4, 7},
};
CreateVmportEnv(input, 1);
client->WaitForIdle();

AddVrf("vrf9");
//Leak route for 2.1.1.0 to default-project:vn1:vn1
Ip4Address ip1 = Ip4Address::from_string("2.1.1.0");
agent_->fabric_inet4_unicast_table()->
AddLocalVmRouteReq(agent_->local_peer(),
"default-project:vn1:vn1", ip1, 24, MakeUuid(3),
"default-project:vn1", 16, SecurityGroupList(),
false, PathPreference(), Ip4Address(0));
client->WaitForIdle();

AddAddressVrfAssignAcl("intf7", 7, "4.1.1.0", "2.1.1.0", 6, 1, 65535,
1, 65535, "vrf9", "true");
client->WaitForIdle();

//Configure Floating-IP for intf7 in default-project:vn1
AddFloatingIpPool("fip-pool1", 1);
AddFloatingIp("fip1", 1, "1.1.1.100");
AddLink("floating-ip", "fip1", "floating-ip-pool", "fip-pool1");
AddLink("floating-ip-pool", "fip-pool1", "virtual-network",
"default-project:vn1");
AddLink("virtual-machine-interface", "intf7", "floating-ip", "fip1");
client->WaitForIdle();

TestFlow flow[] = {
{ TestFlowPkt(Address::INET, "4.1.1.1", "2.1.1.1", IPPROTO_TCP, 10, 20,
"vrf4", VmPortGet(7)->id()),
{
new VerifyVn("default-project:vn1", "default-project:vn1"),
new VerifyAction(1 << TrafficAction::PASS,
1 << TrafficAction::PASS),
new VerifyNat("2.1.1.1", "1.1.1.100", IPPROTO_TCP, 20, 10)
}
}
};
CreateFlow(flow, 1);

DelLink("floating-ip", "fip1", "floating-ip-pool", "fip-pool1");
DelLink("floating-ip-pool", "fip-pool1",
"virtual-network", "default-project:vn1");
DelLink("virtual-machine-interface", "intf7", "floating-ip", "fip1");
DelFloatingIp("fip1");
DelFloatingIpPool("fip-pool1");
DelLink("virtual-network", "default-project:vn1",
"access-control-list", "Acl");
DeleteVmportEnv(input, 1, true);
DelVrf("vrf9");
client->WaitForIdle();
}

Expand Down
2 changes: 1 addition & 1 deletion src/vnsw/agent/test/test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ bool TunnelRouteAdd(const char *server, const char *vmip, const char *vm_vrf,
Agent::GetInstance()->fabric_vrf_name(),
Agent::GetInstance()->router_id(),
vm_vrf, Ip4Address::from_string(server, ec),
TunnelType::AllType(), label, "",
TunnelType::AllType(), label, vn,
SecurityGroupList(), PathPreference());
InetUnicastAgentRouteTable::AddRemoteVmRouteReq(bgp_peer_, vm_vrf,
Ip4Address::from_string(vmip, ec),
Expand Down

0 comments on commit 5ebca65

Please sign in to comment.