Skip to content

Commit

Permalink
Consider ARP probes (ARP with src IP set to zero) as Gratuitous.
Browse files Browse the repository at this point in the history
Also, ignore (do not add ARP entry) when grat ARP is received for
an unknown entry.

Change-Id: I4780ff7209c5c0092afe28c00425fb40beb07013
closes-bug: 1558237
(cherry picked from commit fa011ca)
  • Loading branch information
haripk committed Mar 31, 2016
1 parent cba7cba commit 011b922
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 32 deletions.
10 changes: 8 additions & 2 deletions src/vnsw/agent/oper/path_preference.cc
Original file line number Diff line number Diff line change
Expand Up @@ -865,8 +865,14 @@ void PathPreferenceModule::EnqueueTrafficSeen(Ip4Address ip, uint32_t plen,
}

PathPreferenceEventContainer event;
event.ip_ = rt->addr();
event.plen_ = rt->plen();
if (rt) {
event.ip_ = rt->addr();
event.plen_ = rt->plen();
} else {
// (0 IP + Mac) event required for EVPN
event.ip_ = IpAddress();
event.plen_ = 32;
}
event.interface_index_ = interface_index;
event.vrf_index_ = vrf_index;
event.mac_ = mac;
Expand Down
9 changes: 3 additions & 6 deletions src/vnsw/agent/services/arp_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ bool ArpHandler::HandlePacket() {
return true;
}

if (tpa == spa) {
if (tpa == spa || spa == 0) {
arp_cmd = GRATUITOUS_ARP;
}
} else {
Expand Down Expand Up @@ -199,11 +199,8 @@ bool ArpHandler::HandlePacket() {
entry->HandleArpReply(MacAddress(arp_->arp_sha));
return true;
} else {
entry = new ArpEntry(io_, this, key, key.vrf, ArpEntry::INITING, itf);
entry->HandleArpReply(MacAddress(arp_->arp_sha));
arp_proto->AddArpEntry(entry);
arp_ = NULL;
return false;
// ignore gratuitous ARP when entry is not present in cache
return true;
}
}

Expand Down
64 changes: 40 additions & 24 deletions src/vnsw/agent/services/test/arp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -317,19 +317,49 @@ TEST_F(ArpTest, ArpReqTest) {
arp_cache_sandesh->Release();
}

TEST_F(ArpTest, ArpGratuitousTest) {
// Check that a Grat ARP for non-existing entry is ignored.
TEST_F(ArpTest, ArpNonExistGratuitousTest) {
for (int i = 0; i < 2; i++) {
SendArpReq(req_ifindex, 0, ntohl(inet_addr(GRAT_IP)),
ntohl(inet_addr(GRAT_IP)));
WaitForCompletion(2);
EXPECT_TRUE(FindArpNHEntry(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
EXPECT_TRUE(FindArpRoute(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
SendArpReq(req_ifindex, 0, ntohl(inet_addr(GRAT_IP)),
ntohl(inet_addr(GRAT_IP)));
client->WaitForIdle();
EXPECT_FALSE(FindArpNHEntry(ntohl(inet_addr(GRAT_IP)),
Agent::GetInstance()->fabric_vrf_name()));
EXPECT_FALSE(FindArpRoute(ntohl(inet_addr(GRAT_IP)),
Agent::GetInstance()->fabric_vrf_name()));
}
SendArpMessage(ArpProto::AGING_TIMER_EXPIRED, ntohl(inet_addr(GRAT_IP)));
usleep(175000); // wait for retry timer to expire
}

// Check that a Grat ARP to existing entry is processed.
TEST_F(ArpTest, ArpGratuitousTest) {
TunnelNH(DBRequest::DB_ENTRY_ADD_CHANGE, src_ip, dest_ip);
SendArpReq(req_ifindex, 0, dest_ip, dest_ip);
client->WaitForIdle();
EXPECT_TRUE(FindArpNHEntry(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
EXPECT_TRUE(FindArpRoute(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
TunnelNH(DBRequest::DB_ENTRY_DELETE, src_ip, dest_ip);
client->WaitForIdle();
SendArpMessage(ArpProto::AGING_TIMER_EXPIRED, dest_ip);
usleep(175000);
EXPECT_EQ(1U, Agent::GetInstance()->GetArpProto()->GetArpCacheSize());
EXPECT_FALSE(FindArpNHEntry(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
EXPECT_FALSE(FindArpRoute(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
EXPECT_FALSE(FindArpNHEntry(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
EXPECT_FALSE(FindArpRoute(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
}

// Check that a Grat ARP with src ip zero is processed.
TEST_F(ArpTest, ArpGratZeroSrcTest) {
TunnelNH(DBRequest::DB_ENTRY_ADD_CHANGE, src_ip, dest_ip);
SendArpReq(req_ifindex, 0, 0, dest_ip); // src IP set to zero
client->WaitForIdle();
EXPECT_TRUE(FindArpNHEntry(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
EXPECT_TRUE(FindArpRoute(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
TunnelNH(DBRequest::DB_ENTRY_DELETE, src_ip, dest_ip);
client->WaitForIdle();
SendArpMessage(ArpProto::AGING_TIMER_EXPIRED, dest_ip);
usleep(175000);
EXPECT_EQ(1U, Agent::GetInstance()->GetArpProto()->GetArpCacheSize());
EXPECT_FALSE(FindArpNHEntry(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
EXPECT_FALSE(FindArpRoute(dest_ip, Agent::GetInstance()->fabric_vrf_name()));
}

TEST_F(ArpTest, ArpTunnelGwTest) {
Expand All @@ -345,20 +375,6 @@ TEST_F(ArpTest, ArpTunnelGwTest) {
WaitForCompletion(1);
}

TEST_F(ArpTest, ArpDelTest) {
SendArpReq(req_ifindex, 0, ntohl(inet_addr(GRAT_IP)),
ntohl(inet_addr(GRAT_IP)));
WaitForCompletion(2);
EXPECT_TRUE(FindArpNHEntry(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
EXPECT_TRUE(FindArpRoute(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
ArpNHUpdate(DBRequest::DB_ENTRY_DELETE, ntohl(inet_addr(GRAT_IP)));
client->WaitForIdle();
usleep(175000);
EXPECT_EQ(1U, Agent::GetInstance()->GetArpProto()->GetArpCacheSize());
EXPECT_FALSE(FindArpNHEntry(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
EXPECT_FALSE(FindArpRoute(ntohl(inet_addr(GRAT_IP)), Agent::GetInstance()->fabric_vrf_name()));
}

TEST_F(ArpTest, ArpTunnelTest) {
TunnelNH(DBRequest::DB_ENTRY_ADD_CHANGE, src_ip, dest_ip);
SendArpReq(req_ifindex, 0, src_ip, dest_ip);
Expand Down

0 comments on commit 011b922

Please sign in to comment.