From de1f03eb1d2902ba37e4883a99b0d643a80db8ef Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Thu, 23 Jun 2016 17:20:07 +0530 Subject: [PATCH] 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 6d3008cb1e0fa8bd8316398959785f45e0eef218) Change-Id: Ic46a99cd096c03d6af23c8fc50cac4bd2c70d0b1 --- src/vnsw/agent/kstate/test/test_kstate.cc | 4 ++-- src/vnsw/agent/services/icmpv6_handler.cc | 8 +++++-- src/vnsw/agent/services/icmpv6_proto.cc | 22 ++++++++++++++++--- src/vnsw/agent/services/icmpv6_proto.h | 9 +++++--- src/vnsw/agent/services/services.sandesh | 6 +++-- src/vnsw/agent/services/services_sandesh.cc | 10 +++++++-- .../agent/test/test_agent_route_walker.cc | 6 ++--- 7 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/vnsw/agent/kstate/test/test_kstate.cc b/src/vnsw/agent/kstate/test/test_kstate.cc index fb117c97184..855efd289bc 100644 --- a/src/vnsw/agent/kstate/test/test_kstate.cc +++ b/src/vnsw/agent/kstate/test/test_kstate.cc @@ -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(); diff --git a/src/vnsw/agent/services/icmpv6_handler.cc b/src/vnsw/agent/services/icmpv6_handler.cc index 6ebbb5ea3a5..fa7ca073498 100644 --- a/src/vnsw/agent/services/icmpv6_handler.cc +++ b/src/vnsw/agent/services/icmpv6_handler.cc @@ -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); @@ -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 bytes; for (int i = 0; i < 16; i++) { bytes[i] = icmp->nd_na_target.s6_addr[i]; diff --git a/src/vnsw/agent/services/icmpv6_proto.cc b/src/vnsw/agent/services/icmpv6_proto.cc index ded1f2668e5..0bd7d7e77e2 100644 --- a/src/vnsw/agent/services/icmpv6_proto.cc +++ b/src/vnsw/agent/services/icmpv6_proto.cc @@ -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 + (vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(), + addr, 128, + vn->GetName()); + addr = Ip6Address::from_string(IPV6_ALL_NODES_ADDRESS, ec); static_cast (vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(), addr, 128, @@ -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); @@ -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_++; } } diff --git a/src/vnsw/agent/services/icmpv6_proto.h b/src/vnsw/agent/services/icmpv6_proto.h index 728122af875..c6d8d663006 100644 --- a/src/vnsw/agent/services/icmpv6_proto.h +++ b/src/vnsw/agent/services/icmpv6_proto.h @@ -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_; @@ -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 VmInterfaceMap; @@ -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(); } diff --git a/src/vnsw/agent/services/services.sandesh b/src/vnsw/agent/services/services.sandesh index 23428e2e2a9..5078201518a 100644 --- a/src/vnsw/agent/services/services.sandesh +++ b/src/vnsw/agent/services/services.sandesh @@ -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; } /** @@ -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; } /** diff --git a/src/vnsw/agent/services/services_sandesh.cc b/src/vnsw/agent/services/services_sandesh.cc index 46e6fe46d1f..b92e7c9a426 100644 --- a/src/vnsw/agent/services/services_sandesh.cc +++ b/src/vnsw/agent/services/services_sandesh.cc @@ -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 g_ip_protocol_map = @@ -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(); diff --git a/src/vnsw/agent/test/test_agent_route_walker.cc b/src/vnsw/agent/test/test_agent_route_walker.cc index 2e4dd62cf5c..0866a6e4196 100644 --- a/src/vnsw/agent/test/test_agent_route_walker.cc +++ b/src/vnsw/agent/test/test_agent_route_walker.cc @@ -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); @@ -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); @@ -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);