OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
path_resolver.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include <boost/foreach.hpp>
8 
9 #include "base/lifetime.h"
10 #include "base/set_util.h"
11 #include "base/task.h"
12 #include "base/task_annotations.h"
13 #include "base/task_trigger.h"
14 #include "bgp/bgp_log.h"
15 #include "bgp/bgp_peer_types.h"
16 #include "bgp/bgp_server.h"
17 #include "bgp/bgp_table.h"
19 #include "bgp/inet/inet_route.h"
20 #include "bgp/inet6/inet6_route.h"
21 #include "bgp/evpn/evpn_route.h"
24 
25 using std::make_pair;
26 using std::string;
27 using std::vector;
28 
29 //
30 // Return true if the prefix for the BgpRoute is the same as given IpAddress.
31 //
32 static bool RoutePrefixIsAddress(Address::Family family, const BgpRoute *route,
33  const IpAddress &address) {
34  if (family == Address::INET) {
35  const InetRoute *inet_route = static_cast<const InetRoute *>(route);
36  if (inet_route->GetPrefix().addr() == address.to_v4() &&
37  inet_route->GetPrefix().prefixlen() == Address::kMaxV4PrefixLen) {
38  return true;
39  }
40  } else if (family == Address::INET6) {
41  const Inet6Route *inet6_route = static_cast<const Inet6Route *>(route);
42  if (inet6_route->GetPrefix().addr() == address.to_v6() &&
43  inet6_route->GetPrefix().prefixlen() == Address::kMaxV6PrefixLen) {
44  return true;
45  }
46  } else if (family == Address::EVPN) {
47  const EvpnRoute *evpn_route = static_cast<const EvpnRoute *>(route);
48  if (evpn_route->GetPrefix().family() == Address::INET && address.is_v4()) {
49  if (evpn_route->GetPrefix().addr().to_v4() == address.to_v4() &&
50  evpn_route->GetPrefix().prefixlen() == Address::kMaxV4PrefixLen) {
51  return true;
52  }
53  } else if (evpn_route->GetPrefix().family() == Address::INET6 &&
54  address.is_v6()) {
55  if (evpn_route->GetPrefix().addr().to_v6() == address.to_v6() &&
56  evpn_route->GetPrefix().prefixlen() == Address::kMaxV6PrefixLen) {
57  return true;
58  }
59  }
60  }
61  return false;
62 }
63 
64 // Return true if prefix matches the address.
66  const IpAddress &address) {
67  const InetRoute *inet_route = dynamic_cast<const InetRoute *>(route);
68  if (inet_route) {
69  Ip4Prefix prefix(address.to_v4(), Address::kMaxV4PrefixLen);
70  return prefix.IsMoreSpecific(inet_route->GetPrefix());
71  }
72 
73  const Inet6Route *inet6_route = dynamic_cast<const Inet6Route *>(route);
74  if (inet6_route) {
75  Inet6Prefix prefix(address.to_v6(), Address::kMaxV6PrefixLen);
76  return prefix.IsMoreSpecific(inet6_route->GetPrefix());
77  }
78 
79  const EvpnRoute *evpn_route = static_cast<const EvpnRoute *>(route);
80  if (evpn_route == nullptr) {
81  return false;
82  }
83  if (evpn_route->GetPrefix().family() == Address::INET) {
84  Ip4Prefix prefix(address.to_v4(), Address::kMaxV4PrefixLen);
85  return prefix.IsMoreSpecific(evpn_route->GetPrefix().inet_prefix());
86  } else if (evpn_route->GetPrefix().family() == Address::INET6) {
87  Inet6Prefix prefix(address.to_v6(), Address::kMaxV6PrefixLen);
88  return prefix.IsMoreSpecific(evpn_route->GetPrefix().inet6_prefix());
89  } else {
90  return false;
91  }
92 }
93 
95 public:
96  explicit DeleteActor(PathResolver *resolver)
97  : LifetimeActor(resolver->table()->server()->lifetime_manager()),
98  resolver_(resolver) {
99  }
100  virtual ~DeleteActor() {
101  }
102 
103  virtual bool MayDelete() const {
104  return resolver_->MayDelete();
105  }
106 
107  virtual void Destroy() {
109  }
110 
111 private:
113 };
114 
115 //
116 // Constructor for PathResolver.
117 //
118 // A new PathResolver is created from BgpTable::CreatePathResolver for inet
119 // and inet6 tables in all non-default RoutingInstances.
120 //
121 // The listener_id if used to set state on BgpRoutes for BgpPaths that have
122 // requested resolution.
123 //
125  : table_(table),
126  listener_id_(table->Register(
127  boost::bind(&PathResolver::RouteListener, this, _1, _2),
128  "PathResolver")),
129  nexthop_longest_match_(false),
130  nexthop_reg_unreg_trigger_(new TaskTrigger(
131  boost::bind(&PathResolver::ProcessResolverNexthopRegUnregList, this),
132  TaskScheduler::GetInstance()->GetTaskId("bgp::Config"),
133  0)),
134  nexthop_update_trigger_(new TaskTrigger(
135  boost::bind(&PathResolver::ProcessResolverNexthopUpdateList, this),
136  TaskScheduler::GetInstance()->GetTaskId("bgp::ResolverNexthop"),
137  0)),
138  deleter_(new DeleteActor(this)),
139  table_delete_ref_(this, table->deleter()) {
140  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
141  partitions_.push_back(new PathResolverPartition(part_id, this));
142  }
143 }
144 
145 //
146 // Destructor for PathResolver.
147 //
148 // A PathResolver is deleted via LifetimeManager deletion.
149 // Actual destruction of the object happens via BgpTable::DestroyPathResolver.
150 //
151 // Need to do a deep delete of the partitions vector to ensure deletion of all
152 // PathResolverPartitions.
153 //
159  nexthop_update_trigger_->Reset();
160 }
161 
162 //
163 // Get the address family for PathResolver.
164 //
166  return table_->family();
167 }
168 
169 //
170 // Request PathResolver to start resolution for the given BgpPath.
171 // This API needs to be called explicitly when the BgpPath needs resolution.
172 // This is typically when the BgpPath is added, but may also be needed when
173 // the BgpPath changes nexthop.
174 //
176  BgpTable *nh_table) {
177  CHECK_CONCURRENCY("db::DBTable", "bgp::RouteAggregation",
178  "bgp::Config", "bgp::ConfigHelper");
179 
180  if (!nh_table)
181  nh_table = table_;
182  assert(nh_table->family() == Address::INET ||
183  nh_table->family() == Address::INET6);
184  int part_id = route->get_table_partition()->index();
185  partitions_[part_id]->StartPathResolution(route, path, nh_table);
186 }
187 
188 //
189 // Request PathResolver to stop resolution for the given BgpPath.
190 // This API needs to be called explicitly when the BgpPath does not require
191 // resolution. This is typically when the BgpPath is deleted, but may also be
192 // needed when the BgpPath changes nexthop.
193 //
194 void PathResolver::StopPathResolution(int part_id, const BgpPath *path) {
195  CHECK_CONCURRENCY("db::DBTable", "bgp::RouteAggregation",
196  "bgp::Config", "bgp::ConfigHelper");
197 
198  partitions_[part_id]->StopPathResolution(path);
199 }
200 
201 //
202 // Return the BgpConditionListener for the given family.
203 //
205  Address::Family family) {
206  return table_->server()->condition_listener(family);
207 }
208 
209 //
210 // Add a ResolverNexthop to the register/unregister list and start the Task
211 // to process the list.
212 //
213 // Note that the operation (register/unregister) is not explicitly part of
214 // the list - it's inferred based on the state of the ResolverNexthop when
215 // the list is processed.
216 //
218  ResolverNexthop *rnexthop) {
219  tbb::mutex::scoped_lock lock(mutex_);
220  nexthop_reg_unreg_list_.insert(rnexthop);
222 }
223 
224 //
225 // Add a ResolverNexthop to the update list and start the Task to process the
226 // list.
227 //
229  tbb::mutex::scoped_lock lock(mutex_);
230  nexthop_update_list_.insert(rnexthop);
232 }
233 
234 //
235 // Get the PathResolverPartition for the given part_id.
236 //
238  return partitions_[part_id];
239 }
240 
242  return partitions_[part_id];
243 }
244 
245 //
246 // Find ResolverRouteState for the given BgpRoute.
247 //
249  ResolverRouteState *state = static_cast<ResolverRouteState *>(
250  route->GetState(table_, listener_id_));
251  return state;
252 }
253 
254 //
255 // Find or create ResolverRouteState for the given BgpRoute.
256 //
257 // Note that the refcount for ResolverRouteState gets incremented when the
258 // ResolverPath takes an intrusive_ptr to it.
259 //
261  ResolverRouteState *state = static_cast<ResolverRouteState *>(
262  route->GetState(table_, listener_id_));
263  if (state) {
264  return state;
265  } else {
266  return (new ResolverRouteState(this, route));
267  }
268 }
269 
270 //
271 // Find or create the ResolverNexthop with the given IpAddress.
272 // Called when a new ResolverPath is being created.
273 //
274 // A newly created ResolverNexthop is added to the map.
275 //
277  BgpTable *table) {
278  CHECK_CONCURRENCY("db::DBTable", "bgp::RouteAggregation",
279  "bgp::Config", "bgp::ConfigHelper");
280 
281  tbb::mutex::scoped_lock lock(mutex_);
282  ResolverNexthopKey key(address, table);
283  ResolverNexthopMap::iterator loc = nexthop_map_.find(key);
284  if (loc != nexthop_map_.end()) {
285  return loc->second;
286  } else {
287  ResolverNexthop *rnexthop = new ResolverNexthop(this, address, table);
288  nexthop_map_.insert(make_pair(key, rnexthop));
289  return rnexthop;
290  }
291 }
292 
293 //
294 // Remove the ResolverNexthop from the map and the update list.
295 // Called when ResolverPath is being unregistered from BgpConditionListener
296 // as part of register/unregister list processing.
297 //
298 // If the ResolverNexthop is being unregistered, it's moved to the delete
299 // list till the BgpConditionListener invokes the remove complete callback.
300 //
301 // Note that a ResolverNexthop object cannot be resurrected once it has been
302 // removed from the map - it's destined to get destroyed eventually. A new
303 // object for the same IpAddress gets created if a new ResolverPath needs to
304 // use one.
305 //
307  CHECK_CONCURRENCY("bgp::Config");
308 
309  ResolverNexthopKey key(rnexthop->address(), rnexthop->table());
310  ResolverNexthopMap::iterator loc = nexthop_map_.find(key);
311  assert(loc != nexthop_map_.end());
312  nexthop_map_.erase(loc);
313  nexthop_update_list_.erase(rnexthop);
314 }
315 
316 //
317 // Callback for BgpConditionListener::RemoveMatchCondition operation for
318 // a ResolverNexthop.
319 //
320 // It's safe to unregister the ResolverNexthop at this point. However the
321 // operation cannot be done in the context of db::Walker Task. Enqueue the
322 // ResolverNexthop to the register/unregister list.
323 //
325  ConditionMatch *match) {
326  CHECK_CONCURRENCY("db::Walker");
327 
328  ResolverNexthop *rnexthop = dynamic_cast<ResolverNexthop *>(match);
329  assert(rnexthop);
330  assert(rnexthop->registered());
331  assert(rnexthop->deleted());
332  assert(nexthop_delete_list_.find(rnexthop) != nexthop_delete_list_.end());
334 }
335 
336 //
337 // Handle processing of a ResolverNexthop on the register/unregister list.
338 //
339 // Return true if the ResolverNexthop can be deleted immediately.
340 //
342  CHECK_CONCURRENCY("bgp::Config");
343 
344  BgpTable *table = rnexthop->table();
345  Address::Family family = table->family();
346  BgpConditionListener *condition_listener = get_condition_listener(family);
347 
348  if (rnexthop->registered()) {
349  if (rnexthop->deleted()) {
350  // Unregister the ResolverNexthop from BgpConditionListener since
351  // remove operation has been completed. This is the final step in
352  // the lifetime of ResolverNexthop - the ResolverNexthop will get
353  // deleted when unregister is called.
354  nexthop_delete_list_.erase(rnexthop);
355  condition_listener->UnregisterMatchCondition(table, rnexthop);
356  } else if (rnexthop->empty()) {
357  // Remove the ResolverNexthop from BgpConditionListener as there
358  // are no more ResolverPaths using it. Insert it into the delete
359  // list while remove and unregister operations are still pending.
360  // This prevents premature deletion of the PathResolver itself.
361  // Note that BgpConditionListener marks the ResolverNexthop as
362  // deleted as part of the remove operation.
363  RemoveResolverNexthop(rnexthop);
364  nexthop_delete_list_.insert(rnexthop);
365  BgpConditionListener::RequestDoneCb cb = boost::bind(
367  condition_listener->RemoveMatchCondition(table, rnexthop, cb);
368  }
369  } else {
370  if (!rnexthop->empty()) {
371  // Register ResolverNexthop to BgpConditionListener since there's
372  // one or more ResolverPaths using it. Skip if the BgpTable is in
373  // the process of being deleted - the BgpConditionListener does
374  // not, and should not need to, handle this scenario.
375  if (!table->IsDeleted()) {
376  condition_listener->AddMatchCondition(
377  table, rnexthop, BgpConditionListener::RequestDoneCb());
378  rnexthop->set_registered();
379  }
380  } else {
381  // The ResolverNexthop can be deleted right away since there are
382  // no ResolverPaths using it. This can happen in couple of corner
383  // cases:
384  // 1. ResolverPaths are added and deleted rapidly i.e. before the
385  // ResolverNexthop has been registered with BgpConditionListener.
386  // 2. The ResolverNexthop's BgpTable was in the process of being
387  // deleted when we attempted to register the ResolverNexthop. In
388  // that case, we come here after the last ResolverPath using the
389  // ResolverNexthop has been deleted.
390  RemoveResolverNexthop(rnexthop);
391  return true;
392  }
393  }
394 
395  return false;
396 }
397 
398 //
399 // Handle processing of all ResolverNexthops on the register/unregister list.
400 //
402  CHECK_CONCURRENCY("bgp::Config");
403 
404  for (ResolverNexthopList::iterator it = nexthop_reg_unreg_list_.begin();
405  it != nexthop_reg_unreg_list_.end(); ++it) {
406  ResolverNexthop *rnexthop = *it;
407  if (ProcessResolverNexthopRegUnreg(rnexthop))
408  delete rnexthop;
409  }
410  nexthop_reg_unreg_list_.clear();
411 
412  RetryDelete();
413  return true;
414 }
415 
416 //
417 // Handle processing of all ResolverNexthops on the update list.
418 //
420  CHECK_CONCURRENCY("bgp::ResolverNexthop");
421 
422  for (ResolverNexthopList::iterator it = nexthop_update_list_.begin();
423  it != nexthop_update_list_.end(); ++it) {
424  ResolverNexthop *rnexthop = *it;
425  assert(!rnexthop->deleted());
426  rnexthop->TriggerAllResolverPaths();
427  }
428  nexthop_update_list_.clear();
429  return true;
430 }
431 
432 //
433 // Return true if the DeleteActor is marked deleted.
434 //
436  return deleter_->IsDeleted();
437 }
438 
439 //
440 // Cascade delete from BgpTable delete_ref to self.
441 //
443  deleter_->Delete();
444 }
445 
446 //
447 // Return true if it's safe to delete the PathResolver.
448 //
450  if (!nexthop_map_.empty())
451  return false;
452  if (!nexthop_delete_list_.empty())
453  return false;
454  if (!nexthop_reg_unreg_list_.empty())
455  return false;
456  assert(nexthop_update_list_.empty());
457  return true;
458 }
459 
460 //
461 // Attempt to enqueue a delete for the PathResolver.
462 //
464  if (!deleter_->IsDeleted())
465  return;
466  deleter_->RetryDelete();
467 }
468 
469 //
470 // Dummy callback - required in order to get a listener_id for use with
471 // BgpConditionListener.
472 //
474  return true;
475 }
476 
477 //
478 // Get size of the map.
479 // For testing only.
480 //
482  tbb::mutex::scoped_lock lock(mutex_);
483  return nexthop_map_.size();
484 }
485 
486 //
487 // Get size of the delete list.
488 // For testing only.
489 //
491  tbb::mutex::scoped_lock lock(mutex_);
492  return nexthop_delete_list_.size();
493 }
494 
495 //
496 // Disable processing of the register/unregister list.
497 // For testing only.
498 //
500  nexthop_reg_unreg_trigger_->set_disable();
501 }
502 
503 //
504 // Enable processing of the register/unregister list.
505 // For testing only.
506 //
508  nexthop_reg_unreg_trigger_->set_enable();
509 }
510 
511 //
512 // Get size of the update list.
513 // For testing only.
514 //
516  tbb::mutex::scoped_lock lock(mutex_);
517  return nexthop_reg_unreg_list_.size();
518 }
519 
520 //
521 // Disable processing of the update list.
522 // For testing only.
523 //
525  nexthop_update_trigger_->set_disable();
526 }
527 
528 //
529 // Enable processing of the update list.
530 // For testing only.
531 //
533  nexthop_update_trigger_->set_enable();
534 }
535 
536 //
537 // Get size of the update list.
538 // For testing only.
539 //
541  tbb::mutex::scoped_lock lock(mutex_);
542  return nexthop_update_list_.size();
543 }
544 
545 //
546 // Disable processing of the path update list in all partitions.
547 // For testing only.
548 //
550  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
551  partitions_[part_id]->DisableResolverPathUpdateProcessing();
552  }
553 }
554 
555 //
556 // Enable processing of the path update list in all partitions.
557 // For testing only.
558 //
560  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
561  partitions_[part_id]->EnableResolverPathUpdateProcessing();
562  }
563 }
564 
565 //
566 // Pause processing of the path update list in all partitions.
567 // For testing only.
568 //
570  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
571  partitions_[part_id]->PauseResolverPathUpdateProcessing();
572  }
573 }
574 
575 //
576 // Resume processing of the path update list in all partitions.
577 // For testing only.
578 //
580  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
581  partitions_[part_id]->ResumeResolverPathUpdateProcessing();
582  }
583 }
584 
585 //
586 // Get size of the update list.
587 // For testing only.
588 //
590  size_t total = 0;
591  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
592  total += partitions_[part_id]->GetResolverPathUpdateListSize();
593  }
594  return total;
595 }
596 
597 //
598 // Fill introspect information.
599 //
600 void PathResolver::FillShowInfo(ShowPathResolver *spr, bool summary) const {
601  spr->set_name(table_->name());
602 
603  size_t path_count = 0;
604  size_t modified_path_count = 0;
605  vector<ShowPathResolverPath> sprp_list;
606  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
607  const PathResolverPartition *partition = partitions_[part_id];
608  path_count += partition->rpath_map_.size();
609  modified_path_count += partition->rpath_update_list_.size();
610  if (summary)
611  continue;
612  for (PathResolverPartition::PathToResolverPathMap::const_iterator it =
613  partition->rpath_map_.begin(); it != partition->rpath_map_.end();
614  ++it) {
615  const ResolverPath *rpath = it->second;
616  ShowPathResolverPath sprp;
617  sprp.set_prefix(rpath->route()->ToString());
618  sprp.set_nexthop(rpath->rnexthop()->address().to_string());
619  sprp.set_resolved_path_count(rpath->resolved_path_count());
620  sprp_list.push_back(sprp);
621  }
622  }
623  spr->set_path_count(path_count);
624  spr->set_modified_path_count(modified_path_count);
625  spr->set_nexthop_count(nexthop_map_.size());
626  spr->set_modified_nexthop_count(nexthop_reg_unreg_list_.size() +
628 
629  if (summary)
630  return;
631 
632  vector<ShowPathResolverNexthop> sprn_list;
633  for (ResolverNexthopMap::const_iterator it = nexthop_map_.begin();
634  it != nexthop_map_.end(); ++it) {
635  const ResolverNexthop *rnexthop = it->second;
636  const BgpTable *table = rnexthop->table();
637  ShowPathResolverNexthop sprn;
638  sprn.set_address(rnexthop->address().to_string());
639  sprn.set_table(table->name());
640  const BgpRoute *route = rnexthop->GetRoute();
641  if (route) {
642  ShowRouteBrief show_route;
643  route->FillRouteInfo(table, &show_route);
644  sprn.set_nexthop_route(show_route);
645  }
646  sprn_list.push_back(sprn);
647  }
648 
649  spr->set_paths(sprp_list);
650  spr->set_nexthops(sprn_list);
651 }
652 
653 //
654 //
655 // Constructor for PathResolverPartition.
656 // A new PathResolverPartition is created when a PathResolver is created.
657 //
659  PathResolver *resolver)
660  : part_id_(part_id),
661  resolver_(resolver),
662  rpath_update_trigger_(new TaskTrigger(
663  boost::bind(&PathResolverPartition::ProcessResolverPathUpdateList,
664  this),
665  TaskScheduler::GetInstance()->GetTaskId("bgp::ResolverPath"),
666  part_id)) {
667 }
668 
669 //
670 // Destructor for PathResolverPartition.
671 // All PathResolverPartitions for a PathResolver are destroyed when the
672 // PathResolver is destroyed.
673 //
675  assert(rpath_update_list_.empty());
676  rpath_update_trigger_->Reset();
677 }
678 
679 //
680 // Start resolution for the given BgpPath.
681 // Create a ResolverPath object and trigger resolution for it.
682 // A ResolverNexthop is also created if required.
683 //
684 // Note that the ResolverPath gets linked to the ResolverNexthop via the
685 // ResolverPath constructor.
686 //
688  const BgpPath *path, BgpTable *nh_table) {
689  if (!path->IsResolutionFeasible())
690  return;
691  if (table()->IsDeleted() || nh_table->IsDeleted())
692  return;
693 
694  Address::Family family = table()->family();
695  IpAddress address = path->GetAttr()->nexthop();
696  if (table() == nh_table && RoutePrefixIsAddress(family, route, address))
697  return;
698 
699  ResolverNexthop *rnexthop;
700  if (family != Address::EVPN) {
701  rnexthop = resolver_->LocateResolverNexthop(address, nh_table);
702  }
703  else {
704  rnexthop = resolver_->LocateResolverNexthop(address, table());
705  }
706  assert(!FindResolverPath(path));
707  ResolverPath *rpath = CreateResolverPath(path, route, rnexthop);
708  TriggerPathResolution(rpath);
709 }
710 
711 //
712 // Stop resolution for the given BgpPath.
713 // The ResolverPath is removed from the map right away, but the deletion of
714 // any resolved BgpPaths and the ResolverPath itself happens asynchronously.
715 //
717  ResolverPath *rpath = RemoveResolverPath(path);
718  if (!rpath)
719  return;
720  TriggerPathResolution(rpath);
721 }
722 
723 //
724 // Add a ResolverPath to the update list and start Task to process the list.
725 //
727  CHECK_CONCURRENCY("db::DBTable", "bgp::ResolverNexthop",
728  "bgp::Config", "bgp::ConfigHelper", "bgp::RouteAggregation");
729 
730  rpath_update_list_.insert(rpath);
731  rpath_update_trigger_->Set();
732 }
733 
734 //
735 // Add a ResolverPath to the update list and start Task to process the list.
736 // This is used to defer re-evaluation of the ResolverPath when the update
737 // list is being processed.
738 //
740  CHECK_CONCURRENCY("bgp::ResolverPath");
741 
742  rpath_update_list_.insert(rpath);
743  rpath_update_trigger_->Set();
744 }
745 
746 //
747 // Get the BgpTable partition corresponding to this PathResolverPartition.
748 //
750  return table()->GetTablePartition(part_id_);
751 }
752 
753 //
754 // Create a new ResolverPath for the BgpPath.
755 // The ResolverPath is inserted into the map.
756 //
758  BgpRoute *route, ResolverNexthop *rnexthop) {
759  ResolverPath *rpath = new ResolverPath(this, path, route, rnexthop);
760  rpath_map_.insert(make_pair(path, rpath));
761  return rpath;
762 }
763 
764 //
765 // Find the ResolverPath for given BgpPath.
766 //
768  PathToResolverPathMap::iterator loc = rpath_map_.find(path);
769  return (loc != rpath_map_.end() ? loc->second : NULL);
770 }
771 
772 //
773 // Remove the ResolverPath for given BgpPath.
774 // The ResolverPath is removed from the map and it's back pointer to the
775 // BgpPath is cleared.
776 // Actual deletion of the ResolverPath happens asynchronously.
777 //
779  PathToResolverPathMap::iterator loc = rpath_map_.find(path);
780  if (loc == rpath_map_.end()) {
781  return NULL;
782  } else {
783  ResolverPath *rpath = loc->second;
784  rpath_map_.erase(loc);
785  rpath->clear_path();
786  return rpath;
787  }
788 }
789 
790 //
791 // Handle processing of all ResolverPaths on the update list.
792 //
794  CHECK_CONCURRENCY("bgp::ResolverPath");
795 
796  ResolverPathList update_list;
797  rpath_update_list_.swap(update_list);
798  for (ResolverPathList::iterator it = update_list.begin();
799  it != update_list.end(); ++it) {
800  ResolverPath *rpath = *it;
801  if (rpath->UpdateResolvedPaths())
802  delete rpath;
803  }
804 
805  return rpath_update_list_.empty();
806 }
807 
808 //
809 // Disable processing of the update list.
810 // For testing only.
811 //
813  rpath_update_trigger_->set_disable();
814 }
815 
816 //
817 // Enable processing of the update list.
818 // For testing only.
819 //
821  rpath_update_trigger_->set_enable();
822 }
823 
824 //
825 // Pause processing of the update list.
826 // For testing only.
827 //
829  rpath_update_trigger_->set_deferred();
830 }
831 
832 //
833 // Resume processing of the update list.
834 // For testing only.
835 //
837  rpath_update_trigger_->clear_deferred();
838 }
839 
840 //
841 // Get size of the update list.
842 // For testing only.
843 //
845  return rpath_update_list_.size();
846 }
847 
848 //
849 // Constructor for ResolverRouteState.
850 // Gets called when the first ResolverPath for a BgpRoute is created.
851 //
852 // Set State on the BgpRoute to ensure that it doesn't go away.
853 //
855  BgpRoute *route)
856  : resolver_(resolver),
857  route_(route),
858  refcount_(0) {
860 }
861 
862 //
863 // Destructor for ResolverRouteState.
864 // Gets called via when the refcount goes to 0. This happens when the last
865 // ResolverPath for a BgpRoute is deleted.
866 //
867 // Remove State on the BgpRoute so that deletion can proceed.
868 //
871 }
872 
873 //
874 // Constructor for ResolverPath.
875 // Add the ResolverPath as a dependent of the ResolverNexthop.
876 //
877 // Note that it's the caller's responsibility to add the ResolverPath to the
878 // map in the PathResolverPartition.
879 //
881  const BgpPath *path, BgpRoute *route, ResolverNexthop *rnexthop)
882  : partition_(partition),
883  path_(path),
884  route_(route),
885  rnexthop_(rnexthop),
886  state_(partition_->resolver()->LocateResolverRouteState(route)) {
887  rnexthop->AddResolverPath(partition->part_id(), this);
888 }
889 
890 //
891 // Destructor for ResolverPath.
892 // Remove the ResolverPath as a dependent of the ResolverNexthop. This may
893 // trigger unregistration and eventual deletion of the ResolverNexthop if
894 // there are no more ResolverPaths using it.
895 //
896 // Note that the ResolverPath would have been removed from the map in the
897 // PathResolverPartition much earlier i.e. when resolution is stopped.
898 //
901 }
902 
903 //
904 // Add the BgpPath specified by the iterator to the resolved path list.
905 // Also inserts the BgpPath to the BgpRoute.
906 //
907 void ResolverPath::AddResolvedPath(ResolvedPathList::const_iterator it) {
908  BgpPath *path = *it;
909  const IPeer *peer = path->GetPeer();
910  resolved_path_list_.insert(path);
911  route_->InsertPath(path);
912  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
913  "Added resolved path " << route_->ToString() <<
914  " peer " << (peer ? peer->ToString() : "None") <<
915  " path_id " << BgpPath::PathIdString(path->GetPathId()) <<
916  " nexthop " << path->GetAttr()->nexthop().to_string() <<
917  " label " << path->GetLabel() <<
918  " in table " << partition_->table()->name());
919 }
920 
921 //
922 // Delete the BgpPath specified by the iterator from the resolved path list.
923 // Also deletes the BgpPath from the BgpRoute.
924 //
925 void ResolverPath::DeleteResolvedPath(ResolvedPathList::const_iterator it) {
926  BgpPath *path = *it;
927  const IPeer *peer = path->GetPeer();
928  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
929  "Deleted resolved path " << route_->ToString() <<
930  " peer " << (peer ? peer->ToString() : "None") <<
931  " path_id " << BgpPath::PathIdString(path->GetPathId()) <<
932  " nexthop " << path->GetAttr()->nexthop().to_string() <<
933  " label " << path->GetLabel() <<
934  " in table " << partition_->table()->name());
935  route_->DeletePath(path);
936  resolved_path_list_.erase(it);
937 }
938 
939 //
940 // Find or create the matching resolved BgpPath.
941 //
942 BgpPath *ResolverPath::LocateResolvedPath(const IPeer *peer, uint32_t path_id,
943  const BgpAttr *attr, uint32_t label, bool is_replicated) {
944  for (ResolvedPathList::iterator it = resolved_path_list_.begin();
945  it != resolved_path_list_.end(); ++it) {
946  BgpPath *path = *it;
947  if (path->GetPeer() == peer &&
948  path->GetPathId() == path_id &&
949  path->GetAttr() == attr &&
950  path->GetLabel() == label) {
951  return path;
952  }
953  }
954 
956  uint32_t flags =
957  (path_->GetFlags() & ~BgpPath::ResolveNexthop) | BgpPath::ResolvedPath;
958  if (is_replicated) {
959  return (new BgpSecondaryPath(peer, path_id, src, attr, flags, label));
960  } else {
961  return (new BgpPath(peer, path_id, src, attr, flags, label));
962  }
963 }
964 
965 //
966 // Return an extended community that's built by combining the values in the
967 // original path's attributes with values from the nexthop path's attributes.
968 //
969 // Pick up the security groups, tunnel encapsulation load balance, source-as
970 // and vrf import target values from the nexthop path's attributes.
971 //
973  const BgpAttr *attr, const BgpAttr *nh_attr) {
974  ExtCommunityPtr ext_community = attr->ext_community();
975  const ExtCommunity *nh_ext_community = nh_attr->ext_community();
976  if (!nh_ext_community)
977  return ext_community;
978 
982  ExtCommunity::ExtCommunityValue const *source_as = NULL;
983  ExtCommunity::ExtCommunityValue const *lb = NULL;
984  ExtCommunity::ExtCommunityValue const *rt_mac = nullptr;
985  BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &value,
986  nh_ext_community->communities()) {
987  if (ExtCommunity::is_security_group(value) ||
989  sgid_list.push_back(value);
990  } else if (ExtCommunity::is_tunnel_encap(value)) {
991  encap_list.push_back(value);
992  } else if (ExtCommunity::is_vrf_route_import(value)) {
993  VrfRouteImport vit(value);
994  rtarget.push_back(RouteTarget(vit.GetIPv4Address(),
995  vit.GetNumber()).GetExtCommunity());
996  } else if (ExtCommunity::is_source_as(value)) {
997  source_as = &value;
998  } else if (ExtCommunity::is_load_balance(value) && !lb) {
999  lb = &value;
1000  } else if (ExtCommunity::is_router_mac(value) && !rt_mac) {
1001  rt_mac = &value;
1002  }
1003  }
1004 
1005  // Replace rtarget, sgid list, encap list and load balance.
1006  ext_community = extcomm_db->ReplaceRTargetAndLocate(ext_community.get(),
1007  rtarget);
1008  ext_community = extcomm_db->ReplaceSGIDListAndLocate(
1009  ext_community.get(), sgid_list);
1010  ext_community = extcomm_db->ReplaceTunnelEncapsulationAndLocate(
1011  ext_community.get(), encap_list);
1012  if (source_as) {
1013  ext_community = extcomm_db->ReplaceSourceASAndLocate(
1014  ext_community.get(), *source_as);
1015  }
1016  if (lb) {
1017  ext_community = extcomm_db->ReplaceLoadBalanceAndLocate(
1018  ext_community.get(), *lb);
1019  }
1020  if (rt_mac) {
1021  ext_community = extcomm_db->AppendAndLocate(
1022  ext_community.get(), *rt_mac);
1023  }
1024  return ext_community;
1025 }
1026 
1027 //
1028 // Update resolved BgpPaths for the ResolverPath based on the BgpRoute for
1029 // the ResolverNexthop.
1030 //
1031 // Return true if the ResolverPath can be deleted.
1032 //
1033 // Note that the ResolverPath can only be deleted if resolution for it has
1034 // been stopped. It must not be deleted simply because there is no viable
1035 // BgpRoute for the ResolverNexthop.
1036 //
1038  CHECK_CONCURRENCY("bgp::ResolverPath");
1039 
1040  // Defer updates if we can't get a write lock on the ResolverRouteState
1041  // for the BgpRoute we're trying to modify.
1042  tbb::spin_rw_mutex::scoped_lock rt_write_lock;
1043  if (!rt_write_lock.try_acquire(state_->rw_mutex(), true)) {
1045  return false;
1046  }
1047 
1048  // Defer updates if we can't get a read lock on the ResolverRouteState
1049  // for the BgpRoute to the ResolverNexthop. This ResolverRouteState will
1050  // exist only if the BgpRoute in question itself has resolved paths.
1051  tbb::spin_rw_mutex::scoped_lock nh_read_lock;
1053  if (state_ != nh_state &&
1054  nh_state && !nh_read_lock.try_acquire(nh_state->rw_mutex(), false)) {
1056  return false;
1057  }
1058 
1059  BgpServer *server = partition_->table()->server();
1060  BgpAttrDB *attr_db = server->attr_db();
1061  ExtCommunityDB *extcomm_db = server->extcomm_db();
1062 
1063  // Go through paths of the nexthop route and build the list of future
1064  // resolved paths. If the nexthop RI is the master instance, indicating
1065  // that we are checking for presence of nexthop in the underlay table, the
1066  // existing path is added to future resolved path as is but with updated
1067  // path flag indicating that it is resolved.
1068  ResolvedPathList future_resolved_path_list;
1069  const BgpRoute *nh_route = rnexthop_->GetRoute();
1070  const IPeer *peer = path_ ? path_->GetPeer() : NULL;
1071  // Process paths of nexthop route if nexthop RI is not the master RI.
1072  const RoutingInstance *nh_ri = rnexthop_->table()->routing_instance();
1073  bool nh_ri_def = false;
1074  if (nh_ri->IsMasterRoutingInstance()) {
1075  nh_ri_def = true;
1076  }
1077  bool process_paths = false;
1078  if (path_ && nh_route && !nh_ri_def) {
1079  process_paths = true;
1080  }
1081  Route::PathList::const_iterator it;
1082  if (process_paths)
1083  it = nh_route->GetPathList().begin();
1084  for (; process_paths && it != nh_route->GetPathList().end(); ++it) {
1085  const BgpPath *nh_path = static_cast<const BgpPath *>(it.operator->());
1086 
1087  // Start with attributes of the original path.
1088  BgpAttrPtr attr(path_->GetAttr());
1089 
1090  // Infeasible nexthop paths are not considered.
1091  if (!nh_path->IsFeasible())
1092  break;
1093 
1094  // Take snapshot of all ECMP nexthop paths.
1095  if (nh_route->BestPath()->PathCompare(*nh_path, true))
1096  break;
1097 
1098  // Skip paths with duplicate forwarding information. This ensures
1099  // that we generate only one path with any given next hop when there
1100  // are multiple nexthop paths from the original source received via
1101  // different peers e.g. directly via XMPP and via BGP.
1102  if (nh_route->DuplicateForwardingPath(nh_path))
1103  continue;
1104 
1105  // Skip if there's no source rd.
1106  RouteDistinguisher source_rd = nh_path->GetSourceRouteDistinguisher();
1107  if (source_rd.IsZero())
1108  continue;
1109 
1110  // Use source rd from the nexthop path.
1111  attr = attr_db->ReplaceSourceRdAndLocate(attr.get(), source_rd);
1112 
1113  // Use nexthop address from the nexthop path.
1114  attr = attr_db->ReplaceNexthopAndLocate(attr.get(),
1115  nh_path->GetAttr()->nexthop());
1116 
1117  // obtain extcommunities from original attrs and allow
1118  // route target type values.
1119  ExtCommunityPtr ext_community = attr->ext_community();
1120  ExtCommunity::ExtCommunityList export_list;
1121  if (ext_community)
1122  {
1123  BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &v,
1124  ext_community->communities()) {
1126  continue;
1127  export_list.push_back(RouteTarget(v).GetExtCommunity());
1128  }
1129  }
1130 
1131  // Update extended community based on the nexthop path and use it.
1132  ext_community =
1133  UpdateExtendedCommunity(extcomm_db, attr.get(), nh_path->GetAttr());
1134  if (!export_list.empty()) {
1135  ext_community = extcomm_db->AppendAndLocate(ext_community.get(), export_list);
1136  }
1137  attr = attr_db->ReplaceExtCommunityAndLocate(attr.get(), ext_community);
1138 
1139  // Locate the resolved path.
1140  uint32_t path_id = nh_path->GetAttr()->nexthop().to_v4().to_ulong();
1141  BgpPath *resolved_path =
1142  LocateResolvedPath(peer, path_id, attr.get(), nh_path->GetLabel());
1143  future_resolved_path_list.insert(resolved_path);
1144  }
1145 
1146  // If nexthop RI is the default routing-instance, nothing to update except
1147  // changing path_flags. Locate the resolved path.
1148  if (path_ && nh_route && nh_ri_def) {
1149  BgpPath *updated_path = LocateResolvedPath(peer, path_->GetPathId(),
1151  if (path_->IsReplicated()) {
1152  const BgpSecondaryPath *sec_path =
1153  static_cast<const BgpSecondaryPath *> (path_);
1154  BgpSecondaryPath *sec_upd_path =
1155  dynamic_cast<BgpSecondaryPath *> (updated_path);
1156  sec_upd_path->SetReplicateInfo(sec_path->src_table(),
1157  sec_path->src_rt());
1158  }
1159  future_resolved_path_list.insert(updated_path);
1160  }
1161 
1162  // Reconcile the current and future resolved paths and notify/delete the
1163  // route as appropriate.
1164  bool modified = set_synchronize(&resolved_path_list_,
1165  &future_resolved_path_list,
1166  boost::bind(&ResolverPath::AddResolvedPath, this, _1),
1167  boost::bind(&ResolverPath::DeleteResolvedPath, this, _1));
1168  if (route_->HasPaths()) {
1169  if (modified) {
1171  }
1172  } else {
1174  }
1175 
1176  return (!path_);
1177 }
1178 
1179 //
1180 // Constructor for ResolverNexthop.
1181 // Initialize the vector of paths_lists to the number of DB partitions.
1182 //
1184  BgpTable *table)
1185  : resolver_(resolver),
1186  address_(address),
1187  table_(table),
1188  registered_(false),
1189  rpath_lists_(DB::PartitionCount()),
1190  table_delete_ref_(this, table->deleter()) {
1191 }
1192 
1193 //
1194 // Destructor for ResolverNexthop.
1195 // A deep delete of the path_lists vector is not required.
1196 //
1198  assert(routes_.empty());
1199 }
1200 
1201 //
1202 // Implement virtual method for ConditionMatch base class.
1203 //
1205  return (string("ResolverNexthop ") + address_.to_string());
1206 }
1207 
1208 //
1209 // Implement virtual method for ConditionMatch base class.
1210 //
1212  BgpRoute *route, bool deleted) {
1213  CHECK_CONCURRENCY("db::DBTable");
1214 
1215  // Ignore if the route doesn't match the address.
1216  Address::Family family = table->family();
1217  assert(family == Address::INET || family == Address::INET6 || family == Address::EVPN);
1218 
1219  // If longest match based lookup is not enabled, do an exact match between
1220  // the route and the address.
1221  if (!resolver_->nexthop_longest_match()) {
1222  if (!RoutePrefixIsAddress(family, route, address_))
1223  return false;
1224  } else {
1225  if (!resolver_->RoutePrefixMatch(route, address_))
1226  return false;
1227  }
1228 
1229  // Do not resolve over self.
1230  if (route->table() == table && route->IsUsable() &&
1231  route->BestPath()->GetAttr()->nexthop() == address_) {
1232  return false;
1233  }
1234 
1235  // Set or remove MatchState as appropriate.
1236  BgpConditionListener *condition_listener =
1238  bool state_added = condition_listener->CheckMatchState(table, route, this);
1239 
1240  // In order to also cover the case when route does not change but its path
1241  // attrs, trigger updates by default, unless non longest matching route is
1242  // inserted or removed.
1243  bool longest_match_updated = true;
1244  if (deleted) {
1245  if (state_added) {
1246  longest_match_updated = RemoveRoute(route);
1247  condition_listener->RemoveMatchState(table, route, this);
1248  } else {
1249  return false;
1250  }
1251  } else {
1252  if (!state_added) {
1253  longest_match_updated = InsertRoute(route);
1254  condition_listener->SetMatchState(table, route, this);
1255  }
1256  }
1257 
1258  // Nothing more to do if the ConditionMatch has been removed.
1260  return false;
1261 
1262  // Trigger re-evaluation of all dependent ResolverPaths if the longest
1263  // matching route was updated.
1264  if (longest_match_updated)
1266  return true;
1267 }
1268 
1269 //
1270 // Add the given ResolverPath to the list of dependents in the partition.
1271 // Add to register/unregister list when the first dependent ResolverPath for
1272 // the partition is added.
1273 //
1274 // This may cause the ResolverNexthop to get added to register/unregister
1275 // list multiple times - once for the first ResolverPath in each partition.
1276 // This case is handled by PathResolver::ProcessResolverNexthopRegUnreg.
1277 //
1278 // Do not attempt to access other partitions due to concurrency issues.
1279 //
1281  CHECK_CONCURRENCY("db::DBTable", "bgp::RouteAggregation",
1282  "bgp::Config", "bgp::ConfigHelper");
1283 
1284  if (rpath_lists_[part_id].empty())
1286  rpath_lists_[part_id].insert(rpath);
1287 }
1288 
1289 //
1290 // Remove given ResolverPath from the list of dependents in the partition.
1291 // Add to register/unregister list when the last dependent ResolverPath for
1292 // the partition is removed.
1293 //
1294 // This may cause the ResolverNexthop to get added to register/unregister
1295 // list multiple times - once for the last ResolverPath in each partition.
1296 // This case is handled by PathResolver::ProcessResolverNexthopRegUnreg.
1297 //
1298 // Do not attempt to access other partitions due to concurrency issues.
1299 //
1301  CHECK_CONCURRENCY("bgp::ResolverPath");
1302 
1303  rpath_lists_[part_id].erase(rpath);
1304  if (rpath_lists_[part_id].empty())
1306 }
1307 
1309  if (!GetRoute())
1310  return NULL;
1311  PathResolver *nh_resolver = table_->path_resolver();
1312  if (!nh_resolver)
1313  return NULL;
1314  return nh_resolver->FindResolverRouteState(GetRoute());
1315 }
1316 
1317 //
1318 // Trigger update of resolved BgpPaths for all ResolverPaths that depend on
1319 // the ResolverNexthop. Actual update of the resolved BgpPaths happens when
1320 // the PathResolverPartitions process their update lists.
1321 //
1323  CHECK_CONCURRENCY("bgp::ResolverNexthop");
1324 
1325  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
1326  for (ResolverPathList::iterator it = rpath_lists_[part_id].begin();
1327  it != rpath_lists_[part_id].end(); ++it) {
1328  ResolverPath *rpath = *it;
1329  resolver_->GetPartition(part_id)->TriggerPathResolution(rpath);
1330  }
1331  }
1332 }
1333 
1334 //
1335 // Return true if there are no dependent ResolverPaths in all partitions.
1336 //
1338  CHECK_CONCURRENCY("bgp::Config");
1339 
1340  for (int part_id = 0; part_id < DB::PartitionCount(); ++part_id) {
1341  if (!rpath_lists_[part_id].empty())
1342  return false;
1343  }
1344  return true;
1345 }
1346 
1348  const BgpRoute *lhs, const BgpRoute *rhs) const {
1349  const InetRoute *lhs4 = dynamic_cast<const InetRoute *>(lhs);
1350  const InetRoute *rhs4 = dynamic_cast<const InetRoute *>(rhs);
1351  if (lhs4) {
1352  return lhs4->GetPrefix().prefixlen() > rhs4->GetPrefix().prefixlen();
1353  }
1354 
1355  const Inet6Route *lhs6 = dynamic_cast<const Inet6Route *>(lhs);
1356  const Inet6Route *rhs6 = dynamic_cast<const Inet6Route *>(rhs);
1357  if (lhs6) {
1358  return lhs6->GetPrefix().prefixlen() > rhs6->GetPrefix().prefixlen();
1359  }
1360 
1361  const EvpnRoute *lhs_e = dynamic_cast<const EvpnRoute *>(lhs);
1362  const EvpnRoute *rhs_e = dynamic_cast<const EvpnRoute *>(rhs);
1363  if (lhs_e != nullptr) {
1364  return lhs_e->GetPrefix().ip_address_length() >
1365  rhs_e->GetPrefix().ip_address_length();
1366  }
1367  else {
1368  return false;
1369  }
1370 }
1371 
1372 // Insert route into the set of routes sorted based on the prefix length in
1373 // descending order. Return true if the route inserted is the new longest match.
1375  tbb::mutex::scoped_lock lock(routes_mutex_);
1376  routes_.insert(route);
1377  bool longest_match = (*(routes_.begin()) == route);
1378  return longest_match;
1379 }
1380 
1381 // Remove route from the set of routes sorted based on the prefix length in
1382 // descending order. Return true if the route removed was the old longest match.
1384  tbb::mutex::scoped_lock lock(routes_mutex_);
1385  bool longest_match = (*(routes_.begin()) == route);
1386  routes_.erase(route);
1387  return longest_match;
1388 }
1389 
1391  tbb::mutex::scoped_lock lock(routes_mutex_);
1392  return !routes_.empty() ? *(routes_.begin()) : NULL;
1393 }
1394 
1396  tbb::mutex::scoped_lock lock(routes_mutex_);
1397  return !routes_.empty() ? *(routes_.begin()) : NULL;
1398 }
void FillRouteInfo(const BgpTable *table, ShowRouteBrief *show_route) const
Definition: bgp_route.cc:432
virtual bool MayDelete() const
ResolverNexthop * LocateResolverNexthop(IpAddress address, BgpTable *table)
bool RouteListener(DBTablePartBase *root, DBEntryBase *entry)
void PauseResolverPathUpdateProcessing()
ExtCommunityPtr ReplaceSGIDListAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &sgid_list)
Definition: community.cc:757
ExtCommunityPtr AppendAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &list)
Definition: community.cc:696
bool MayDelete() const
boost::scoped_ptr< DeleteActor > deleter_
PathResolver * resolver_
boost::array< uint8_t, 8 > ExtCommunityValue
Definition: community.h:152
const IpAddress & nexthop() const
Definition: bgp_attr.h:886
void STLDeleteValues(Container *container)
Definition: util.h:101
const ResolverNexthop * rnexthop() const
Ip4Address addr() const
Definition: inet_route.h:24
BgpTable * table()
static const uint8_t kMaxV6PrefixLen
Definition: address.h:22
const BgpPath * BestPath() const
Definition: bgp_route.cc:46
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
void FillShowInfo(ShowPathResolver *spr, bool summary) const
void ResumeResolverPathUpdateProcessing()
ResolverNexthopList nexthop_update_list_
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
void clear_path()
ResolverPath * CreateResolverPath(const BgpPath *path, BgpRoute *route, ResolverNexthop *rnexthop)
bool set_synchronize(const SetType *set1, const SetType *set2, AddFunctor add_fn, DelFunctor del_fn)
Definition: set_util.h:21
boost::function< void(BgpTable *, ConditionMatch *)> RequestDoneCb
void DisableResolverPathUpdateProcessing()
static bool is_security_group(const ExtCommunityValue &val)
Definition: community.h:304
virtual bool Match(BgpServer *server, BgpTable *table, BgpRoute *route, bool deleted)
bool ProcessResolverNexthopRegUnregList()
static std::string PathIdString(uint32_t path_id)
Definition: bgp_path.cc:18
void RemoveMatchState(BgpTable *table, BgpRoute *route, ConditionMatch *obj)
tbb::mutex mutex_
tbb::mutex routes_mutex_
ResolvedPathList resolved_path_list_
void TriggerPathResolution(ResolverPath *rpath)
RoutingInstance * routing_instance()
Definition: bgp_table.h:148
Family
Definition: address.h:24
ResolverRouteSet routes_
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
boost::asio::ip::address IpAddress
Definition: address.h:13
PathResolver(BgpTable *table)
size_t GetResolverPathUpdateListSize() const
const IpAddress & addr() const
DBTablePartBase * table_partition()
virtual ~ResolverNexthop()
PathResolverPartition(int part_id, PathResolver *resolver)
BgpAttrPtr ReplaceNexthopAndLocate(const BgpAttr *attr, const IpAddress &addr)
Definition: bgp_attr.cc:1413
ResolverNexthop * rnexthop_
void StartPathResolution(BgpRoute *route, const BgpPath *path, BgpTable *nh_table=NULL)
static bool is_source_as(const ExtCommunityValue &val)
Definition: community.h:335
const uint32_t GetPathId() const
Definition: bgp_path.h:78
const BgpRoute * GetRoute() const
bool IsResolutionFeasible() const
Definition: bgp_path.h:94
static const uint8_t kMaxV4PrefixLen
Definition: address.h:20
ResolverNexthopList nexthop_reg_unreg_list_
friend class PathResolverPartition
BgpConditionListener * condition_listener(Address::Family family)
Definition: bgp_server.h:114
BgpTable * table() const
void Delete(DBEntryBase *)
virtual Address::Family family() const =0
uint32_t GetFlags() const
Definition: bgp_path.h:100
Definition: ipeer.h:186
PathToResolverPathMap rpath_map_
void DeferPathResolution(ResolverPath *rpath)
int prefixlen() const
Definition: inet_route.h:27
void Unregister(ListenerId listener)
Definition: db_table.cc:186
void DisableResolverNexthopUpdateProcessing()
bool ProcessResolverNexthopUpdateList()
PathResolver * resolver_
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
bool IsUsable() const
Definition: bgp_route.cc:324
#define BGP_LOG_STR(obj, level, flags, arg)
Definition: bgp_log.h:89
void RetryDelete()
ResolverPath * RemoveResolverPath(const BgpPath *path)
static bool is_security_group4(const ExtCommunityValue &val)
Definition: community.h:313
ResolverNexthop(PathResolver *resolver, IpAddress address, BgpTable *table)
uint8_t prefixlen() const
bool IsDeleted() const
Definition: bgp_table.h:143
Definition: db.h:24
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
void SetReplicateInfo(const BgpTable *table, const BgpRoute *rt)
Definition: bgp_path.h:172
bool empty() const
BgpTable * table() const
PathSource
Definition: bgp_path.h:37
void EnableResolverNexthopUpdateProcessing()
size_t resolved_path_count() const
void StopPathResolution(const BgpPath *path)
uint16_t GetNumber() const
void RegisterUnregisterResolverNexthop(ResolverNexthop *rnexthop)
void RemoveMatchCondition(BgpTable *table, ConditionMatch *obj, RequestDoneCb deleteDonecb)
bool IsFeasible() const
Definition: bgp_path.h:92
size_t GetResolverNexthopDeleteListSize() const
ResolverRouteState * LocateResolverRouteState(BgpRoute *route)
PathSource GetSource() const
Definition: bgp_path.h:103
size_t GetResolverNexthopUpdateListSize() const
Inet6Prefix inet6_prefix() const
bool ProcessResolverPathUpdateList()
void AddMatchCondition(BgpTable *table, ConditionMatch *obj, RequestDoneCb addDoneCb)
const ExtCommunityList & communities() const
Definition: community.h:180
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:189
Ip6Address addr() const
Definition: inet6_route.h:26
static bool is_router_mac(const ExtCommunityValue &val)
Definition: community.h:257
DBTableBase::ListenerId listener_id_
BgpRoute * route_
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
friend class ResolverNexthop
Ip4Prefix inet_prefix() const
Address::Family family() const
BgpPath * LocateResolvedPath(const IPeer *peer, uint32_t path_id, const BgpAttr *attr, uint32_t label, bool is_replicated=false)
virtual const std::string & ToString() const =0
#define CHECK_CONCURRENCY(...)
void SetMatchState(BgpTable *table, BgpRoute *route, ConditionMatch *obj, ConditionMatchState *state=NULL)
void UpdateResolverNexthop(ResolverNexthop *rnexthop)
void DestroyPathResolver()
Definition: bgp_table.cc:1087
virtual std::string ToString() const =0
size_t GetResolverPathUpdateListSize() const
bool CheckMatchState(BgpTable *table, BgpRoute *route, ConditionMatch *obj)
PathResolver * resolver_
BgpRoute * route() const
DBTableBase::ListenerId listener_id() const
void RemoveResolverNexthop(ResolverNexthop *rnexthop)
IPeer * GetPeer()
Definition: bgp_path.h:76
BgpAttrPtr ReplaceSourceRdAndLocate(const BgpAttr *attr, const RouteDistinguisher &source_rd)
Definition: bgp_attr.cc:1362
boost::scoped_ptr< TaskTrigger > nexthop_reg_unreg_trigger_
void EnableResolverPathUpdateProcessing()
const std::string & name() const
Definition: db_table.h:110
uint8_t ip_address_length() const
std::pair< IpAddress, BgpTable * > ResolverNexthopKey
void DisableResolverNexthopRegUnregProcessing()
ResolverRouteStatePtr state_
void RemoveResolverPath(int part_id, ResolverPath *rpath)
uint32_t GetLabel() const
Definition: bgp_path.h:89
int PathCompare(const BgpPath &rhs, bool allow_ecmp) const
Definition: bgp_path.cc:58
const Ip4Prefix & GetPrefix() const
Definition: inet_route.h:70
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
void UnregisterResolverNexthopDone(BgpTable *table, ConditionMatch *match)
ExtCommunityPtr ReplaceSourceASAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityValue &sas)
Definition: community.cc:828
bool InsertRoute(BgpRoute *route)
void TriggerAllResolverPaths() const
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
ResolverRouteState * GetResolverRouteState()
std::set< ResolverPath * > ResolverPathList
bool DuplicateForwardingPath(const BgpPath *in_path) const
Definition: bgp_route.cc:352
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
BgpServer * server()
Definition: bgp_table.cc:88
BgpTable * table_
bool ProcessResolverNexthopRegUnreg(ResolverNexthop *rnexthop)
const EvpnPrefix & GetPrefix() const
virtual std::string ToString() const
void DisableResolverPathUpdateProcessing()
bool IsMasterRoutingInstance() const
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
void DeleteResolvedPath(ResolvedPathList::const_iterator it)
ResolverPath(PathResolverPartition *partition, const BgpPath *path, BgpRoute *route, ResolverNexthop *rnexthop)
ResolverNexthopMap nexthop_map_
const BgpRoute * src_rt() const
Definition: bgp_path.h:186
void StartPathResolution(BgpRoute *route, const BgpPath *path, BgpTable *nh_table)
#define BGP_LOG_FLAG_TRACE
Definition: bgp_log.h:43
BgpAttrDB * attr_db()
Definition: bgp_server.h:183
bool operator()(const BgpRoute *lhs, const BgpRoute *rhs) const
BgpTable * table_
boost::scoped_ptr< TaskTrigger > rpath_update_trigger_
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
ExtCommunityPtr ReplaceTunnelEncapsulationAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &tunnel_encaps)
Definition: community.cc:899
void ResumeResolverPathUpdateProcessing()
std::vector< PathResolverPartition * > partitions_
BgpTable * table()
Definition: bgp_route.cc:424
void StopPathResolution(int part_id, const BgpPath *path)
bool HasPaths() const
Definition: bgp_route.h:28
static bool is_route_target(const ExtCommunityValue &val)
Definition: community.h:265
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
bool registered() const
static bool is_tunnel_encap(const ExtCommunityValue &val)
Definition: community.h:366
bool IsMoreSpecific(const Ip4Prefix &rhs) const
Definition: inet_route.cc:96
IpAddress address() const
static const int kInvalidId
Definition: db_table.h:64
const BgpPath * path_
int prefixlen() const
Definition: inet6_route.h:33
void AddResolverPath(int part_id, ResolverPath *rpath)
ExtCommunityPtr ReplaceLoadBalanceAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityValue &lb)
Definition: community.cc:914
void EnableResolverNexthopRegUnregProcessing()
void DeletePath(BgpPath *path)
Definition: bgp_route.cc:126
static bool RoutePrefixMatch(const BgpRoute *route, const IpAddress &address)
size_t GetResolverNexthopRegUnregListSize() const
void PauseResolverPathUpdateProcessing()
static int PartitionCount()
Definition: db.cc:32
ResolverPathList rpath_update_list_
void UnregisterMatchCondition(BgpTable *table, ConditionMatch *obj)
IpAddress address_
const Inet6Prefix & GetPrefix() const
Definition: inet6_route.h:80
DBTablePartBase * get_table_partition() const
Definition: db_entry.cc:115
const BgpTable * src_table() const
Definition: bgp_path.h:182
ResolverNexthopList nexthop_delete_list_
void Notify(DBEntryBase *entry)
std::vector< ResolverPathList > rpath_lists_
bool IsZero() const
Definition: rd.h:43
static bool is_vrf_route_import(const ExtCommunityValue &val)
Definition: community.h:357
DeleteActor(PathResolver *resolver)
PathResolverPartition * GetPartition(int part_id)
boost::scoped_ptr< TaskTrigger > nexthop_update_trigger_
tbb::spin_rw_mutex & rw_mutex()
ResolverRouteState(PathResolver *resolver, BgpRoute *route)
PathResolverPartition * partition_
RouteDistinguisher GetSourceRouteDistinguisher() const
Definition: bgp_path.cc:181
bool IsDeleted() const
void ManagedDelete()
BgpConditionListener * get_condition_listener(Address::Family family)
virtual bool IsReplicated() const
Definition: bgp_path.h:91
bool nexthop_longest_match() const
ResolverRouteState * FindResolverRouteState(BgpRoute *route)
static bool RoutePrefixIsAddress(Address::Family family, const BgpRoute *route, const IpAddress &address)
ExtCommunityPtr ReplaceRTargetAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &export_list)
Definition: community.cc:743
std::set< BgpPath * > ResolvedPathList
void AddResolvedPath(ResolvedPathList::const_iterator it)
void EnableResolverPathUpdateProcessing()
ResolverPath * FindResolverPath(const BgpPath *path)
bool IsMoreSpecific(const Inet6Prefix &rhs) const
Definition: inet6_route.cc:69
Ip4Address GetIPv4Address() const
Address::Family family() const
static ExtCommunityPtr UpdateExtendedCommunity(ExtCommunityDB *extcomm_db, const BgpAttr *attr, const BgpAttr *nh_attr)
PathResolver * path_resolver()
Definition: bgp_table.h:153
bool RemoveRoute(BgpRoute *route)
int index() const
const PathList & GetPathList() const
Definition: route.h:46
size_t GetResolverNexthopMapSize() const
static bool is_load_balance(const ExtCommunityValue &val)
Definition: community.h:372
bool UpdateResolvedPaths()
virtual ~ResolverRouteState()