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