Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add route to trap neighbor advertisement messages to Agent.
Issue:
In case of IPv6 Allowed Address Pair, when switchover happens to new interface,
the traffic does not move to new interface. As part of switchover, Unsolicited
Neighbor Advertisement message from new interface is not trapped to agent.

Fix
Agent now adds a route to trap IPv6 All Nodes Multicast address in each VRF so
that Unsolicited Neighbor Advertisement message reaches agent. Agent, as part
of this message processing updates the Allowed Address pair state machine so
that route preference is updated for new interface and traffic starts flowing
from new interface. Also define separate counters in agent for Solicited and
Unsolicited Neighbor advertisement message.
Also update the UT.

Closes-Bug: #1592119
(cherry picked from commit 6d3008c)

Change-Id: Ic46a99cd096c03d6af23c8fc50cac4bd2c70d0b1
  • Loading branch information
ashoksr committed Jun 24, 2016
1 parent f95b243 commit de1f03e
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/vnsw/agent/kstate/test/test_kstate.cc
Expand Up @@ -393,8 +393,8 @@ TEST_F(KStateTest, RouteDumpTest) {
//Addition of 2 vm ports in a new VN (VRF) will result in the following routes
// 2 routes corresponding to the addresses of VM
// l2 broadcast
// 2 - v6 host route for new vrf addition
TestRouteKState::Init(true, prev_rt_count + (MAX_TEST_FD * 2) + 3);
// 3 - v6 host route for new vrf addition
TestRouteKState::Init(true, prev_rt_count + (MAX_TEST_FD * 2) + 4);
client->WaitForIdle();
client->KStateResponseWait(1);
DeletePorts();
Expand Down
8 changes: 6 additions & 2 deletions src/vnsw/agent/services/icmpv6_handler.cc
Expand Up @@ -58,6 +58,7 @@ bool Icmpv6Handler::Run() {
ICMPV6_TRACE(Trace, "Received ICMP with l3 disabled");
return true;
}
nd_neighbor_advert *icmp = (nd_neighbor_advert *)icmp_;
switch (icmp_->icmp6_type) {
case ND_ROUTER_SOLICIT:
icmpv6_proto->IncrementStatsRouterSolicit(vm_itf);
Expand Down Expand Up @@ -103,9 +104,12 @@ bool Icmpv6Handler::Run() {
break;

case ND_NEIGHBOR_ADVERT:
icmpv6_proto->IncrementStatsNeighborAdvert(vm_itf);
if (icmp->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED) {
icmpv6_proto->IncrementStatsNeighborAdvertSolicited(vm_itf);
} else {
icmpv6_proto->IncrementStatsNeighborAdvertUnSolicited(vm_itf);
}
if (CheckPacket()) {
nd_neighbor_advert *icmp = (nd_neighbor_advert *)icmp_;
boost::array<uint8_t, 16> bytes;
for (int i = 0; i < 16; i++) {
bytes[i] = icmp->nd_na_target.s6_addr[i];
Expand Down
22 changes: 19 additions & 3 deletions src/vnsw/agent/services/icmpv6_proto.cc
Expand Up @@ -83,6 +83,11 @@ void Icmpv6Proto::VnNotify(DBEntryBase *entry) {

boost::system::error_code ec;
Ip6Address addr = Ip6Address::from_string(IPV6_ALL_ROUTERS_ADDRESS, ec);
static_cast<InetUnicastAgentRouteTable *>
(vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(),
addr, 128,
vn->GetName());
addr = Ip6Address::from_string(IPV6_ALL_NODES_ADDRESS, ec);
static_cast<InetUnicastAgentRouteTable *>
(vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(),
addr, 128,
Expand Down Expand Up @@ -115,6 +120,9 @@ void Icmpv6Proto::VrfNotify(DBTablePartBase *part, DBEntryBase *entry) {
Ip6Address addr =
Ip6Address::from_string(IPV6_ALL_ROUTERS_ADDRESS, ec);
// enqueue delete request on fabric VRF
agent_->fabric_inet4_unicast_table()->DeleteReq(
agent_->local_peer(), vrf->GetName(), addr, 128, NULL);
addr = Ip6Address::from_string(IPV6_ALL_NODES_ADDRESS, ec);
agent_->fabric_inet4_unicast_table()->DeleteReq(
agent_->local_peer(), vrf->GetName(), addr, 128, NULL);
addr = Ip6Address::from_string(PKT0_LINKLOCAL_ADDRESS, ec);
Expand Down Expand Up @@ -386,10 +394,18 @@ void Icmpv6Proto::IncrementStatsNeighborSolicit(VmInterface *vmi) {
}
}

void Icmpv6Proto::IncrementStatsNeighborAdvert(VmInterface *vmi) {
stats_.icmpv6_neighbor_advert_++;
void Icmpv6Proto::IncrementStatsNeighborAdvertSolicited(VmInterface *vmi) {
stats_.icmpv6_neighbor_advert_solicited_++;
Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
if (stats) {
stats->icmpv6_neighbor_advert_solicited_++;
}
}

void Icmpv6Proto::IncrementStatsNeighborAdvertUnSolicited(VmInterface *vmi) {
stats_.icmpv6_neighbor_advert_unsolicited_++;
Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
if (stats) {
stats->icmpv6_neighbor_advert_++;
stats->icmpv6_neighbor_advert_unsolicited_++;
}
}
9 changes: 6 additions & 3 deletions src/vnsw/agent/services/icmpv6_proto.h
Expand Up @@ -31,7 +31,8 @@ class Icmpv6Proto : public Proto {
void Reset() {
icmpv6_router_solicit_ = icmpv6_router_advert_ = 0;
icmpv6_ping_request_ = icmpv6_ping_response_ = icmpv6_drop_ = 0;
icmpv6_neighbor_solicit_ = icmpv6_neighbor_advert_ = 0;
icmpv6_neighbor_solicit_ = icmpv6_neighbor_advert_solicited_ = 0;
icmpv6_neighbor_advert_unsolicited_ = 0;
}

uint32_t icmpv6_router_solicit_;
Expand All @@ -40,7 +41,8 @@ class Icmpv6Proto : public Proto {
uint32_t icmpv6_ping_response_;
uint32_t icmpv6_drop_;
uint32_t icmpv6_neighbor_solicit_;
uint32_t icmpv6_neighbor_advert_;
uint32_t icmpv6_neighbor_advert_solicited_;
uint32_t icmpv6_neighbor_advert_unsolicited_;
};

typedef std::map<VmInterface *, Icmpv6Stats> VmInterfaceMap;
Expand All @@ -62,8 +64,9 @@ class Icmpv6Proto : public Proto {
void IncrementStatsPingRequest(VmInterface *vmi);
void IncrementStatsPingResponse(VmInterface *vmi);
void IncrementStatsDrop() { stats_.icmpv6_drop_++; }
void IncrementStatsNeighborAdvertSolicited(VmInterface *vmi);
void IncrementStatsNeighborAdvertUnSolicited(VmInterface *vmi);
void IncrementStatsNeighborSolicit(VmInterface *vmi);
void IncrementStatsNeighborAdvert(VmInterface *vmi);
const Icmpv6Stats &GetStats() const { return stats_; }
Icmpv6Stats *VmiToIcmpv6Stats(VmInterface *i);
void ClearStats() { stats_.Reset(); }
Expand Down
6 changes: 4 additions & 2 deletions src/vnsw/agent/services/services.sandesh
Expand Up @@ -213,7 +213,8 @@ response sandesh Icmpv6Stats {
4: i32 icmpv6_ping_response;
5: i32 icmpv6_drop;
6: i32 icmpv6_neighbor_solicit;
7: i32 icmpv6_neighbor_advert;
7: i32 icmpv6_neighbor_advert_solicited;
8: i32 icmpv6_neighbor_advert_unsolicited;
}

/**
Expand Down Expand Up @@ -253,7 +254,8 @@ struct InterfaceIcmpv6Stats {
4: u32 icmpv6_ping_request;
5: u32 icmpv6_ping_response;
6: u32 icmpv6_neighbor_solicit;
7: u32 icmpv6_neighbor_advert;
7: u32 icmpv6_neighbor_advert_solicited;
8: u32 icmpv6_neighbor_advert_unsolicited;
}

/**
Expand Down
10 changes: 8 additions & 2 deletions src/vnsw/agent/services/services_sandesh.cc
Expand Up @@ -31,7 +31,10 @@
entry.set_icmpv6_ping_request(stats.icmpv6_ping_request_); \
entry.set_icmpv6_ping_response(stats.icmpv6_ping_response_); \
entry.set_icmpv6_neighbor_solicit(stats.icmpv6_neighbor_solicit_); \
entry.set_icmpv6_neighbor_advert(stats.icmpv6_neighbor_advert_); \
entry.set_icmpv6_neighbor_advert_solicited \
(stats.icmpv6_neighbor_advert_solicited_); \
entry.set_icmpv6_neighbor_advert_unsolicited \
(stats.icmpv6_neighbor_advert_unsolicited_); \
list.push_back(entry);

std::map<uint16_t, std::string> g_ip_protocol_map =
Expand Down Expand Up @@ -261,7 +264,10 @@ void ServicesSandesh::Icmpv6StatsSandesh(std::string ctxt, bool more) {
icmp->set_icmpv6_ping_response(istats.icmpv6_ping_response_);
icmp->set_icmpv6_drop(istats.icmpv6_drop_);
icmp->set_icmpv6_neighbor_solicit(istats.icmpv6_neighbor_solicit_);
icmp->set_icmpv6_neighbor_advert(istats.icmpv6_neighbor_advert_);
icmp->set_icmpv6_neighbor_advert_solicited
(istats.icmpv6_neighbor_advert_solicited_);
icmp->set_icmpv6_neighbor_advert_unsolicited
(istats.icmpv6_neighbor_advert_unsolicited_);
icmp->set_context(ctxt);
icmp->set_more(more);
icmp->Response();
Expand Down
6 changes: 3 additions & 3 deletions src/vnsw/agent/test/test_agent_route_walker.cc
Expand Up @@ -277,7 +277,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_wih_1_vrf) {
client->Reset();
SetupEnvironment(1);
StartVrfWalk();
VerifyNotifications(19, 2, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 2));
VerifyNotifications(20, 2, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 2));
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(1);
Expand All @@ -287,7 +287,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_with_2_vrf) {
client->Reset();
SetupEnvironment(2);
StartVrfWalk();
VerifyNotifications(29, 3, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 3));
VerifyNotifications(31, 3, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 3));
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(2);
Expand All @@ -297,7 +297,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_with_3_vrf) {
client->Reset();
SetupEnvironment(3);
StartVrfWalk();
VerifyNotifications(39, 4, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 4));
VerifyNotifications(42, 4, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 4));
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(3);
Expand Down

0 comments on commit de1f03e

Please sign in to comment.