OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
icmpv6_proto.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "base/os.h"
6 #include <init/agent_init.h>
7 #include <pkt/pkt_handler.h>
8 #include "pkt/pkt_init.h"
9 #include <oper/route_common.h>
10 #include <services/icmpv6_proto.h>
12 
13 Icmpv6Proto::Icmpv6Proto(Agent *agent, boost::asio::io_context &io) :
14  Proto(agent, "Agent::Services", PktHandler::ICMPV6, io) {
15  // limit the number of entries in the workqueue
17  work_queue_.SetBounded(true);
18 
20  boost::bind(&Icmpv6Proto::VnNotify, this, _2));
22  boost::bind(&Icmpv6Proto::VrfNotify, this, _1, _2));
24  boost::bind(&Icmpv6Proto::InterfaceNotify,
25  this, _2));
27  boost::bind(&Icmpv6Proto::NexthopNotify, this, _2));
28 
29  boost::shared_ptr<PktInfo> pkt_info(new PktInfo(PktHandler::ICMPV6, NULL));
30  icmpv6_handler_.reset(new Icmpv6Handler(agent, pkt_info, io));
31 
32  timer_ = TimerManager::CreateTimer(io, "Icmpv6Timer",
33  TaskScheduler::GetInstance()->GetTaskId("Agent::Services"),
37  icmpv6_handler_.get(), this));
38 }
39 
41 }
42 
47  timer_->Cancel();
49 }
50 
51 ProtoHandler *Icmpv6Proto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
52  boost::asio::io_context &io) {
53  return new Icmpv6Handler(agent(), info, io);
54 }
55 
57  Icmpv6VrfState *state = new Icmpv6VrfState(agent_, this, vrf,
59  vrf->GetEvpnRouteTable());
61  Register(boost::bind(&Icmpv6VrfState::RouteUpdate, state, _1, _2)));
63  Register(boost::bind(&Icmpv6VrfState::EvpnRouteUpdate, state, _1, _2)));
64  vrf->SetState(vrf->get_table_partition()->parent(),
65  vrf_table_listener_id_, state);
66  return state;
67 }
68 
70  if (entry->IsDeleted()) return;
71 
72  VnEntry *vn = static_cast<VnEntry *>(entry);
73  VrfEntry *vrf = vn->GetVrf();
74  if (!vrf || vrf->IsDeleted()) return;
75 
76  if (vrf->GetName() == agent_->fabric_vrf_name())
77  return;
78 
79  if (vn->layer3_forwarding()) {
80  Icmpv6VrfState *state = static_cast<Icmpv6VrfState *>(vrf->GetState(
81  vrf->get_table_partition()->parent(),
83  if (state == NULL) {
84  state = CreateAndSetVrfState(vrf);
85  }
86  if (state->default_routes_added()) {
87  return;
88  }
89 
90  boost::system::error_code ec;
91  Ip6Address addr = Ip6Address::from_string(IPV6_ALL_ROUTERS_ADDRESS, ec);
92  static_cast<InetUnicastAgentRouteTable *>
93  (vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(),
94  addr, 128,
95  vn->GetName(), false);
96  addr = Ip6Address::from_string(IPV6_ALL_NODES_ADDRESS, ec);
97  static_cast<InetUnicastAgentRouteTable *>
98  (vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(),
99  addr, 128,
100  vn->GetName(), false);
101  /* We need route for PKT0_LINKLOCAL_ADDRESS so that vrouter can respond
102  * to NDP requests for PKT0_LINKLOCAL_ADDRESS. Even though the nexthop
103  * for this route is pkt0, vrouter never sends pkts pointing to this
104  * route on pkt0.
105  */
106  addr = Ip6Address::from_string(PKT0_LINKLOCAL_ADDRESS, ec);
107  static_cast<InetUnicastAgentRouteTable *>
108  (vrf->GetInet6UnicastRouteTable())->AddHostRoute(vrf->GetName(),
109  addr, 128,
110  vn->GetName(), false);
111  state->set_default_routes_added(true);
112  }
113 }
114 
116  VrfEntry *vrf = static_cast<VrfEntry *>(entry);
117 
118  Icmpv6VrfState *state = static_cast<Icmpv6VrfState *>(vrf->GetState(
119  vrf->get_table_partition()->parent(),
121  if (entry->IsDeleted()) {
122  if (state) {
123  boost::system::error_code ec;
124  Ip6Address addr =
125  Ip6Address::from_string(IPV6_ALL_ROUTERS_ADDRESS, ec);
126  // enqueue delete request on fabric VRF
128  agent_->local_peer(), vrf->GetName(), addr, 128, NULL);
129  addr = Ip6Address::from_string(IPV6_ALL_NODES_ADDRESS, ec);
131  agent_->local_peer(), vrf->GetName(), addr, 128, NULL);
132  addr = Ip6Address::from_string(PKT0_LINKLOCAL_ADDRESS, ec);
134  agent_->local_peer(), vrf->GetName(), addr, 128, NULL);
135  state->set_default_routes_added(false);
136  state->Delete();
137  }
138  return;
139  }
140  if (!state) {
142  }
143 }
144 
146  Interface *intrface = static_cast<Interface *>(entry);
147  if (intrface->type() != Interface::VM_INTERFACE)
148  return;
149 
150  Icmpv6Stats stats;
151  VmInterface *vm_interface = static_cast<VmInterface *>(entry);
152  VmInterfaceMap::iterator it = vm_interfaces_.find(vm_interface);
153  if (intrface->IsDeleted()) {
154  if (it != vm_interfaces_.end()) {
155  vm_interfaces_.erase(it);
156  }
157  if (vm_interface->vmi_type() == VmInterface::VHOST) {
160  }
161  } else {
162  if (it == vm_interfaces_.end()) {
163  vm_interfaces_.insert(VmInterfacePair(vm_interface, stats));
164  }
165  if (vm_interface->vmi_type() == VmInterface::VHOST) {
166  set_ip_fabric_interface(intrface);
167  set_ip_fabric_interface_index(intrface->id());
168  set_ip_fabric_interface_mac(intrface->mac());
169  }
170  }
171 }
172 
174  const VrfEntry *vrf, InterfaceConstRef itf) {
175  Icmpv6Ipc *ipc = new Icmpv6Ipc(type, ip, vrf, itf);
177 }
178 
180  InterfaceConstRef itf) {
181  Icmpv6Ipc *ipc = new Icmpv6Ipc(type, key, itf);
183 }
184 
186  NextHop *nh = static_cast<NextHop *>(entry);
187 
188  switch(nh->GetType()) {
189  case NextHop::NDP: {
190  NdpNH *ndp_nh = (static_cast<NdpNH *>(nh));
191  if (ndp_nh->IsDeleted()) {
192  SendIcmpv6Ipc(Icmpv6Proto::NDP_DELETE, ndp_nh->GetIp()->to_v6(),
193  ndp_nh->GetVrf(), ndp_nh->GetInterface());
194  } else if (ndp_nh->IsValid() == false && ndp_nh->GetInterface()) {
195  SendIcmpv6Ipc(Icmpv6Proto::NDP_RESOLVE, ndp_nh->GetIp()->to_v6(),
196  ndp_nh->GetVrf(), ndp_nh->GetInterface());
197  }
198  break;
199  }
200 
201  default:
202  break;
203  }
204 }
205 
207  Icmpv6VrfState *vrf_state) {
208  if (!vrf->IsDeleted()) {
209  return false;
210  }
211 
212  if (vrf_state->l3_walk_completed() == false) {
213  return false;
214  }
215 
216  if (vrf_state->evpn_walk_completed() == false) {
217  return false;
218  }
219 
220  if (vrf_state->managed_delete_walk_ref().get() != NULL ||
221  vrf_state->evpn_walk_ref().get() != NULL) {
222  return false;
223  }
224 
225  DBState *state = static_cast<DBState *>
226  (vrf->GetState(vrf->get_table_partition()->parent(),
228  if (state) {
229  vrf->ClearState(vrf->get_table_partition()->parent(),
231  }
232  return true;
233 }
234 
236  InetUnicastRouteEntry *route = static_cast<InetUnicastRouteEntry *>(entry);
237 
238  Icmpv6RouteState *state = static_cast<Icmpv6RouteState *>
239  (entry->GetState(part->parent(), route_table_listener_id_));
240 
241 #if 0
242  // This is the code for sending unsolicited NA for vhost0 but it should
243  // be taken care of by linux itself
244  const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>(
245  route->GetActiveNextHop());
246  const Interface *intf = (intf_nh) ?
247  static_cast<const Interface *>(intf_nh->GetInterface()) : NULL;
248 
249  NdpKey key(route->prefix_address().to_v6(), route->vrf());
250  NdpEntry *ndpentry = icmp_proto_->UnsolNaEntry(key, intf);
251  if (route->vrf()->GetName() == agent_->fabric_vrf_name()) {
253  }
254 #endif
255  if (entry->IsDeleted() || deleted_) {
256  if (state) {
257  //icmp_proto_->DeleteUnsolNaEntry(ndpentry);
258  entry->ClearState(part->parent(), route_table_listener_id_);
259  delete state;
260  }
261  return;
262  }
263 
264  if (!state) {
265  state = new Icmpv6RouteState(this, route->vrf_id(), route->prefix_address(),
266  route->prefix_length());
267  entry->SetState(part->parent(), route_table_listener_id_, state);
268  }
269 
270 #if 0
271  // May not be needed since kernel can take care of sending unsolicited NA
272  if (route->vrf()->GetName() == agent_->fabric_vrf_name() &&
273  route->GetActiveNextHop()->GetType() == NextHop::RECEIVE &&
274  icmp_proto_->agent()->router_id6() == route->prefix_address().to_v6()) {
275  //Send unsolicited NA
278  route->prefix_address().to_v6(), route->vrf(),
280  }
281 #endif
282 
283  //Check if there is a local VM path, if yes send a
284  //Neighbor Solicit request, to trigger route preference state machine
285  if (state && route->GetTableType() == Agent::INET6_UNICAST &&
286  route->vrf()->GetName() != agent_->fabric_vrf_name()) {
287  state->SendNeighborSolicitForAllIntf(route);
288  }
289 }
290 
292  EvpnRouteEntry *route = static_cast<EvpnRouteEntry *>(entry);
293 
294  Icmpv6RouteState *state = static_cast<Icmpv6RouteState *>
295  (entry->GetState(part->parent(), evpn_route_table_listener_id_));
296 
297  if (entry->IsDeleted() || deleted_) {
298  if (state) {
300  delete state;
301  }
302  return;
303  }
304 
305  if (!state) {
306  state = new Icmpv6RouteState(this, route->vrf_id(), route->prefix_address(),
307  route->prefix_length());
308  entry->SetState(part->parent(), evpn_route_table_listener_id_, state);
309  }
310 
311  //Check if there is a local VM path, if yes send a
312  //Neighbor Solicit request, to trigger route preference state machine
313  if (state && route->vrf()->GetName() != agent_->fabric_vrf_name()) {
314  state->SendNeighborSolicitForAllIntf(route);
315  }
316 }
317 
319  RouteUpdate(part, ent);
320  return true;
321 }
322 
324  DBEntryBase *ent) {
325  EvpnRouteUpdate(part, ent);
326  return true;
327 }
328 
330  if (managed_delete_walk_ref_.get() == NULL)
331  return;
332 
334  if (evpn_walk_ref_.get())
336  deleted_ = true;
337 }
338 
340  if (icmp_proto_->ValidateAndClearVrfState(vrf_, this) == false) {
341  return false;
342  }
343 
345  table_delete_ref_.Reset(NULL);
346 
349  return true;
350 }
351 
353  if (partition == state->rt_table_) {
355  state->managed_delete_walk_ref_ = NULL;
356  state->l3_walk_completed_ = true;
357  } else {
359  state->evpn_walk_ref_ = NULL;
360  state->evpn_walk_completed_ = true;
361  }
362 
363  if (state->PreWalkDone(partition)) {
364  delete state;
365  }
366 }
367 
370  if (ptr == NULL) {
371  ptr = new Icmpv6PathPreferenceState(this, vrf_->vrf_id(), ip, 128);
372  icmpv6_path_preference_map_[ip] = ptr;
373  }
374  return ptr;
375 }
376 
378  WaitForTrafficIntfMap::iterator it = l3_wait_for_traffic_map_.find(itf);
379  if (it == l3_wait_for_traffic_map_.end()) {
380  return;
381  }
382  InterfaceIcmpv6PathPreferenceInfo &data = it->second;
383 
384  // resetting ns_try_count as interface sent NA
385  data.ns_try_count = 0;
386 
387 }
388 
389 void Icmpv6Proto::HandlePathPreferenceNA(const VrfEntry *vrf, uint32_t itf,
390  IpAddress sip) {
391  if (!vrf) {
392  return;
393  }
394  InetUnicastRouteEntry *rt = vrf->GetUcRoute(sip);
395  if (!rt) {
396  return;
397  }
398 
399  Icmpv6VrfState *state = static_cast<Icmpv6VrfState *>
400  (vrf->GetState(vrf->get_table_partition()->parent(),
402  if (!state) {
403  return;
404  }
405  Icmpv6PathPreferenceState *pstate = state->Get(sip);
406  if (!pstate) {
407  return;
408  }
409  pstate->HandleNA(itf);
410 }
411 
413  icmpv6_path_preference_map_.erase(ip);
414 }
415 
417  VrfEntry *vrf_entry, AgentRouteTable *table,
418  AgentRouteTable *evpn_rt_table):
419  agent_(agent_ptr), icmp_proto_(proto), vrf_(vrf_entry), rt_table_(table),
420  evpn_rt_table_(evpn_rt_table),
421  route_table_listener_id_(DBTableBase::kInvalidId),
422  evpn_route_table_listener_id_(DBTableBase::kInvalidId),
423  table_delete_ref_(this, table->deleter()),
424  evpn_table_delete_ref_(this, evpn_rt_table_->deleter()),
425  deleted_(false),
426  default_routes_added_(false), l3_walk_completed_(false),
427  evpn_walk_completed_(false) {
429  boost::bind(&Icmpv6VrfState::DeleteEvpnRouteState, this, _1, _2),
430  boost::bind(&Icmpv6VrfState::WalkDone, _2, this));
432  boost::bind(&Icmpv6VrfState::DeleteRouteState, this, _1, _2),
433  boost::bind(&Icmpv6VrfState::WalkDone, _2, this));
434 }
435 
437  assert(icmpv6_path_preference_map_.size() == 0);
438 }
439 
441  ps->refcount_.fetch_and_increment();
442 }
443 
445  Icmpv6VrfState *state = ps->vrf_state();
446  int prev = ps->refcount_.fetch_and_decrement();
447  if (prev == 1) {
448  state->Erase(ps->ip());
449  delete ps;
450  }
451 }
452 
454  Icmpv6VrfState *vrf_state, uint32_t vrf_id,
455  IpAddress ip, uint8_t plen) :
456  vrf_state_(vrf_state), ns_req_timer_(NULL), vrf_id_(vrf_id), vm_ip_(ip),
457  plen_(plen), svc_ip_(Ip6Address()) {
458  refcount_ = 0;
459 }
460 
462  if (ns_req_timer_) {
465  }
466  assert(refcount_ == 0);
467 }
468 
470  &wait_for_traffic_map,
472  &nd_transmitted_map) {
473  bool ret = false;
474  boost::shared_ptr<PktInfo> pkt(new PktInfo(vrf_state_->agent(),
476  PktHandler::ICMPV6, 0));
477  Icmpv6Handler handler(vrf_state_->agent(), pkt,
479 
480  WaitForTrafficIntfMap::iterator it = wait_for_traffic_map.begin();
481  for (;it != wait_for_traffic_map.end(); it++) {
482 
483  VmInterface *vm_intf = static_cast<VmInterface *>(
484  vrf_state_->agent()->interface_table()->FindInterface(it->first));
485  if (!vm_intf) {
486  continue;
487  }
488  InterfaceIcmpv6PathPreferenceInfo &data = it->second;
489  bool inserted = nd_transmitted_map.insert(it->first).second;
490  ++data.ns_retry_count;
491  if (inserted == false) {
492  continue;
493  }
494 
496  GetMacIpLearningTable()->GetPairedMacAddress(
497  vm_intf->vrf_id(), ip());
498  if (mil_mac != MacAddress()) {
499  ++data.ns_try_count;
500  if (data.ns_try_count == kNSTryCount) {
501  IpAddress ip = vm_ip_;
502  MacAddress mac = mil_mac;
504  GetMacIpLearningTable()->MacIpEntryUnreachable(
505  vm_intf->vrf_id(), ip, mac);
506  return true;
507  }
508  }
509 
510  Ip6Address src_addr;
511  if (svc_ip_.is_unspecified() == false && svc_ip_.is_v6())
512  src_addr = svc_ip_.to_v6();
513  handler.SendNeighborSolicit(src_addr, vm_ip_.to_v6(), vm_intf, vrf_id_);
514 
516  ++data.ns_send_count;
517 
518  // reduce the frequency of NS requests after some tries
519  if (data.ns_send_count >= kMaxRetry) {
520  // change frequency only if not in gateway mode with remote VMIs and
521  // learnt mac is not present
522  if (vm_intf->vmi_type() != VmInterface::REMOTE_VM
523  && mil_mac == MacAddress()) {
525  }
526  }
527 
528  ret = true;
529  }
530  return ret;
531 }
532 
534  if (l3_wait_for_traffic_map_.size() == 0 &&
535  evpn_wait_for_traffic_map_.size() == 0) {
536  return false;
537  }
538 
539  bool ret = false;
540  NDTransmittedIntfMap nd_transmitted_map;
541  if (SendNeighborSolicit(l3_wait_for_traffic_map_, nd_transmitted_map)) {
542  ret = true;
543  }
544 
545  if (SendNeighborSolicit(evpn_wait_for_traffic_map_, nd_transmitted_map)) {
546  ret = true;
547  }
548  return ret;
549 }
550 
552  if (ns_req_timer_ == NULL) {
555  "Neighbor Solicit Request timer for VM",
556  TaskScheduler::GetInstance()->GetTaskId("Agent::Services"),
558  }
560  boost::bind(&Icmpv6PathPreferenceState::
562  this));
563 }
564 
566  uint32_t vrf_id, IpAddress ip,
567  uint8_t plen) {
568  if (plen == Address::kMaxV6PrefixLen) {
569  icmpv6_path_preference_state_ = vrf_state->Locate(ip);
570  }
571 }
572 
574  icmpv6_path_preference_state_.reset(NULL);
575 }
576 
578  if (icmpv6_path_preference_state_.get()) {
579  icmpv6_path_preference_state_->SendNeighborSolicitForAllIntf(route);
580  }
581 }
582 
583 //Send Neighbor Solicit request on interface in Active-BackUp mode
584 //So that preference of route can be incremented if the VM replies with
585 //Neighbor Advertisement
587  (const AgentRoute *route) {
588 
589  WaitForTrafficIntfMap wait_for_traffic_map = evpn_wait_for_traffic_map_;
590  if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
591  wait_for_traffic_map = l3_wait_for_traffic_map_;
592  }
593 
594  WaitForTrafficIntfMap new_wait_for_traffic_map;
595  for (Route::PathList::const_iterator it = route->GetPathList().begin();
596  it != route->GetPathList().end(); it++) {
597  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
598  if (path->peer() &&
599  path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
600  const NextHop *nh = path->ComputeNextHop(vrf_state_->agent());
601  if (nh->GetType() != NextHop::INTERFACE) {
602  continue;
603  }
604 
605  const InterfaceNH *intf_nh =
606  static_cast<const InterfaceNH *>(nh);
607  const Interface *intf =
608  static_cast<const Interface *>(intf_nh->GetInterface());
609  if (intf->type() != Interface::VM_INTERFACE) {
610  //Ignore non vm interface nexthop
611  continue;
612  }
613  if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
614  const VmInterface *vm_intf =
615  static_cast<const VmInterface *>(intf);
616  if (vm_intf->primary_ip6_addr().is_unspecified() == false) {
617  svc_ip_ = vm_intf->GetServiceIp(vm_intf->primary_ip6_addr());
618  }
619  }
620 
621  if (path->path_preference().IsDependentRt() == true) {
622  continue;
623  }
624 
625  uint32_t intf_id = intf->id();
626  WaitForTrafficIntfMap::const_iterator wait_for_traffic_it =
627  wait_for_traffic_map.find(intf_id);
628  if (wait_for_traffic_it == wait_for_traffic_map.end()) {
630  new_wait_for_traffic_map.insert(std::make_pair(intf_id, data));
631  } else {
632  new_wait_for_traffic_map.insert(std::make_pair(intf_id,
633  wait_for_traffic_it->second));
634  }
635  }
636  }
637 
638 
639  if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
640  l3_wait_for_traffic_map_ = new_wait_for_traffic_map;
641  } else {
642  evpn_wait_for_traffic_map_ = new_wait_for_traffic_map;
643  }
644  if (new_wait_for_traffic_map.size() > 0) {
645  SendNeighborSolicit();
646  StartTimer();
647  }
648 }
649 
651  VmInterfaceMap::iterator it = vm_interfaces_.find(i);
652  if (it == vm_interfaces_.end()) {
653  return NULL;
654  }
655  return &it->second;
656 }
657 
660  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
661  if (stats) {
662  stats->icmpv6_router_solicit_++;
663  }
664 }
665 
668  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
669  if (stats) {
670  stats->icmpv6_router_advert_++;
671  }
672 }
673 
676  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
677  if (stats) {
678  stats->icmpv6_ping_request_++;
679  }
680 }
681 
684  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
685  if (stats) {
686  stats->icmpv6_ping_response_++;
687  }
688 }
689 
692  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
693  if (stats) {
694  stats->icmpv6_neighbor_solicit_++;
695  }
696 }
697 
700  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
701  if (stats) {
703  }
704 }
705 
708  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
709  if (stats) {
711  }
712 }
713 
716  Icmpv6Stats *stats = VmiToIcmpv6Stats(vmi);
717  if (stats) {
719  }
720 }
721 
724  if (iter == unsol_na_cache_.end()) {
725  return NULL;
726  }
727  return *iter->second.begin();
728 }
729 
731  NdpEntrySet empty_set;
732  unsol_na_cache_.insert(UnsolNaCachePair(key, empty_set));
733 }
734 
736  if (!entry)
737  return ;
738 
739  Icmpv6Proto::UnsolNaIterator iter = unsol_na_cache_.find(entry->key());
740  if (iter == unsol_na_cache_.end()) {
741  return;
742  }
743 
744  iter->second.erase(entry);
745  delete entry;
746  if (iter->second.empty()) {
747  unsol_na_cache_.erase(iter);
748  }
749 }
750 
751 NdpEntry *
752 Icmpv6Proto::UnsolNaEntry(const NdpKey &key, const Interface *intf) {
754  if (it == unsol_na_cache_.end())
755  return NULL;
756 
757  for (NdpEntrySet::iterator sit = it->second.begin();
758  sit != it->second.end(); sit++) {
759  NdpEntry *entry = *sit;
760  if (entry->get_interface() == intf)
761  return *sit;
762  }
763 
764  return NULL;
765 }
766 
768 Icmpv6Proto::UnsolNaEntryIterator(const NdpKey &key, bool *key_valid) {
770  if (it == unsol_na_cache_.end())
771  return it;
772  const VrfEntry *vrf = key.vrf;
773  if (!vrf)
774  return it;
775  const Icmpv6VrfState *state = static_cast<const Icmpv6VrfState *>
776  (vrf->GetState(vrf->get_table_partition()->parent(),
778  // If VRF is delete marked, do not add Ndp entries to cache
779  if (state == NULL || state->deleted() == true)
780  return it;
781  *key_valid = true;
782  return it;
783 }
784 
786  const VrfEntry *vrf = entry->key().vrf;
787  const Icmpv6VrfState *state = static_cast<const Icmpv6VrfState *>
788  (vrf->GetState(vrf->get_table_partition()->parent(),
790  // If VRF is delete marked, do not add Ndp entries to cache
791  if (state == NULL || state->deleted() == true)
792  return false;
793 
794  bool ret = ndp_cache_.insert(NdpCachePair(entry->key(), entry)).second;
795  uint32_t intf_id = entry->get_interface()->id();
796  InterfaceNdpMap::iterator it = interface_ndp_map_.find(intf_id);
797  if (it == interface_ndp_map_.end()) {
798  InterfaceNdpInfo intf_entry;
799  intf_entry.ndp_key_list.insert(entry->key());
800  interface_ndp_map_.insert(InterfaceNdpPair(intf_id, intf_entry));
801  } else {
802  InterfaceNdpInfo &intf_entry = it->second;
803  NdpKeySet::iterator key_it = intf_entry.ndp_key_list.find(entry->key());
804  if (key_it == intf_entry.ndp_key_list.end()) {
805  intf_entry.ndp_key_list.insert(entry->key());
806  }
807  }
808  return ret;
809 }
810 
812  if (!entry)
813  return false;
814 
815  Icmpv6Proto::NdpIterator iter = ndp_cache_.find(entry->key());
816  if (iter == ndp_cache_.end()) {
817  return false;
818  }
819 
820  DeleteNdpEntry(iter);
821  return true;
822 }
823 
826  NdpEntry *entry = iter->second;
827  ndp_cache_.erase(iter++);
828  delete entry;
829  return iter;
830 }
831 
833  NdpIterator it = ndp_cache_.find(key);
834  if (it == ndp_cache_.end())
835  return NULL;
836  return it->second;
837 }
uint8_t prefix_length() const
!
uint32_t vrf_id() const
std::map< NdpKey, NdpEntrySet >::iterator UnsolNaIterator
Definition: icmpv6_proto.h:86
DBTable::DBTableWalkRef managed_delete_walk_ref()
Definition: icmpv6_proto.h:227
void SetBounded(bool bounded)
Definition: queue_task.h:200
const Interface * GetInterface() const
Definition: nexthop.h:1293
int intrusive_ptr_add_ref(const AsPath *cpath)
Definition: bgp_aspath.h:147
NdpEntry * FindNdpEntry(const NdpKey &key)
bool l3_walk_completed() const
Definition: icmpv6_proto.h:220
Icmpv6Proto * icmp_proto_
Definition: icmpv6_proto.h:236
Type type() const
Definition: interface.h:112
Icmpv6PathPreferenceState * Locate(const IpAddress &ip)
void HandlePathPreferenceNA(const VrfEntry *, uint32_t, IpAddress)
bool deleted() const
Definition: icmpv6_proto.h:212
bool DeleteNdpEntry(NdpEntry *entry)
void SendMessage(PktModuleName mod, InterTaskMsg *msg)
static const uint8_t kMaxV6PrefixLen
Definition: address.h:22
static const uint32_t kNSTryCount
Definition: icmpv6_proto.h:271
Definition: vrf.h:86
std::pair< VmInterface *, Icmpv6Stats > VmInterfacePair
Definition: icmpv6_proto.h:78
Icmpv6Proto * icmp_proto() const
Definition: icmpv6_proto.h:194
const PathPreference & path_preference() const
Definition: agent_path.h:329
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
void VrfNotify(DBTablePartBase *part, DBEntryBase *entry)
DBTable::DBTableWalkRef evpn_walk_ref()
Definition: icmpv6_proto.h:230
Icmpv6VrfState(Agent *agent, Icmpv6Proto *proto, VrfEntry *vrf, AgentRouteTable *table, AgentRouteTable *evpn_table)
InetUnicastAgentRouteTable * fabric_inet4_unicast_table() const
Definition: agent.h:578
const uint32_t id() const
Definition: interface.h:123
NextHopTable * nexthop_table() const
Definition: agent.h:475
Icmpv6VrfState * vrf_state_
Definition: icmpv6_proto.h:322
WaitForTrafficIntfMap l3_wait_for_traffic_map_
Definition: icmpv6_proto.h:329
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge, EVPN (Type2/Type5). This base class contains common code for all types of route tables.
Definition: agent_route.h:109
void IncrementStatsNeighborAdvertUnSolicited(VmInterface *vmi)
void set_route_table_listener_id(const DBTableBase::ListenerId &id)
Definition: icmpv6_proto.h:195
bool PreWalkDone(DBTableBase *partition)
void SendNeighborSolicitForAllIntf(const AgentRoute *route)
const Interface * GetInterface() const
Definition: nexthop.h:926
bool IsDeleted() const
Definition: db_entry.h:49
const IpAddress * GetIp() const
Definition: nexthop.h:929
DBTableBase::ListenerId evpn_route_table_listener_id_
Definition: icmpv6_proto.h:241
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
Icmpv6RouteState(Icmpv6VrfState *vrf_state, uint32_t vrf_id, IpAddress vm_ip_addr, uint8_t plen)
DBTableBase::ListenerId vrf_table_listener_id_
Definition: icmpv6_proto.h:174
boost::asio::ip::address IpAddress
Definition: address.h:13
MacLearningProto * mac_learning_proto() const
Definition: agent.h:1005
uint32_t icmpv6_neighbor_advert_solicited_
Definition: icmpv6_proto.h:73
AgentRouteTable * rt_table_
Definition: icmpv6_proto.h:238
const VrfEntry * GetVrf() const
Definition: nexthop.h:930
tbb::atomic< int > refcount_
Definition: icmpv6_proto.h:331
Icmpv6Stats * VmiToIcmpv6Stats(VmInterface *i)
DBTableWalkRef AllocWalker(WalkFn walk_fn, WalkCompleteFn walk_complete)
Definition: db_table.cc:613
boost::asio::io_context * io_service()
Definition: event_manager.h:42
DBTableBase * parent()
InterfaceTable * interface_table() const
Definition: agent.h:465
UnsolNaCache unsol_na_cache_
Definition: icmpv6_proto.h:164
VnTable * vn_table() const
Definition: agent.h:495
uint32_t icmpv6_neighbor_solicit_
Definition: icmpv6_proto.h:71
bool RouterAdvertisement(Icmpv6Proto *proto)
Icmpv6PathPreferenceStatePtr icmpv6_path_preference_state_
Definition: icmpv6_proto.h:347
void SendIcmpv6Ipc(Icmpv6Proto::Icmpv6MsgType type, Ip6Address ip, const VrfEntry *vrf, InterfaceConstRef itf)
bool default_routes_added() const
Definition: icmpv6_proto.h:201
void set_evpn_route_table_listener_id(const DBTableBase::ListenerId &id)
Definition: icmpv6_proto.h:198
InetUnicastAgentRouteTable * GetInet6UnicastRouteTable() const
Definition: vrf.cc:338
const string & GetName() const
Definition: vrf.h:100
const MacAddress & mac() const
Definition: interface.h:131
static const uint32_t kTimeoutMultiplier
Definition: icmpv6_proto.h:269
Agent * agent() const
Definition: icmpv6_proto.h:193
IpAddress GetServiceIp(const IpAddress &ip) const
ProtoHandler * AllocProtoHandler(boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
Definition: icmpv6_proto.cc:51
void IncrementStatsNeighborSolicit(VmInterface *vmi)
Type GetType() const
Definition: nexthop.h:405
Base class for all Route entries in agent.
Definition: agent_route.h:224
void set_ip_fabric_interface_mac(const MacAddress &mac)
Definition: icmpv6_proto.h:136
void Unregister(ListenerId listener)
Definition: db_table.cc:186
DBTableBase::ListenerId interface_listener_id_
Definition: icmpv6_proto.h:175
Icmpv6VrfState * vrf_state()
Definition: icmpv6_proto.h:285
LifetimeRef< Icmpv6VrfState > evpn_table_delete_ref_
Definition: icmpv6_proto.h:243
void ReleaseWalker(DBTableWalkRef &walk)
Definition: db_table.cc:619
int GetTaskId(const std::string &name)
Definition: task.cc:856
static const uint32_t kMaxRetry
Definition: icmpv6_proto.h:265
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
const std::string & fabric_vrf_name() const
Definition: agent.h:903
const Type GetType() const
Definition: peer.h:87
void IncrementStatsRouterSolicit(VmInterface *vmi)
void WalkAgain(DBTableWalkRef walk)
Definition: db_table.cc:631
void IncrementStatsPingResponse(VmInterface *vmi)
bool IsValid() const
Definition: nexthop.h:406
std::set< uint32_t > NDTransmittedIntfMap
Definition: icmpv6_proto.h:274
static const uint32_t kRouterAdvertTimeout
Definition: icmpv6_proto.h:34
static void WalkDone(DBTableBase *partition, Icmpv6VrfState *state)
void IncrementStatsNeighborSolicited(VmInterface *vmi)
uint8_t type
Definition: load_balance.h:109
bool IsDependentRt(void) const
Definition: agent_path.h:156
void HandleNA(uint32_t itf)
NdpEntry * UnsolNaEntry(const NdpKey &key, const Interface *intf)
void SetSize(size_t size)
Definition: queue_task.h:196
void IncrementStatsNeighborAdvertSolicited(VmInterface *vmi)
Definition: agent.h:358
bool ValidateAndClearVrfState(VrfEntry *vrf, Icmpv6VrfState *state)
void IncrementStatsRouterAdvert(VmInterface *vmi)
uint32_t vrf_id() const
Definition: interface.cc:621
static TaskScheduler * GetInstance()
Definition: task.cc:547
void Reset(LifetimeActor *actor)
Definition: lifetime.h:82
#define IPV6_ALL_ROUTERS_ADDRESS
Definition: icmpv6_proto.h:14
AgentRouteTable * evpn_rt_table_
Definition: icmpv6_proto.h:239
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:881
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
void set_ip_fabric_interface_index(uint32_t ind)
Definition: icmpv6_proto.h:133
EventManager * event_manager() const
Definition: agent.h:1103
uint32_t icmpv6_neighbor_advert_unsolicited_
Definition: icmpv6_proto.h:74
const VrfEntry * vrf
Definition: ndp_entry.h:31
Icmpv6PathPreferenceState(Icmpv6VrfState *vrf_state, uint32_t vrf_id, IpAddress vm_ip_addr, uint8_t plen)
Definition: nexthop.h:909
const Peer * peer() const
Definition: agent_path.h:263
void set_ip_fabric_interface(Interface *itf)
Definition: icmpv6_proto.h:132
void NexthopNotify(DBEntryBase *entry)
DBTableBase::ListenerId vn_table_listener_id_
Definition: icmpv6_proto.h:173
void Erase(const IpAddress &ip)
#define PKT0_LINKLOCAL_ADDRESS
Definition: icmpv6_proto.h:15
boost::intrusive_ptr< const Interface > InterfaceConstRef
Definition: agent.h:51
Icmpv6Stats stats_
Definition: icmpv6_proto.h:161
void SendNeighborSolicitForAllIntf(const AgentRoute *route)
const Peer * local_peer() const
Definition: agent.h:1022
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
DBTable::DBTableWalkRef managed_delete_walk_ref_
Definition: icmpv6_proto.h:246
std::set< NdpEntry * > NdpEntrySet
Definition: icmpv6_proto.h:83
const Interface * get_interface() const
Definition: ndp_entry.h:58
void AddUnsolNaEntry(NdpKey &key)
AgentParam * params() const
Definition: agent.h:1218
void DeleteUnsolNaEntry(NdpEntry *entry)
virtual Agent::RouteTableType GetTableType() const
const uint32_t vrf_id() const
Definition: vrf.h:99
static void DeleteReq(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen, AgentRouteData *data)
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
Definition: timer.cc:201
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
Icmpv6Proto::UnsolNaIterator UnsolNaEntryIterator(const NdpKey &key, bool *key_valid)
IpAddress router_id6() const
Definition: agent.h:667
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:375
std::pair< NdpKey, NdpEntry * > NdpCachePair
Definition: icmpv6_proto.h:80
boost::scoped_ptr< Icmpv6Handler > icmpv6_handler_
Definition: icmpv6_proto.h:172
void EvpnRouteUpdate(DBTablePartBase *part, DBEntryBase *entry)
void SendNeighborSolicit(const Ip6Address &sip, const Ip6Address &dip, const VmInterface *vmi, uint32_t vrf, bool send_unicast=false)
bool Cancel()
Definition: timer.cc:150
Definition: vn.h:151
std::pair< uint32_t, InterfaceNdpInfo > InterfaceNdpPair
Definition: icmpv6_proto.h:94
NdpCache ndp_cache_
Definition: icmpv6_proto.h:163
void RouteUpdate(DBTablePartBase *part, DBEntryBase *entry)
VrfTable * vrf_table() const
Definition: agent.h:485
MacAddress mac(void) const
Definition: icmpv6_proto.h:293
static const uint32_t kTimeout
Definition: icmpv6_proto.h:267
bool DeleteEvpnRouteState(DBTablePartBase *part, DBEntryBase *entry)
VrfEntry * GetVrf() const
Definition: vn.h:170
uint32_t services_queue_limit()
Definition: agent_param.h:417
uint8_t prefix_length() const
!
NdpEntry * FindUnsolNaEntry(NdpKey &key)
bool layer3_forwarding() const
Definition: vn.h:192
VmInterface::VmiType vmi_type() const
Icmpv6PathPreferenceState * Get(const IpAddress ip)
Definition: icmpv6_proto.h:216
VmInterfaceMap vm_interfaces_
Definition: icmpv6_proto.h:162
const Ip6Address & primary_ip6_addr() const
Icmpv6PathPreferenceStateMap icmpv6_path_preference_map_
Definition: icmpv6_proto.h:248
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
std::pair< NdpKey, NdpEntrySet > UnsolNaCachePair
Definition: icmpv6_proto.h:85
std::map< uint32_t, InterfaceIcmpv6PathPreferenceInfo > WaitForTrafficIntfMap
Definition: icmpv6_proto.h:273
#define ICMP_PKT_SIZE
Definition: icmpv6_proto.h:12
Timer * timer_
Definition: icmpv6_proto.h:160
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
LifetimeRef< Icmpv6VrfState > table_delete_ref_
Definition: icmpv6_proto.h:242
virtual ~Icmpv6Proto()
Definition: icmpv6_proto.cc:40
VrfEntry * vrf() const
Definition: agent_route.h:275
void intrusive_ptr_release(const AsPath *cpath)
Definition: bgp_aspath.h:155
bool AddNdpEntry(NdpEntry *entry)
void set_default_routes_added(bool value)
Definition: icmpv6_proto.h:202
DBTable::DBTableWalkRef evpn_walk_ref_
Definition: icmpv6_proto.h:247
InterfaceNdpMap interface_ndp_map_
Definition: icmpv6_proto.h:165
const IpAddress & ip() const
Definition: icmpv6_proto.h:289
DBTableBase::ListenerId nexthop_listener_id_
Definition: icmpv6_proto.h:176
void VnNotify(DBEntryBase *entry)
Definition: icmpv6_proto.cc:69
virtual const NextHop * ComputeNextHop(Agent *agent) const
Definition: agent_path.cc:91
bool DeleteRouteState(DBTablePartBase *part, DBEntryBase *entry)
const string & GetName() const
Definition: vn.h:162
DBTablePartBase * get_table_partition() const
Definition: db_entry.cc:115
uint32_t icmpv6_neighbor_solicited_
Definition: icmpv6_proto.h:72
void IncrementStatsPingRequest(VmInterface *vmi)
bool Reschedule(int time)
Definition: timer.cc:137
bool evpn_walk_completed_
Definition: icmpv6_proto.h:250
Icmpv6VrfState * CreateAndSetVrfState(VrfEntry *vrf)
Definition: icmpv6_proto.cc:56
const NdpKey & key() const
Definition: ndp_entry.h:57
PktModule * pkt() const
Definition: agent.cc:965
Icmpv6Proto(Agent *agent, boost::asio::io_context &io)
Definition: icmpv6_proto.cc:13
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
Definition: vrf.cc:237
Interface * ip_fabric_interface() const
Definition: icmpv6_proto.h:125
VrfEntry * vrf_
Definition: icmpv6_proto.h:237
#define IPV6_ALL_NODES_ADDRESS
Definition: icmpv6_proto.h:13
DBTableBase::ListenerId route_table_listener_id_
Definition: icmpv6_proto.h:240
std::map< NdpKey, NdpEntry * >::iterator NdpIterator
Definition: icmpv6_proto.h:81
void InterfaceNotify(DBEntryBase *entry)
WaitForTrafficIntfMap evpn_wait_for_traffic_map_
Definition: icmpv6_proto.h:330
void Shutdown()
Definition: icmpv6_proto.cc:43
bool evpn_walk_completed() const
Definition: icmpv6_proto.h:224
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:222
const PathList & GetPathList() const
Definition: route.h:46
bool l3_walk_completed_
Definition: icmpv6_proto.h:249