Skip to content

Commit

Permalink
Merge "* Try ARP request even when EVPN route is in wait for traffic …
Browse files Browse the repository at this point in the history
…mode" into R2.21.x
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Dec 6, 2016
2 parents ae8971e + 795fde8 commit 90148ab
Show file tree
Hide file tree
Showing 12 changed files with 684 additions and 83 deletions.
10 changes: 10 additions & 0 deletions src/vnsw/agent/pkt/flow_table.cc
Expand Up @@ -3369,6 +3369,16 @@ AgentRoute *FlowTable::GetL2Route(const VrfEntry *vrf,
return table->FindRoute(mac);
}

//Find EVPN route
AgentRoute* FlowTable::GetEvpnRoute(const VrfEntry *vrf,
const MacAddress &mac,
const IpAddress &ip,
uint32_t ethernet_tag) {
EvpnAgentRouteTable *table = static_cast<EvpnAgentRouteTable *>(
vrf->GetEvpnRouteTable());
return table->FindRoute(mac, ip, ethernet_tag);
}

AgentRoute *FlowTable::GetUcRoute(const VrfEntry *entry,
const IpAddress &addr) {
AgentRoute *rt = NULL;
Expand Down
2 changes: 2 additions & 0 deletions src/vnsw/agent/pkt/flow_table.h
Expand Up @@ -720,6 +720,8 @@ class FlowTable {

DBTableBase::ListenerId nh_listener_id();
AgentRoute *GetL2Route(const VrfEntry *entry, const MacAddress &mac);
AgentRoute *GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac,
const IpAddress &addr, uint32_t ethernet_tag);
AgentRoute *GetUcRoute(const VrfEntry *entry, const IpAddress &addr);
static const SecurityGroupList &default_sg_list() {return default_sg_list_;}
bool ValidFlowMove(const FlowEntry *new_flow,
Expand Down
61 changes: 43 additions & 18 deletions src/vnsw/agent/pkt/pkt_flow_info.cc
Expand Up @@ -1353,6 +1353,48 @@ bool PktFlowInfo::Process(const PktInfo *pkt, PktControlInfo *in,
return true;
}

void PktFlowInfo::EnqueueTrafficSeen(const PktInfo *pkt,
PktControlInfo *in,
PktControlInfo *out) {
if (pkt->family != Address::INET) {
return;
}

Ip4Address v4_src = pkt->ip_saddr.to_v4();
if (short_flow || linklocal_flow || !ingress) {
return;
}

const AgentRoute *rt = NULL;
bool enqueue_traffic_seen = false;
const VmInterface *vm_intf = dynamic_cast<const VmInterface *>(in->intf_);

if (l3_flow) {
rt = in->rt_;
} else if (in->vrf_) {
rt = flow_table->GetUcRoute(in->vrf_, v4_src);
}

if (rt && rt->WaitForTraffic()) {
enqueue_traffic_seen = true;
} else if (vm_intf) {
//L3 route is not in wait for traffic state
//EVPN route could be in wait for traffic, if yes
//enqueue traffic seen
rt = flow_table->GetEvpnRoute(in->vrf_, pkt->smac, v4_src,
vm_intf->ethernet_tag());
if (rt && rt->WaitForTraffic()) {
enqueue_traffic_seen = true;
}
}

if (enqueue_traffic_seen) {
flow_table->agent()->oper_db()->route_preference_module()->
EnqueueTrafficSeen(v4_src, 32, in->intf_->id(),
pkt->vrf, pkt->smac);
}
}

void PktFlowInfo::Add(const PktInfo *pkt, PktControlInfo *in,
PktControlInfo *out) {
FlowKey key(in->nh_, pkt->ip_saddr, pkt->ip_daddr, pkt->ip_proto,
Expand All @@ -1365,24 +1407,7 @@ void PktFlowInfo::Add(const PktInfo *pkt, PktControlInfo *in,
Agent::GetInstance()->pkt()->flow_table()->DeleteFlowInfo(flow.get());
}

if (pkt->family == Address::INET) {
Ip4Address v4_src = pkt->ip_saddr.to_v4();
if (ingress && !short_flow && !linklocal_flow) {
const AgentRoute *rt = NULL;
if (l3_flow) {
rt = in->rt_;
} else if (in->vrf_) {
rt = flow_table->GetUcRoute(in->vrf_, v4_src);
}
if (rt && rt->WaitForTraffic()) {
flow_table->agent()->oper_db()->route_preference_module()->
EnqueueTrafficSeen(v4_src, 32, in->intf_->id(),
pkt->vrf, pkt->smac);
}
}
} else if (pkt->family == Address::INET6) {
//TODO:: Handle Ipv6 changes
}
EnqueueTrafficSeen(pkt, in, out);

// Do not allow more than max flows
if ((in->vm_ &&
Expand Down
3 changes: 3 additions & 0 deletions src/vnsw/agent/pkt/pkt_flow_info.h
Expand Up @@ -96,6 +96,9 @@ class PktFlowInfo {
const IpAddress &addr, const MacAddress &mac,
FlowRouteRefMap &ref_map);
uint8_t RouteToPrefixLen(const AgentRoute *route);
void EnqueueTrafficSeen(const PktInfo *pkt,
PktControlInfo *in,
PktControlInfo *out);

bool l3_flow;
Address::Family family;
Expand Down
30 changes: 30 additions & 0 deletions src/vnsw/agent/pkt/test/test_pkt_flow.cc
Expand Up @@ -591,6 +591,7 @@ class FlowTest : public ::testing::Test {
};

bool FlowTest::ksync_init_;

//Ingress flow test (VMport to VMport - Same VN)
//Flow creation using IP and TCP packets
TEST_F(FlowTest, FlowAdd_1) {
Expand Down Expand Up @@ -3853,6 +3854,35 @@ TEST_F(FlowTest, AclRuleUpdate) {
client->WaitForIdle(5);
}

//Create a layer2 flow and verify that we dont add layer2 route
//in prefix length manipulation
TEST_F(FlowTest, WaitForTraffic) {
Ip4Address ip = Ip4Address::from_string(vm1_ip);
MacAddress mac(0, 0, 0, 1, 1, 1);

AgentRoute *ip_rt = RouteGet("vrf5", Ip4Address::from_string(vm1_ip), 32);
AgentRoute *evpn_Rt = EvpnRouteGet("vrf5", mac, ip, 0);

EXPECT_TRUE(ip_rt->WaitForTraffic() == true);
EXPECT_TRUE(evpn_Rt->WaitForTraffic() == true);

//Enqueue a flow with wrong mac address
TxL2Packet(flow0->id(),input[2].mac, input[1].mac,
input[0].addr, input[1].addr, 1);
client->WaitForIdle();
//Only IP route should goto wait for traffic
EXPECT_TRUE(ip_rt->WaitForTraffic() == false);
EXPECT_TRUE(evpn_Rt->WaitForTraffic() == true);

//Enqueue flow with right mac address
//EVPN route should also goto traffic seen state
TxL2Packet(flow0->id(),input[0].mac, input[1].mac,
input[0].addr, input[1].addr, 1);
client->WaitForIdle();
EXPECT_TRUE(ip_rt->WaitForTraffic() == false);
EXPECT_TRUE(evpn_Rt->WaitForTraffic() == false);
}

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

Expand Down

0 comments on commit 90148ab

Please sign in to comment.