OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
static_route.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/assign/list_of.hpp>
8 #include <boost/foreach.hpp>
9 
10 #include <algorithm>
11 #include <string>
12 #include <vector>
13 
14 #include "base/map_util.h"
15 #include "base/task_annotations.h"
16 #include "base/task_trigger.h"
17 #include "bgp/bgp_config.h"
18 #include "bgp/bgp_log.h"
19 #include "bgp/bgp_server.h"
25 #include "bgp/routing-instance/static_route_types.h"
27 #include "net/community_type.h"
28 
29 using boost::assign::list_of;
30 using boost::system::error_code;
31 using std::make_pair;
32 using std::set;
33 using std::string;
34 using std::vector;
35 
37 public:
39  }
41  return info_;
42  }
43 
44 private:
47 };
48 
49 template <typename T>
50 class StaticRoute : public ConditionMatch {
51 public:
52  typedef typename T::RouteT RouteT;
53  typedef typename T::VpnRouteT VpnRouteT;
54  typedef typename T::PrefixT PrefixT;
55  typedef typename T::AddressT AddressT;
57 
58  // List of Route targets
59  typedef set<RouteTarget> RouteTargetList;
60 
61  // List of path ids for the Nexthop
62  typedef set<uint32_t> NexthopPathIdList;
63 
65  NoChange = 0,
69  };
70 
71  StaticRoute(RoutingInstance *rtinstance, StaticRouteMgrT *manager,
72  const PrefixT &static_route, const StaticRouteConfig &config);
75  return manager_->GetAddress(addr);
76  }
77 
79  void FillShowInfo(StaticRouteInfo *info) const;
80 
81  const PrefixT &prefix() const {
82  return prefix_;
83  }
84 
85  const IpAddress &nexthop() const {
86  return nexthop_;
87  }
88 
90  return routing_instance_;
91  }
92 
93  BgpTable *bgp_table() const {
94  return routing_instance_->GetTable(this->GetFamily());
95  }
96 
98  return nexthop_route_;
99  }
100 
102 
105 
106  if (!nexthop_route_) {
107  nexthop_path_ids_.clear();
108  return;
109  }
110 
111  assert(nexthop_path_ids_.empty());
112 
113  for (Route::PathList::iterator it =
114  nexthop_route->GetPathList().begin();
115  it != nexthop_route->GetPathList().end(); it++) {
116  BgpPath *path = static_cast<BgpPath *>(it.operator->());
117 
118  // Infeasible paths are not considered
119  if (!path->IsFeasible()) break;
120 
121  // take snapshot of all ECMP paths
122  if (nexthop_route_->BestPath()->PathCompare(*path, true)) break;
123 
124  // Use the nexthop attribute of the nexthop path as the path id.
125  uint32_t path_id = path->GetAttr()->nexthop().to_v4().to_ulong();
126  nexthop_path_ids_.insert(path_id);
127  }
128  }
129 
130  const RouteTargetList &rtarget_list() const {
131  return rtarget_list_;
132  }
133 
134  void UpdateAttributes(const StaticRouteConfig &config);
135  void AddStaticRoute(NexthopPathIdList *list);
136  void UpdateStaticRoute();
137  void RemoveStaticRoute();
138  void NotifyRoute();
139  bool IsPending() const;
140 
141  virtual bool Match(BgpServer *server, BgpTable *table,
142  BgpRoute *route, bool deleted);
143 
144  virtual string ToString() const {
145  return (string("StaticRoute ") + nexthop_.to_string());
146  }
147 
149  unregistered_ = true;
150  }
151 
152  bool unregistered() const {
153  return unregistered_;
154  }
155 
156 private:
157  // Helper function to match
158  bool is_nexthop_route(BgpRoute *route) {
159  RouteT *ip_route = dynamic_cast<RouteT *>(route);
160  return (nexthop_ == ip_route->GetPrefix().addr());
161  }
162 
164  ExtCommunityPtr UpdateExtCommunity(const BgpAttr *attr) const;
165 
175 
177 };
178 
179 template <typename T>
181  StaticRouteMgrT *manager, const PrefixT &prefix,
182  const StaticRouteConfig &config)
183  : routing_instance_(rtinstance),
184  manager_(manager),
185  prefix_(prefix),
186  nexthop_(config.nexthop),
187  nexthop_route_(NULL),
188  unregistered_(false) {
189  UpdateAttributes(config);
190 }
191 
192 //
193 // Compare the given config against the current state of the StaticRoute.
194 // Return the appropriate value from CompareResult.
195 //
196 template <typename T>
198  const StaticRouteConfig &config) {
199  AddressT address = this->GetAddress(config.address);
200  PrefixT prefix(address, config.prefix_length);
201  if (prefix_ != prefix) {
202  return PrefixChange;
203  }
204  if (nexthop_ != config.nexthop) {
205  return NexthopChange;
206  }
207  if (rtarget_list_.size() != config.route_targets.size()) {
208  return AttributeChange;
209  }
210  for (vector<string>::const_iterator it = config.route_targets.begin();
211  it != config.route_targets.end(); ++it) {
212  error_code ec;
213  RouteTarget rtarget = RouteTarget::FromString(*it, &ec);
214  if (rtarget_list_.find(rtarget) == rtarget_list_.end()) {
215  return AttributeChange;
216  }
217  }
218  if (community_ != GetCommunity(config)) {
219  return AttributeChange;
220  }
221 
222  return NoChange;
223 }
224 
225 template <typename T>
226 void StaticRoute<T>::FillShowInfo(StaticRouteInfo *info) const {
227  BgpTable *table = bgp_table();
228  RouteT rt_key(prefix_);
229  const BgpRoute *route = static_cast<const BgpRoute *>(table->Find(&rt_key));
230  const BgpPath *path = route ? route->FindPath(BgpPath::StaticRoute) : NULL;
231 
232  info->set_prefix(prefix_.ToString());
233  info->set_static_rt(path ? true : false);
234  info->set_nexthop(nexthop_.to_string());
235  if (nexthop_route_) {
236  ShowRouteBrief show_route;
237  nexthop_route_->FillRouteInfo(table, &show_route);
238  info->set_nexthop_rt(show_route);
239  }
240 
241  vector<string> community_list;
242  BOOST_FOREACH(uint32_t value, community_->communities()) {
243  community_list.push_back(CommunityType::CommunityToString(value));
244  }
245  info->set_community_list(community_list);
246 
247  vector<string> route_target_list;
248  for (RouteTargetList::const_iterator it = rtarget_list_.begin();
249  it != rtarget_list_.end(); ++it) {
250  route_target_list.push_back(it->ToString());
251  }
252  info->set_route_target_list(route_target_list);
253 
254  if (path) {
255  const RoutePathReplicator *replicator = table->server()->replicator(
256  Address::VpnFamilyFromFamily(GetFamily()));
257  info->set_secondary_tables(
258  replicator->GetReplicatedTableNameList(table, route, path));
259  }
260 }
261 
262 // Match function called from BgpConditionListener
263 // Concurrency : db::DBTable
264 template <typename T>
266  BgpRoute *route, bool deleted) {
267  CHECK_CONCURRENCY("db::DBTable");
269 
270  if (is_nexthop_route(route) && !unregistered()) {
271  if (deleted)
273  else
275  } else {
276  return false;
277  }
278 
279  BgpConditionListener *listener = server->condition_listener(GetFamily());
280  StaticRouteState *state = static_cast<StaticRouteState *>
281  (listener->GetMatchState(table, route, this));
282  if (!deleted) {
283  // MatchState is added to the Route to ensure that DBEntry is not
284  // deleted before the module processes the WorkQueue request.
285  if (!state) {
286  state = new StaticRouteState(StaticRoutePtr(this));
287  listener->SetMatchState(table, route, this, state);
288  }
289  } else {
290  // MatchState is set on all the Routes that matches the conditions
291  // Retrieve to check and ignore delete of unseen Add Match
292  if (state == NULL) {
293  // Not seen ADD ignore DELETE
294  return false;
295  }
296  }
297 
298  // The MatchState reference is taken to ensure that the route is not
299  // deleted when request is still present in the queue
300  // This is to handle the case where MatchState already exists and
301  // deleted entry gets reused or reused entry gets deleted.
302  state->IncrementRefCnt();
303 
304  // Post the Match result to StaticRoute processing task to take Action
305  // Nexthop route found in NAT instance ==> Add Static Route
306  // and stitch the Path Attribute from nexthop route
307  StaticRouteRequest *req =
308  new StaticRouteRequest(type, table, route, StaticRoutePtr(this));
309  manager_->EnqueueStaticRouteReq(req);
310 
311  return true;
312 }
313 
314 //
315 // Build a Community for the given StaticRouteConfig.
316 // Always add the AcceptOwnNexthop community in addition to the configured
317 // list.
318 //
319 template <typename T>
321  CommunitySpec comm_spec;
322  comm_spec.communities.push_back(CommunityType::AcceptOwnNexthop);
323  for (vector<string>::const_iterator it = config.communities.begin();
324  it != config.communities.end(); ++it) {
325  uint32_t value = CommunityType::CommunityFromString(*it);
326  if (!value)
327  continue;
328  comm_spec.communities.push_back(value);
329  }
330  CommunityDB *comm_db = routing_instance()->server()->comm_db();
331  return comm_db->Locate(comm_spec);
332 }
333 
334 //
335 // Build an updated ExtCommunity for the static route.
336 //
337 // Replace any RouteTargets with the list of RouteTargets for the StaticRoute.
338 // If the StaticRoute has an empty RouteTarget list, then we infer that this
339 // is not a snat use case and add the OriginVn as well. We don't want to add
340 // OriginVn in snat scenario because the route has to be imported into many
341 // VRFs and we want to set the OriginVn differently for each imported route.
342 //
343 template <typename T>
345  ExtCommunity::ExtCommunityList export_list;
346  for (RouteTargetList::const_iterator it = rtarget_list().begin();
347  it != rtarget_list().end(); it++) {
348  export_list.push_back(it->GetExtCommunity());
349  }
350 
351  BgpServer *server = routing_instance()->server();
352  ExtCommunityDB *extcomm_db = server->extcomm_db();
353  ExtCommunityPtr new_ext_community = extcomm_db->ReplaceRTargetAndLocate(
354  attr->ext_community(), export_list);
355 
356  int vn_index = routing_instance()->virtual_network_index();
357  if (export_list.empty() && vn_index) {
358  as_t asn = server->autonomous_system();
359  if (asn > AS2_MAX && vn_index > 0xffff) {
360  OriginVn origin_vn(asn, AS_TRANS);
361  new_ext_community = extcomm_db->ReplaceOriginVnAndLocate(
362  new_ext_community.get(), origin_vn.GetExtCommunity());
363  OriginVn origin_vn2(AS_TRANS, vn_index);
364  new_ext_community = extcomm_db->AppendAndLocate(
365  new_ext_community.get(), origin_vn2.GetExtCommunity());
366  } else {
367  OriginVn origin_vn(server->autonomous_system(), vn_index);
368  new_ext_community = extcomm_db->ReplaceOriginVnAndLocate(
369  new_ext_community.get(), origin_vn.GetExtCommunity());
370  }
371  }
372  return new_ext_community;
373 }
374 
375 template <typename T>
377  rtarget_list_.clear();
378  for (vector<string>::const_iterator it = config.route_targets.begin();
379  it != config.route_targets.end(); ++it) {
380  error_code ec;
381  RouteTarget rtarget = RouteTarget::FromString(*it, &ec);
382  if (ec.failed())
383  continue;
384  rtarget_list_.insert(rtarget);
385  }
386  community_ = GetCommunity(config);
387 }
388 
389 // RemoveStaticRoute
390 template <typename T>
392  CHECK_CONCURRENCY("bgp::StaticRoute");
393  RouteT rt_key(prefix_);
394  DBTablePartition *partition =
395  static_cast<DBTablePartition *>(bgp_table()->GetTablePartition(&rt_key));
396  BgpRoute *static_route =
397  static_cast<BgpRoute *>(partition->Find(&rt_key));
398  if (!static_route || static_route->IsDeleted()) return;
399 
400  for (NexthopPathIdList::iterator it = NexthopPathIds()->begin();
401  it != NexthopPathIds()->end(); it++) {
402  static_route->RemovePath(BgpPath::StaticRoute, NULL, *it);
403  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
404  "Removed Static route path " << static_route->ToString() <<
405  " path_id " << BgpPath::PathIdString(*it) <<
406  " in table " << bgp_table()->name());
407  }
408 
409  if (!static_route->HasPaths()) {
410  partition->Delete(static_route);
411  } else {
412  partition->Notify(static_route);
413  }
414 }
415 
416 // UpdateStaticRoute
417 template <typename T>
419  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
420  RouteT rt_key(prefix_);
421  DBTablePartition *partition =
422  static_cast<DBTablePartition *>(bgp_table()->GetTablePartition(&rt_key));
423  BgpRoute *static_route =
424  static_cast<BgpRoute *>(partition->Find(&rt_key));
425  if (static_route == NULL) return;
426 
427  static_route->ClearDelete();
428 
429  BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
430  for (NexthopPathIdList::iterator it = NexthopPathIds()->begin();
431  it != NexthopPathIds()->end(); it++) {
432  BgpPath *existing_path =
433  static_route->FindPath(BgpPath::StaticRoute, NULL, *it);
434  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
435  "Update attributes of StaticRoute path "
436  << static_route->ToString() << " path_id "
437  << BgpPath::PathIdString(*it) << " in table "
438  << bgp_table()->name());
439 
440  // Add the RouteTarget and OrignVn in the ExtCommunity attribute.
441  ExtCommunityPtr ptr = UpdateExtCommunity(existing_path->GetAttr());
442  BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
443  existing_path->GetAttr(), ptr);
444 
445  // Use pre-calculated community from the StaticRoute.
446  new_attr =
447  attr_db->ReplaceCommunityAndLocate(new_attr.get(), community_);
448 
449  BgpPath *new_path =
450  new BgpPath(*it, BgpPath::StaticRoute, new_attr.get(),
451  existing_path->GetFlags(), existing_path->GetLabel());
452 
453  static_route->RemovePath(BgpPath::StaticRoute, NULL, *it);
454 
455  static_route->InsertPath(new_path);
456  }
457  partition->Notify(static_route);
458 }
459 
460 // AddStaticRoute
461 template <typename T>
463  CHECK_CONCURRENCY("bgp::StaticRoute");
464 
465  RouteT rt_key(prefix_);
466  DBTablePartition *partition =
467  static_cast<DBTablePartition *>(bgp_table()->GetTablePartition(&rt_key));
468  BgpRoute *static_route =
469  static_cast<BgpRoute *>(partition->Find(&rt_key));
470 
471  if (static_route == NULL) {
472  static_route = new RouteT(prefix_);
473  partition->Add(static_route);
474  } else {
475  static_route->ClearDelete();
476  }
477 
478  BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
479  for (Route::PathList::iterator it = nexthop_route()->GetPathList().begin();
480  it != nexthop_route()->GetPathList().end(); it++) {
481  BgpPath *nexthop_route_path = static_cast<BgpPath *>(it.operator->());
482 
483  // Infeasible paths are not considered
484  if (!nexthop_route_path->IsFeasible()) break;
485 
486  // take snapshot of all ECMP paths
487  if (nexthop_route()->BestPath()->PathCompare(*nexthop_route_path, true))
488  break;
489 
490  // Skip paths with duplicate forwarding information. This ensures
491  // that we generate only one path with any given next hop and label
492  // when there are multiple nexthop paths from the original source
493  // received via different peers e.g. directly via XMPP and via BGP.
494  if (nexthop_route()->DuplicateForwardingPath(nexthop_route_path))
495  continue;
496 
497  // Add the route target in the ExtCommunity attribute.
498  ExtCommunityPtr ptr = UpdateExtCommunity(nexthop_route_path->GetAttr());
499  BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
500  nexthop_route_path->GetAttr(), ptr);
501 
502  // Use pre-calculated community from the static route.
503  new_attr =
504  attr_db->ReplaceCommunityAndLocate(new_attr.get(), community_);
505 
506  // Strip aspath. This is required when the nexthop route is learnt
507  // via BGP.
508  new_attr = attr_db->ReplaceAsPathAndLocate(new_attr.get(), AsPathPtr());
509 
510  // Replace the source rd if the nexthop path is a secondary path
511  // of a primary path in the l3vpn table. Use the RD of the primary.
512  if (nexthop_route_path->IsReplicated()) {
513  const BgpSecondaryPath *spath =
514  static_cast<const BgpSecondaryPath *>(nexthop_route_path);
515  const RoutingInstance *ri = spath->src_table()->routing_instance();
516  if (ri->IsMasterRoutingInstance()) {
517  const VpnRouteT *vpn_route =
518  static_cast<const VpnRouteT *>(spath->src_rt());
519  new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(),
520  vpn_route->GetPrefix().route_distinguisher());
521  }
522  }
523 
524  // Check whether we already have a path with the associated path id.
525  uint32_t path_id =
526  nexthop_route_path->GetAttr()->nexthop().to_v4().to_ulong();
527  BgpPath *existing_path = static_route->FindPath(BgpPath::StaticRoute,
528  NULL, path_id);
529  if (existing_path != NULL) {
530  if ((new_attr.get() != existing_path->GetAttr()) ||
531  (nexthop_route_path->GetFlags() != existing_path->GetFlags()) ||
532  (nexthop_route_path->GetLabel() != existing_path->GetLabel())) {
533  // Update Attributes and notify (if needed)
534  static_route->RemovePath(BgpPath::StaticRoute, NULL, path_id);
535  } else {
536  continue;
537  }
538  }
539 
540  // Populate SubProtocol for StaticRoute.
541  new_attr = attr_db->ReplaceSubProtocolAndLocate(new_attr.get(),
543 
544  BgpPath *new_path =
545  new BgpPath(path_id, BgpPath::StaticRoute, new_attr.get(),
546  nexthop_route_path->GetFlags(), nexthop_route_path->GetLabel());
547  static_route->InsertPath(new_path);
548  partition->Notify(static_route);
549 
550  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
551  "Added Static Route path " << static_route->ToString() <<
552  " path_id " << BgpPath::PathIdString(path_id) <<
553  " in table " << bgp_table()->name());
554  }
555 
556  if (!old_path_ids) return;
557 
558  for (NexthopPathIdList::iterator it = old_path_ids->begin();
559  it != old_path_ids->end(); it++) {
560  if (NexthopPathIds()->find(*it) != NexthopPathIds()->end())
561  continue;
562  static_route->RemovePath(BgpPath::StaticRoute, NULL, *it);
563  partition->Notify(static_route);
564 
565  BGP_LOG_STR(BgpMessage, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
566  "Removed StaticRoute path " << static_route->ToString() <<
567  " path_id " << BgpPath::PathIdString(*it) <<
568  " in table " << bgp_table()->name());
569  }
570 }
571 
572 template <typename T>
574  RouteT rt_key(prefix_);
575  DBTablePartition *partition =
576  static_cast<DBTablePartition *>(bgp_table()->GetTablePartition(&rt_key));
577  BgpRoute *static_route = static_cast<BgpRoute *>(partition->Find(&rt_key));
578  if (!static_route)
579  return;
580  partition->Notify(static_route);
581 }
582 
583 template <typename T>
585  RouteT rt_key(prefix_);
586  DBTablePartition *partition =
587  static_cast<DBTablePartition *>(bgp_table()->GetTablePartition(&rt_key));
588  const BgpRoute *route = static_cast<BgpRoute *>(partition->Find(&rt_key));
589  return (!route || !route->FindPath(BgpPath::StaticRoute));
590 }
591 
592 template <>
594 template <>
596 
597 template <typename T>
599  : rtinstance_(rtinstance),
600  listener_(rtinstance_->server()->condition_listener(GetFamily())),
601  unregister_list_trigger_(new TaskTrigger(
602  boost::bind(&StaticRouteMgr::ProcessUnregisterList, this),
603  TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0)) {
604  if (static_route_task_id_ == -1) {
606  static_route_task_id_ = scheduler->GetTaskId("bgp::StaticRoute");
607  }
608 
611  boost::bind(&StaticRouteMgr::StaticRouteEventCallback, this, _1));
612 }
613 
614 template <>
616  return Address::INET;
617 }
618 
619 template <>
621  return Address::INET6;
622 }
623 
624 template <>
626  assert(addr.is_v4());
627  return addr.to_v4();
628 }
629 
630 template <>
632  assert(addr.is_v6());
633  return addr.to_v6();
634 }
635 
636 template <typename T>
638  static_route_queue_->Enqueue(req);
639 }
640 
641 template <typename T>
643  CHECK_CONCURRENCY("bgp::StaticRoute");
644  BgpTable *table = req->table_;
645  BgpRoute *route = req->rt_;
646  StaticRouteT *info = static_cast<StaticRouteT *>(req->info_.get());
647 
648  StaticRouteState *state = NULL;
649  if (route) {
650  state = static_cast<StaticRouteState *>
651  (listener_->GetMatchState(table, route, info));
652  }
653 
654  switch (req->type_) {
656  assert(state);
657  state->reset_deleted();
658  if (route->IsDeleted() || !route->BestPath() ||
659  !route->BestPath()->IsFeasible()) {
660  break;
661  }
662 
663  // Store the old path list
664  typename StaticRouteT::NexthopPathIdList path_ids;
665  path_ids.swap(*(info->NexthopPathIds()));
666 
667  // Populate the Nexthop PathID
668  info->set_nexthop_route(route);
669 
670  info->AddStaticRoute(&path_ids);
671  break;
672  }
674  assert(state);
675  info->RemoveStaticRoute();
676  if (info->deleted() || route->IsDeleted()) {
677  state->set_deleted();
678  }
679  info->set_nexthop_route(NULL);
680  break;
681  }
682  default: {
683  assert(0);
684  break;
685  }
686  }
687 
688  if (state) {
689  state->DecrementRefCnt();
690  if (state->refcnt() == 0 && state->deleted()) {
691  listener_->RemoveMatchState(table, route, info);
692  delete state;
693  if (!info->num_matchstate() && info->unregistered()) {
694  UnregisterAndResolveStaticRoute(info);
695  }
696  }
697  }
698 
699  delete req;
700  return true;
701 }
702 
703 template <typename T>
705  CHECK_CONCURRENCY("bgp::Config");
706 
707  for (StaticRouteProcessList::iterator
708  it = unregister_static_route_list_.begin();
709  it != unregister_static_route_list_.end(); ++it) {
710  StaticRouteT *info = static_cast<StaticRouteT *>(it->get());
711  listener_->UnregisterMatchCondition(info->bgp_table(), info);
712  static_route_map_.erase(RouteKey(info->prefix(), info->nexthop()));
713  }
714 
715  unregister_static_route_list_.clear();
716 
717  if (static_route_map_.empty()) {
718  rtinstance_->server()->RemoveStaticRouteMgr(this);
719  }
720 
721  if (!routing_instance()->deleted() &&
722  routing_instance()->config()) {
723  ProcessStaticRouteConfig();
724  }
725  return true;
726 }
727 
728 template <typename T>
730  tbb::mutex::scoped_lock lock(mutex_);
731  unregister_static_route_list_.insert(entry);
732  unregister_list_trigger_->Set();
733 }
734 
735 template <typename T>
737  const StaticRouteConfig &config) {
738  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
739  AddressT address = this->GetAddress(config.address);
740  PrefixT prefix(address, config.prefix_length);
741  RouteKey route_key(prefix, config.nexthop);
742 
743  // Verify whether the entry already exists
744  typename StaticRouteMap::iterator it = static_route_map_.find(route_key);
745  if (it != static_route_map_.end()) {
746  // Wait for the delete complete cb
747  if (it->second->deleted()) return;
748 
749  StaticRouteT *match =
750  static_cast<StaticRouteT *>(it->second.get());
751  // Check whether the config has got updated
752  typename StaticRouteT::CompareResult change =
753  match->CompareConfig(config);
754 
755  // StaticRoutePrefix is the key, it can't change.
756  assert(change != StaticRouteT::PrefixChange);
757 
758  // Skip if there's no change.
759  if (change == StaticRouteT::NoChange)
760  return;
761 
762  // Update the attributes and any existing BgpPaths.
763  if (change == StaticRouteT::AttributeChange) {
764  match->UpdateAttributes(config);
765  match->UpdateStaticRoute();
766  return;
767  }
768 
769  // If the nexthop changes, remove the static route, if already added.
770  // To do this, remove match condition and wait for remove completion.
772  boost::bind(&StaticRouteMgr::StopStaticRouteDone, this, _1, _2);
773  listener_->RemoveMatchCondition(
774  match->bgp_table(), it->second.get(), callback);
775  return;
776  }
777 
778  StaticRouteT *match =
779  new StaticRouteT(routing_instance(), this, prefix, config);
780  StaticRoutePtr static_route_match = StaticRoutePtr(match);
781 
782  if (static_route_map_.empty())
783  rtinstance_->server()->InsertStaticRouteMgr(this);
784  static_route_map_.insert(make_pair(route_key, static_route_match));
785 
786  listener_->AddMatchCondition(match->bgp_table(), static_route_match.get(),
788 }
789 
790 template <typename T>
792  ConditionMatch *info) {
793  CHECK_CONCURRENCY("db::Walker");
794  StaticRoute<T> *match = static_cast<StaticRoute<T> *>(info);
795  match->set_unregistered();
796  if (!match->num_matchstate() && match->unregistered()) {
797  UnregisterAndResolveStaticRoute(match);
798  }
799  return;
800 }
801 
802 template <typename T>
804  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
805  typename StaticRouteMap::iterator it = static_route_map_.find(static_route);
806  if (it == static_route_map_.end()) return;
807 
808  if (it->second->deleted()) return;
809 
811  boost::bind(&StaticRouteMgr::StopStaticRouteDone, this, _1, _2);
812 
813  StaticRouteT *match = static_cast<StaticRouteT *>(it->second.get());
814  listener_->RemoveMatchCondition(match->bgp_table(), match, callback);
815 }
816 
817 template <typename T>
819  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
820  if (routing_instance()->deleted() || !routing_instance()->config()) return;
822  routing_instance()->config()->static_routes(GetFamily());
823  typedef BgpInstanceConfig::StaticRouteList::const_iterator iterator_t;
824  for (iterator_t iter = list.begin(); iter != list.end(); ++iter) {
825  LocateStaticRoutePrefix(*iter);
826  }
827 }
828 
829 template <typename T>
831  if (static_route_queue_)
832  delete static_route_queue_;
833 }
834 
835 template <typename T>
837  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
838  StaticRouteConfigList config_list =
839  routing_instance()->config()->static_routes(GetFamily());
840 
841  map_difference(&static_route_map_,
842  config_list.begin(), config_list.end(),
843  boost::bind(&StaticRouteMgr<T>::CompareStaticRoute, this, _1, _2),
844  boost::bind(&StaticRouteMgr<T>::AddStaticRoute, this, _1),
845  boost::bind(&StaticRouteMgr<T>::DelStaticRoute, this, _1),
846  boost::bind(&StaticRouteMgr<T>::UpdateStaticRoute, this, _1, _2));
847 }
848 
849 template <typename T>
851  CHECK_CONCURRENCY("bgp::Config");
852  for (typename StaticRouteMap::iterator it = static_route_map_.begin();
853  it != static_route_map_.end(); it++) {
854  RemoveStaticRoutePrefix(it->first);
855  }
856 }
857 
858 template <typename T>
860  typename StaticRouteMap::iterator loc,
861  StaticRouteConfigList::iterator it) {
862  AddressT address = this->GetAddress(it->address);
863  PrefixT prefix(address, it->prefix_length);
864  RouteKey route_key(prefix, it->nexthop);
865  KEY_COMPARE(loc->first, route_key);
866  return 0;
867 }
868 
869 template <typename T>
870 void StaticRouteMgr<T>::AddStaticRoute(StaticRouteConfigList::iterator it) {
871  LocateStaticRoutePrefix(*it);
872 }
873 
874 template <typename T>
875 void StaticRouteMgr<T>::DelStaticRoute(typename StaticRouteMap::iterator loc) {
876  RemoveStaticRoutePrefix(loc->first);
877 }
878 
879 template <typename T>
880 void StaticRouteMgr<T>::UpdateStaticRoute(typename StaticRouteMap::iterator loc,
881  StaticRouteConfigList::iterator it) {
882  LocateStaticRoutePrefix(*it);
883 }
884 
885 template <typename T>
887  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
888  for (typename StaticRouteMap::iterator it = static_route_map_.begin();
889  it != static_route_map_.end(); ++it) {
890  StaticRouteT *static_route =
891  static_cast<StaticRouteT *>(it->second.get());
892  static_route->NotifyRoute();
893  }
894 }
895 
896 template <typename T>
898  CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
899  for (typename StaticRouteMap::iterator it = static_route_map_.begin();
900  it != static_route_map_.end(); ++it) {
901  StaticRouteT *static_route =
902  static_cast<StaticRouteT *>(it->second.get());
903  static_route->UpdateStaticRoute();
904  }
905 }
906 
907 template <typename T>
909  unregister_list_trigger_->set_disable();
910 }
911 
912 template <typename T>
914  unregister_list_trigger_->set_enable();
915 }
916 
917 template <typename T>
919  CHECK_CONCURRENCY("bgp::ShowCommand");
920  return static_route_map_.size();
921 }
922 
923 template <typename T>
925  CHECK_CONCURRENCY("bgp::ShowCommand");
926  uint32_t count = 0;
927  for (typename StaticRouteMap::const_iterator it = static_route_map_.begin();
928  it != static_route_map_.end(); ++it) {
929  const StaticRouteT *static_route =
930  static_cast<const StaticRouteT *>(it->second.get());
931  if (static_route->IsPending())
932  count++;
933  }
934  return count;
935 }
936 
937 template <typename T> bool StaticRouteMgr<T>::FillStaticRouteInfo(
938  RoutingInstance *ri, StaticRouteEntriesInfo *info) const {
939  if (static_route_map_.empty())
940  return false;
941 
942  info->set_ri_name(ri->name());
944  static_route_map_.begin(); it != static_route_map_.end(); ++it) {
945  StaticRoute<T> *match =
946  static_cast<StaticRoute<T> *>(it->second.get());
947  StaticRouteInfo static_info;
948  match->FillShowInfo(&static_info);
949  info->static_route_list.push_back(static_info);
950  }
951  return true;
952 }
953 
954 // Explicit instantiation of StaticRouteMgr for INET and INET6.
955 template class StaticRouteMgr<StaticRouteInet>;
956 template class StaticRouteMgr<StaticRouteInet6>;
boost::intrusive_ptr< const AsPath > AsPathPtr
Definition: bgp_aspath.h:165
std::vector< std::string > route_targets
Definition: bgp_config.h:342
ExtCommunityPtr AppendAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &list)
Definition: community.cc:696
virtual string ToString() const
ExtCommunityPtr ReplaceOriginVnAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityValue &origin_vn)
Definition: community.cc:884
static Family VpnFamilyFromFamily(Family family)
Definition: address.cc:71
int CompareStaticRoute(typename StaticRouteMap::iterator loc, StaticRouteConfigList::iterator it)
const IpAddress & nexthop() const
Definition: bgp_attr.h:886
BgpTable * GetTable(Address::Family fmly)
bool IsPending() const
StaticRouteMgr< T > StaticRouteMgrT
Definition: static_route.cc:56
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
ExtCommunityPtr UpdateExtCommunity(const BgpAttr *attr) const
void AddStaticRoute(StaticRouteConfigList::iterator it)
TypePtr Locate(Type *attr)
IpAddress address
Definition: bgp_config.h:339
virtual void EnableUnregisterTrigger()
RouteTargetList rtarget_list_
IpAddress nexthop_
BgpTable * bgp_table() const
Definition: static_route.cc:93
set< uint32_t > NexthopPathIdList
Definition: static_route.cc:62
StaticRouteState(StaticRoutePtr info)
Definition: static_route.cc:38
CommunityPtr community_
virtual bool Match(BgpServer *server, BgpTable *table, BgpRoute *route, bool deleted)
DISALLOW_COPY_AND_ASSIGN(StaticRoute)
boost::function< void(BgpTable *, ConditionMatch *)> RequestDoneCb
BgpAttrPtr ReplaceCommunityAndLocate(const BgpAttr *attr, CommunityPtr community)
Definition: bgp_attr.cc:1314
DBEntry * Find(const DBEntry *entry)
static std::string PathIdString(uint32_t path_id)
Definition: bgp_path.cc:18
virtual void NotifyAllRoutes()
ConditionMatchState * GetMatchState(BgpTable *table, BgpRoute *route, ConditionMatch *obj)
RoutingInstance * routing_instance()
Definition: bgp_table.h:148
Family
Definition: address.h:24
#define KEY_COMPARE(x, y)
Definition: util.h:70
bool IsDeleted() const
Definition: db_entry.h:49
const PrefixT & prefix() const
Definition: static_route.cc:81
static const std::string CommunityToString(uint32_t comm)
boost::asio::ip::address IpAddress
Definition: address.h:13
const IpAddress & nexthop() const
Definition: static_route.cc:85
RequestType type_
Definition: static_route.h:54
virtual void UpdateAllRoutes()
void UpdateStaticRoute(typename StaticRouteMap::iterator loc, StaticRouteConfigList::iterator it)
StaticRouteMgr(RoutingInstance *instance)
bool is_nexthop_route(BgpRoute *route)
virtual void UpdateStaticRouteConfig()
void set_nexthop_route(BgpRoute *nexthop_route)
IpAddress nexthop
Definition: bgp_config.h:341
const std::string & name() const
const BgpPath * FindPath(BgpPath::PathSource src) const
Definition: bgp_route.cc:145
virtual void FlushStaticRouteConfig()
BgpConditionListener * condition_listener(Address::Family family)
Definition: bgp_server.h:114
T::PrefixT PrefixT
Definition: static_route.cc:54
RoutePathReplicator * replicator(Address::Family family)
Definition: bgp_server.h:146
PrefixT prefix_
std::set< StaticRouteConfig > StaticRouteList
Definition: bgp_config.h:425
std::vector< std::string > communities
Definition: bgp_config.h:343
virtual void ProcessStaticRouteConfig()
void Delete(DBEntryBase *)
uint32_t GetFlags() const
Definition: bgp_path.h:100
uint32_t as_t
Definition: bgp_common.h:21
bool unregistered_
T::RouteT RouteT
Definition: static_route.cc:52
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
int GetTaskId(const std::string &name)
Definition: task.cc:856
T::PrefixT PrefixT
Definition: static_route.h:68
#define BGP_LOG_STR(obj, level, flags, arg)
Definition: bgp_log.h:89
bool StaticRouteEventCallback(StaticRouteRequest *req)
DISALLOW_COPY_AND_ASSIGN(StaticRouteState)
RoutingInstance * routing_instance() const
Definition: static_route.cc:89
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
StaticRoutePtr info_
Definition: static_route.h:57
virtual void DisableUnregisterTrigger()
RoutingInstance * routing_instance_
void RemoveStaticRoute()
bool IsFeasible() const
Definition: bgp_path.h:92
uint8_t type
Definition: load_balance.h:109
BgpRoute * nexthop_route_
void map_difference(ForwardIterator __first1, ForwardIterator __last1, ForwardIterator __first2, ForwardIterator __last2, AddFunctor __add_fn, DelFunctor __del_fn, EqFunctor __eq_fn)
Definition: map_util.h:20
Address::Family GetFamily() const
Definition: static_route.cc:73
virtual uint32_t GetRouteCount() const
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:187
static TaskScheduler * GetInstance()
Definition: task.cc:547
StaticRouteMgrT * manager_
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
BgpAttrPtr ReplaceSubProtocolAndLocate(const BgpAttr *attr, const std::string &sbp)
Definition: bgp_attr.cc:1396
void set_unregistered()
#define CHECK_CONCURRENCY(...)
AddressT GetAddress(IpAddress addr) const
Definition: static_route.cc:74
void SetMatchState(BgpTable *table, BgpRoute *route, ConditionMatch *obj, ConditionMatchState *state=NULL)
const string MatchProtocolToString(MatchProtocol::MatchProtocolType protocol)
void EnqueueStaticRouteReq(StaticRouteRequest *req)
const RouteTargetList & rtarget_list() const
void UpdateStaticRoute()
WorkQueue< StaticRouteRequest * > * static_route_queue_
Definition: static_route.h:146
void DelStaticRoute(typename StaticRouteMap::iterator loc)
virtual std::string ToString() const =0
bool ProcessUnregisterList()
BgpAttrPtr ReplaceSourceRdAndLocate(const BgpAttr *attr, const RouteDistinguisher &source_rd)
Definition: bgp_attr.cc:1362
void FillShowInfo(StaticRouteInfo *info) const
BgpServer * server()
Definition: bgp_attr.h:1031
void ClearDelete()
Definition: db_entry.h:48
set< RouteTarget > RouteTargetList
Definition: static_route.cc:59
static RouteTarget FromString(const std::string &str, boost::system::error_code *error=NULL)
uint32_t GetLabel() const
Definition: bgp_path.h:89
int PathCompare(const BgpPath &rhs, bool allow_ecmp) const
Definition: bgp_path.cc:58
AddressT GetAddress(IpAddress addr) const
boost::intrusive_ptr< const Community > CommunityPtr
Definition: community.h:109
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
std::vector< std::string > GetReplicatedTableNameList(const BgpTable *table, const BgpRoute *route, const BgpPath *path) const
BgpServer * server()
Definition: bgp_table.cc:88
bool RemovePath(BgpPath::PathSource src, const IPeer *peer=NULL, uint32_t path_id=0)
Definition: bgp_route.cc:262
BgpRoute * nexthop_route() const
Definition: static_route.cc:97
StaticRoutePtr info_
Definition: static_route.cc:45
bool unregistered() const
void UnregisterAndResolveStaticRoute(StaticRoutePtr entry)
bool IsMasterRoutingInstance() const
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
BgpAttrPtr ReplaceAsPathAndLocate(const BgpAttr *attr, AsPathPtr aspath)
Definition: bgp_attr.cc:1306
const BgpRoute * src_rt() const
Definition: bgp_path.h:186
Address::Family GetFamily() const
#define BGP_LOG_FLAG_TRACE
Definition: bgp_log.h:43
BgpAttrDB * attr_db()
Definition: bgp_server.h:181
static ExtCommunityPtr UpdateExtCommunity(BgpServer *server, const RoutingInstance *rtinstance, const ExtCommunity *ext_community, const ExtCommunity::ExtCommunityList &export_list)
void AddStaticRoute(NexthopPathIdList *list)
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
bool HasPaths() const
Definition: bgp_route.h:27
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
BgpTable * table_
Definition: static_route.h:55
void RemoveStaticRoutePrefix(const RouteKey &static_route)
DBEntry * Find(const DBEntry *entry)
Definition: db_table.cc:469
virtual bool FillStaticRouteInfo(RoutingInstance *rtinstance, StaticRouteEntriesInfo *info) const
const bytes_type & GetExtCommunity() const
Definition: origin_vn.h:33
void NotifyRoute()
CommunityPtr GetCommunity(const StaticRouteConfig &config)
NexthopPathIdList nexthop_path_ids_
virtual void Add(DBEntry *entry)
CompareResult CompareConfig(const StaticRouteConfig &config)
std::vector< uint32_t > communities
Definition: community.h:33
const BgpTable * src_table() const
Definition: bgp_path.h:182
void StopStaticRouteDone(BgpTable *table, ConditionMatch *info)
void Notify(DBEntryBase *entry)
T::VpnRouteT VpnRouteT
Definition: static_route.cc:53
BgpInstanceConfig::StaticRouteList StaticRouteConfigList
Definition: static_route.h:114
uint32_t num_matchstate() const
static uint32_t CommunityFromString(const std::string &comm, boost::system::error_code *perr=NULL)
virtual bool IsReplicated() const
Definition: bgp_path.h:91
as_t autonomous_system() const
Definition: bgp_server.h:205
StaticRoute(RoutingInstance *rtinstance, StaticRouteMgrT *manager, const PrefixT &static_route, const StaticRouteConfig &config)
#define AS_TRANS
Definition: bgp_common.h:23
ExtCommunityPtr ReplaceRTargetAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &export_list)
Definition: community.cc:743
NexthopPathIdList * NexthopPathIds()
T::AddressT AddressT
Definition: static_route.cc:55
void LocateStaticRoutePrefix(const StaticRouteConfig &config)
T::AddressT AddressT
Definition: static_route.h:69
const PathList & GetPathList() const
Definition: route.h:46
virtual uint32_t GetDownRouteCount() const
#define AS2_MAX
Definition: bgp_common.h:24
void UpdateAttributes(const StaticRouteConfig &config)
ConditionMatchPtr StaticRoutePtr
Definition: static_route.h:41
StaticRoutePtr info()
Definition: static_route.cc:40