OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
agent_route.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 #include <boost/uuid/uuid_io.hpp>
5 #include <boost/lexical_cast.hpp>
6 
7 #include <cmn/agent_cmn.h>
8 #include <route/route.h>
9 
10 #include <vnc_cfg_types.h>
11 #include <agent_types.h>
12 
13 #include <init/agent_param.h>
14 #include <oper/peer.h>
15 #include <oper/vrf.h>
16 #include <oper/interface_common.h>
17 #include <oper/nexthop.h>
18 #include <oper/tunnel_nh.h>
19 #include <oper/vn.h>
20 #include <oper/mirror_table.h>
21 #include <oper/vxlan.h>
22 #include <oper/mpls.h>
23 #include <oper/route_common.h>
24 #include <oper/multicast.h>
25 #include <sandesh/sandesh_trace.h>
26 #include <sandesh/common/vns_constants.h>
30 
31 #include <oper/physical_device.h>
32 using namespace std;
33 using namespace boost::asio;
34 
36  public:
38  LifetimeActor(rt_table->agent()->lifetime_manager()),
39  table_(rt_table) {
40  }
41  virtual ~DeleteActor() {
42  }
43  virtual bool MayDelete() const {
44  return table_->MayDelete();
45  }
46  virtual void Shutdown() {
47  }
48  virtual void Destroy() {
49  assert(table_->vrf_entry_.get() != NULL);
50  table_->vrf_entry_->SetRouteTableDeleted(table_->GetTableType());
51  //Release refernces
52  table_->vrf_delete_ref_.Reset(NULL);
53  table_->vrf_entry_ = NULL;
54  }
55 
56  private:
58 };
59 
60 bool RouteComparator::operator() (const AgentRoute *rt1, const AgentRoute *rt2) const {
61  return rt1->IsLess(*rt2);
62 }
63 
64 bool NHComparator::operator() (const NextHop *nh1, const NextHop *nh2) const {
65  return nh1->IsLess(*nh2);
66 }
67 
69 // AgentRouteTable routines
71 AgentRouteTable::AgentRouteTable(DB *db, const std::string &name):
72  RouteTable(db, name), agent_(NULL), vrf_id_(0), vrf_entry_(NULL, this),
73  deleter_(NULL), vrf_delete_ref_(this, NULL), unresolved_rt_tree_(),
74  unresolved_nh_tree_() {
75  OperDBTraceBuf = SandeshTraceBufferCreate("OperRoute", 5000);
76 }
77 
79 }
80 
81 // Allocate a route entry
82 unique_ptr<DBEntry> AgentRouteTable::AllocEntry(const DBRequestKey *k) const {
83  const AgentRouteKey *key = static_cast<const AgentRouteKey*>(k);
84  VrfKey vrf_key(key->vrf_name());
85  AgentRoute *route =
86  static_cast<AgentRoute *>(key->AllocRouteEntry(vrf_entry_.get(),
87  false));
88  return unique_ptr<DBEntry>(static_cast<DBEntry *>(route));
89 }
90 
91 // Algorithm to select an active path from multiple potential paths.
92 // Uses comparator in path for selection
93 bool AgentRouteTable::PathSelection(const Path &path1, const Path &path2) {
94  const AgentPath &l_path = dynamic_cast<const AgentPath &> (path1);
95  const AgentPath &r_path = dynamic_cast<const AgentPath &> (path2);
96  return l_path.IsLess(r_path);
97 }
98 
100  static const string uc_suffix(".uc.route.0");
101  static const string mpls_suffix(".uc.route.3");
102  static const string mc_suffix(".mc.route.0");
103  static const string evpn_suffix(".evpn.route.0");
104  static const string l2_suffix(".l2.route.0");
105  static const string uc_inet6_suffix(".uc.route6.0");
106 
107  switch (type) {
109  return uc_suffix;
110  case Agent::INET4_MPLS:
111  return mpls_suffix;
113  return mc_suffix;
114  case Agent::EVPN:
115  return evpn_suffix;
116  case Agent::BRIDGE:
117  return l2_suffix;
119  return uc_inet6_suffix;
120  default:
121  return Agent::NullString();
122  }
123 }
124 
125 // Set VRF and delete life-time actor reference to VRF
127  agent_ = (static_cast<VrfTable *>(vrf->get_table()))->agent();
128  vrf_entry_ = vrf;
129  vrf_id_ = vrf->vrf_id();
130  vrf_delete_ref_.Reset(vrf->deleter());
131  deleter_.reset(new DeleteActor(this));
132 }
133 
134 //Delete all the routes
138  boost::bind(&AgentRouteTable::DelExplicitRouteWalkerCb, this, _1, _2),
139  boost::bind(&AgentRouteTable::DeleteRouteDone, this, _1, _2, state));
140  //On managed delete, walk to delete paths need to be done once as no route
141  //should be added in deleted vrf.
142  //Once the walk is over walkdone will reset walk_ref.
143  WalkTable(walk_ref);
144  deleter_->Delete();
145 }
146 
148  DBTableBase *base,
149  RouteTableWalkerState *state) {
150  LOG(DEBUG, "Deleted all BGP injected routes for " << base->name());
151  ReleaseWalker(walk_ref);
152  delete state;
153 }
154 
156  DBEntryBase *entry) {
157  AgentRoute *route = static_cast<AgentRoute *>(entry);
158  if (route == NULL)
159  return true;
160 
161  return route->DeleteAllBgpPath(part, this);
162 }
163 
165  if (!deleter()->IsDeleted()) {
166  return;
167  }
168  if (empty()) {
169  vrf_entry()->RetryDelete();
170  }
171  deleter()->RetryDelete();
172 }
173 
175  agent()->ConcurrencyCheck();
176  DBTablePartBase *tpart =
177  static_cast<DBTablePartition *>(GetTablePartition(e));
178  tpart->Notify(e);
179 }
180 
182 // Agent route input processing
184 
185 // Inline processing of Route request.
187  agent()->ConcurrencyCheck();
188  DBTablePartition *tpart =
189  static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
190  tpart->Process(NULL, &req);
191 }
192 
193 // Input handler for Route Table.
194 // Adds a route entry if not present.
195 // Adds path to route entry
196 // Paths are sorted in order of their precedence
197 // A DELETE request always removes path from the peer
198 // Route entry with no paths is automatically deleted
200  DBRequest *req) {
201  AgentRouteKey *key = static_cast<AgentRouteKey *>(req->key.get());
202  AgentRouteData *data = static_cast<AgentRouteData *>(req->data.get());
203 
204  VrfEntry *vrf = agent_->vrf_table()->FindVrfFromName(key->vrf_name());
205  // Ignore request if VRF not found.
206  // VRF in deleted state is handled below based on operation
207  if (vrf == NULL)
208  return;
209 
210  // We dont force DBRequest to be enqueued to the right DB Table.
211  // Find the right DBTable from VRF and invoke Input from right table
212  AgentRouteTable *req_table = vrf->GetRouteTable(key->GetRouteTableType());
213  if (req_table != this) {
214  if (req_table == NULL) {
215  // If route table is already deleted from VRF, it means VRF should
216  // also be in deleted state
217  assert(vrf->IsDeleted());
218  return;
219  }
220 
221  DBTablePartition *p =
222  static_cast<DBTablePartition *>(req_table->GetTablePartition(key));
223  req_table->Input(p, client, req);
224  return;
225  }
226 
227  AgentRoute *rt = static_cast<AgentRoute *>(part->Find(key));
228  if (req->oper == DBRequest::DB_ENTRY_DELETE) {
229  if (rt)
230  rt->DeleteInput(part, this, key, data);
231  return;
232  }
233 
234  if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
235  AddChangeInput(part, vrf, rt, key, data);
236  return;
237  }
238 
239  assert(0);
240 }
241 
242 // Handle RESYNC and ADD_CHANGE requests
244  AgentRoute *rt, AgentRouteKey *key,
245  AgentRouteData *data) {
246  if (key->peer()->SkipAddChangeRequest()) {
247  AGENT_ROUTE_LOG(this, "Route operation ignored. Deleted Peer ",
248  key->ToString(), vrf_name(), key->peer()->GetName());
249  return;
250  }
251 
252  if (vrf->IsDeleted() && vrf->allow_route_add_on_deleted_vrf() == false)
253  return;
254 
255  AgentPath *path = NULL;
256  bool notify = false;
257  const NextHop *nh = NULL;
258  if (rt) {
259  nh = rt->GetActiveNextHop();
260  }
261  if (key->sub_op_ == AgentKey::RESYNC) {
262  // Process RESYNC only if route present and not-deleted
263  if (rt && (rt->IsDeleted() == false))
264  notify |= rt->SubOpResyncInput(vrf, this, &path, key, data);
265  } else if (key->sub_op_ == AgentKey::ADD_DEL_CHANGE) {
266  bool route_added = (rt == NULL);
267  rt = LocateRoute(part, vrf, rt, key, data, &notify);
268  notify |= rt->SubOpAddChangeInput(vrf, this, &path, key, data,
269  route_added);
270  } else {
271  assert(0);
272  }
273 
274  // If this route has a unresolved path, insert to unresolved list
275  // this is a hack , TODO: fix unresolved route handling correctly
276  if (rt && rt->HasUnresolvedPath() == true) {
277  rt->AddUnresolvedRouteToTable(this);
278  }
279  // Route changed, trigger change on dependent routes
280  if (notify) {
281  bool active_path_changed = (path == rt->GetActivePath());
282  const AgentPath *prev_active_path = rt->GetActivePath();
283  CompositeNH *cnh = NULL;
284  if (prev_active_path) {
285  cnh = dynamic_cast<CompositeNH *>(prev_active_path->nexthop());
286  }
287  const Path *prev_front = rt->front();
288  if (prev_front) {
289  rt->Sort(&AgentRouteTable::PathSelection, prev_front);
290  }
291  if (rt->GetActiveNextHop() != nh) {
292  active_path_changed = true;
293  }
294  // for flow stickiness , maintain same component NH grid
295  // if the newly insterted path becomes active,
296  // if peer type is same, and it is composite NH
297  // then import previous active NH to current active path
298  // Note: Change is limited to BGP peer paths
299  if ( (path == rt->GetActivePath()) &&
300  (path != prev_active_path)) {
301  CompositeNH *new_cnh =
302  dynamic_cast<CompositeNH *>(path->nexthop());
303  if (cnh && new_cnh &&
304  (path->peer()->GetType() == Peer::BGP_PEER) &&
305  (prev_active_path->peer()->GetType() == Peer::BGP_PEER) &&
306  (cnh->composite_nh_type() == Composite::ECMP) &&
307  (new_cnh->composite_nh_type() == Composite::ECMP)) {
308  path->ImportPrevActiveNH(agent_, cnh);
309  }
310  }
311  part->Notify(rt);
312  rt->UpdateDependantRoutes();
313  rt->ResyncTunnelNextHop();
314 
315  // Since newly added path became active path, send path with
316  // path_changed flag as true. Path can be NULL for resync requests
317  active_path_changed |= (path == rt->GetActivePath());
318  rt->UpdateDerivedRoutes(this, path, active_path_changed);
319  }
320 }
321 
323  VrfEntry *vrf, AgentRoute *rt,
324  AgentRouteKey *key,
325  AgentRouteData *data, bool *notify) {
326  // Return if route already present and not deleted
327  if (rt != NULL && rt->IsDeleted() == false)
328  return rt;
329 
330  // Add route if not present already
331  if (rt == NULL) {
332  rt = static_cast<AgentRoute *>
333  (key->AllocRouteEntry(vrf, data->is_multicast()));
334  assert(rt->vrf() != NULL);
335  part->Add(rt);
336  }
337 
338  // Renew the route if its in deleted state
339  if (rt->IsDeleted()) {
340  assert(rt->IsDeleted());
341  rt->ClearDelete();
342  *notify = true;
343  }
344 
345  ProcessAdd(rt);
346  RouteInfo rt_info;
347  rt->FillTrace(rt_info, AgentRoute::ADD, NULL);
348  OPER_TRACE_ROUTE_ENTRY(Route, this, rt_info);
349  return rt;
350 }
351 
353 
354  if (dependent_route_table_ == NULL) {
355  const AgentPath *path = GetActivePath();
356  if (path->GetDependentTable()) {
358  } else {
359  dependent_route_table_ = table;
360  }
361  }
363 }
367  } else {
368  table->RemoveUnresolvedRoute(this);
369  }
370 }
371 
372 
373 // Re-evaluate all unresolved NH. Flush and enqueue RESYNC for all NH in the
374 // unresolved NH tree
376  for (UnresolvedNHTree::iterator it = unresolved_nh_tree_.begin();
377  it != unresolved_nh_tree_.end(); ++it) {
378  (*it)->EnqueueResync();
379 
381  req.key = (*it)->GetDBRequestKey();
382  (static_cast<NextHopKey *>(req.key.get()))->sub_op_ = AgentKey::RESYNC;
383  agent_->nexthop_table()->Enqueue(&req);
384  }
385 
386  unresolved_nh_tree_.clear();
387 }
388 
390  unresolved_nh_tree_.insert(nh);
391 }
392 
394  unresolved_nh_tree_.erase(nh);
395 }
396 
397 // Re-evaluate all unresolved routes. Flush and enqueue RESYNC for all routes
398 // in the unresolved route tree
400  for (UnresolvedRouteTree::iterator it = unresolved_rt_tree_.begin();
401  it != unresolved_rt_tree_.end(); ++it) {
402  (*it)->EnqueueRouteResync();
403  }
404 
405  unresolved_rt_tree_.clear();
406 }
407 
409  unresolved_rt_tree_.insert(rt);
410 }
411 
413  unresolved_rt_tree_.erase(rt);
414 }
415 
416 // Find entry not in deleted state
418  AgentRoute *entry = static_cast<AgentRoute *>(Find(key));
419  if (entry && entry->IsDeleted()) {
420  return NULL;
421  }
422  return entry;
423 }
424 
426  DBTable *table = static_cast<DBTable *>(this);
427  AgentRoute *entry = static_cast<AgentRoute *>(table->FindNoLock(key));
428  if (entry && entry->IsDeleted()) {
429  return NULL;
430  }
431  return entry;
432 }
433 
435  AgentRoute *entry = static_cast<AgentRoute *>(Find(key));
436  if (entry && entry->IsDeleted()) {
437  return NULL;
438  }
439  return entry;
440 }
441 
443  DBTable *table = static_cast<DBTable *>(this);
444  AgentRoute *entry = static_cast<AgentRoute *>(table->FindNoLock(key));
445  if (entry && entry->IsDeleted()) {
446  return NULL;
447  }
448  return entry;
449 }
450 
452  return deleter_.get();
453 }
454 
455 const std::string &AgentRouteTable::vrf_name() const {
456  return vrf_entry_->GetName();
457 }
458 
460  return vrf_entry_.get();
461 }
462 
464 // AgentRoute routines
466 
467 // Hnadle RESYNC operation for a route
469  AgentPath **path_ptr, AgentRouteKey *key,
470  AgentRouteData *data) {
471  // Handle change to route itself and not to a particular path
472  if (data == NULL || key->peer() == NULL) {
473  Sync();
474  return true;
475  }
476 
477  // Get path to update
478  AgentPath *path = FindPath(key->peer());
479  if (path == NULL)
480  return false;
481 
482  bool ret = false;
483  *path_ptr = path;
484  bool old_ecmp = path->path_preference().is_ecmp();
485  if (data->AddChangePath(table->agent(), path, this))
486  ret = true;
487 
488  // Transition from ECMP to non-ECMP should result in removal of member
489  // from ECMP path
490  if (old_ecmp && old_ecmp != path->path_preference().is_ecmp()) {
491  ReComputePathDeletion(path);
492  return ret;
493  }
494 
495  if (ReComputePathAdd(path))
496  ret = true;
497 
498  return ret;
499 }
500 
502  AgentPath **path_ptr, AgentRouteKey *key,
503  AgentRouteData *data, bool route_added) {
504  bool ret = false;
505  // Update route level attributes first
506  if (data && data->UpdateRoute(this))
507  ret = true;
508 
509  AgentRoute::Trace event;
510  AgentPath *path = FindPathUsingKeyData(key, data);
511  // Allocate path if not yet present
512  if (path == NULL) {
513  path = data->CreateAgentPath(key->peer(), this);
514  InsertPath(path);
515  data->AddChangePath(table->agent(), path, this);
516  std::string origin_vn_name = path->dest_vn_name();
517  set_origin_vn_name(origin_vn_name);
518  ret = true;
519  event = AgentRoute::ADD_PATH;
520  } else {
521  bool ecmp = path->path_preference().is_ecmp();
522  if (data->AddChangePath(table->agent(), path, this))
523  ret = true;
524 
525  // Transition from ECMP to non-ECMP should result in removal of member
526  // from ECMP path
527  if (ecmp && ecmp != path->path_preference().is_ecmp()) {
528  ReComputePathDeletion(path);
529  }
530  event = AgentRoute::CHANGE_PATH;
531  }
532 
533  // Trace log for path add/change
534  RouteInfo rt_info;
535  FillTrace(rt_info, event, path);
536  OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info);
537 
538  if (path->RouteNeedsSync())
539  ret |= Sync();
540 
541  if (route_added) {
542  table->EvaluateUnresolvedRoutes();
543  table->EvaluateUnresolvedNH();
544  }
545 
546  // Do necessary recompute on addition of path
547  if (ReComputePathAdd(path))
548  ret = true;
549 
550  *path_ptr = path;
551  return ret;
552 }
553 
554 // Handle DELETE operation for a route. Deletes path created by peer in key.
555 // Ideally only peer match is required in path however for few cases
556 // more than peer comparision be required.
558  AgentRouteKey *key, AgentRouteData *data) {
559  assert (key->sub_op_ == AgentKey::ADD_DEL_CHANGE);
560  bool force_delete = false;
561  // If peer in key is deleted, set force_delete to true.
562  if (key->peer()->IsDeleted() || key->peer()->SkipAddChangeRequest())
563  force_delete = true;
564 
565  // In case of multicast routes, BGP can give multiple paths.
566  // So, iterate thru all paths and identify paths that can be deleted
567  for (Route::PathList::iterator it = GetPathList().begin();
568  it != GetPathList().end(); ) {
569  AgentPath *path = static_cast<AgentPath *>(it.operator->());
570  // Current path can be deleted below. Incremnt the iterator and dont
571  // use it again below
572  it++;
573 
574  if (key->peer() != path->peer())
575  continue;
576 
577  bool check_can_delete =
578  ((key->peer()->GetType() == Peer::BGP_PEER) ||
579  (key->peer()->GetType() == Peer::EVPN_ROUTING_PEER) ||
580  (key->peer()->GetType() == Peer::EVPN_PEER) ||
581  (key->peer()->GetType() == Peer::INET_EVPN_PEER));
582 
583  if (force_delete)
584  check_can_delete = false;
585 
586  // There are two ways to receive delete of BGP peer path in l2 route.
587  // First is via withdraw meesage from control node in which
588  // force_delete will be false and vxlan_id will be matched to
589  // decide.
590  // Second can be via route walkers where on peer going down or vrf
591  // delete, paths from BGP peer should be deleted irrespective of
592  // vxlan_id.
593  if (check_can_delete && data &&
594  data->CanDeletePath(table->agent(), path, this) == false) {
595  continue;
596  }
597 
598  DeletePathFromPeer(part, table, path);
599  }
600 }
601 
603  const Path *prev_front = front();
604  insert(path);
605  Sort(&AgentRouteTable::PathSelection, prev_front);
606 }
607 
609  const Path *prev_front = front();
610  remove(path);
611  Sort(&AgentRouteTable::PathSelection, prev_front);
612  return;
613 }
614 
615 // Delete all paths from BGP Peer. Delete route if no path left
617  AgentRouteTable *table) {
618  for(Route::PathList::iterator it = GetPathList().begin();
619  it != GetPathList().end();) {
620  AgentPath *path = static_cast<AgentPath *>(it.operator->());
621  it++;
622 
623  const Peer *peer = path->peer();
624  if (peer == NULL)
625  continue;
626 
627  if (peer->GetType() == Peer::BGP_PEER ||
628  peer->GetType() == Peer::EVPN_ROUTING_PEER ||
630  DeletePathFromPeer(part, table, path);
631  } else if (peer->GetType() == Peer::LOCAL_VM_PEER) {
632  // Delete LOCAL_VM_PEER paths only from routes belonging to
633  // routing VRFs
634  VrfEntry *vrf = vrf_;
635  if (vrf && vrf->routing_vrf() && (table->GetTableType() == Agent::EVPN)) {
636  DeletePathFromPeer(part, table, path);
637  }
638  }
639  }
640 
641  return true;
642 }
643 
644 // Delete path from the given peer.
645 // If all paths are deleted,
646 // delete the route and notify
647 // Else
648 // Notify the DBEntry if any path is deleted
649 //
650 // Ideally, route must be notified only when active-path is deleted,
651 // But, notification of deleting non-active path is needed in one case.
652 //
653 // For VM spawned locally, we path BGP_PEER path with higher priority than
654 // LOCAL_VM peer path. But, controller-peer needs to know deletion of
655 // LOCAL_VM path to retract the route. So, force notify deletion of any path.
657  AgentRouteTable *table, AgentPath *path) {
658 
659  RouteInfo rt_info;
660  FillTrace(rt_info, AgentRoute::DELETE_PATH, path);
661  OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info);
662 
663  if (path == NULL) {
664  return;
665  }
666 
667  // Assign path to auto-pointer to delete it on return
668  std::unique_ptr<AgentPath> path_ref(path);
669 
670  // TODO : Move this to end of delete processing?
671  // Path deletion can result in changes such as ECMP-NH, Mulitcast NH etc
672  // The algirthms expect path to be present in route still. So, do the
673  // necessary recompute before path is deleted from route
674  ReComputePathDeletion(path);
675 
676  // Store if this was active path
677  bool active_path = (GetActivePath() == path);
678  const Peer *old_active_path_peer = path->peer();
679  // Remove path from the route
680  RemovePath(path);
681 
682  // TODO : Move this code to ECMP Hash management code.
683  CompositeNH *cnh = dynamic_cast<CompositeNH *>(path->nexthop());
684  if (cnh) {
685  path->ResetEcmpHashFields();
687  table->vrf_name());
688  }
689 
690  // Delete route if no more paths
691  if (GetActivePath() == NULL) {
692  RouteInfo rt_info_del;
693  FillTrace(rt_info_del, AgentRoute::DEL, NULL);
694  OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info_del);
695  DeleteDerivedRoutes(table);
696  table->RemoveUnresolvedRoute(this); // TODO: remove this call and make changes in gw route
700  table->ProcessDelete(this);
701  part->Delete(this);
702  } else {
703  // change to support flow stickiness for ecmp paths
704  // find new active path peer
705  // if peer type is same, and it is composite NH
706  // then import previous active NH to current active path
707  // Note: Change is limited to paths of same type
708  const Peer *new_active_path_peer = GetActivePath()->peer();
709  AgentPath *new_active_path = FindPath(new_active_path_peer);
710  CompositeNH *new_cnh = NULL;
711  if (new_active_path && new_active_path->nexthop()) {
712  new_cnh =
713  dynamic_cast<CompositeNH *>(new_active_path->nexthop());
714  }
715  if (active_path &&
716  cnh && new_cnh &&
717  (old_active_path_peer->GetType() == Peer::BGP_PEER) &&
718  (new_active_path_peer->GetType() == Peer::BGP_PEER) &&
719  (cnh->composite_nh_type() == Composite::ECMP) &&
720  (new_cnh->composite_nh_type() == Composite::ECMP)) {
721  new_active_path->ImportPrevActiveNH(table->agent(), cnh);
722  }
723  // Notify deletion of path.
724  part->Notify(this);
725  UpdateDerivedRoutes(table, NULL, active_path);
726  }
727 }
728 
730  for(Route::PathList::const_iterator it = GetPathList().begin();
731  it != GetPathList().end(); it++) {
732  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
733  if (path->peer() == NULL) {
734  continue;
735  }
736  if (path->peer()->GetType() == Peer::LOCAL_PEER ||
737  path->peer()->GetType() == Peer::LINKLOCAL_PEER) {
738  return const_cast<AgentPath *>(path);
739  }
740  }
741  return NULL;
742 }
743 
745  for(Route::PathList::const_iterator it = GetPathList().begin();
746  it != GetPathList().end(); it++) {
747  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
748  if (path->peer() == NULL) {
749  continue;
750  }
751  if (path->peer()->export_to_controller()) {
752  return const_cast<AgentPath *>(path);
753  }
754 
755  if (path->peer()->GetType() == Peer::ECMP_PEER ||
756  path->peer()->GetType() == Peer::VGW_PEER ||
757  path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER ||
758  path->peer()->GetType() == Peer::MULTICAST_TOR_PEER ||
759  path->peer()->GetType() == Peer::OVS_PEER) {
760  return const_cast<AgentPath *>(path);
761  }
762  }
763  return NULL;
764 }
765 
767 // to a local composite interface
769  const NextHop *a_nh = NULL;
770 
771  if (!a_path) {
772  return false;
773  }
774 
775  a_nh = a_path->nexthop();
776  if (!a_nh) {
777  return false;
778  }
779 
780  if (a_path->peer()->export_to_controller() &&
781  a_nh->GetType() == NextHop::COMPOSITE) {
782  return true;
783  }
784 
785  if (a_path->peer()->GetType() == Peer::ECMP_PEER) {
786  return true;
787  }
788 
789  return false;
790 }
791 
793 // to a local interface
794 bool RtPathHasLocalInterface(const AgentPath* a_path) {
795  const NextHop *a_nh = NULL;
796 
797  if (!a_path) {
798  return false;
799  }
800 
801  a_nh = a_path->nexthop();
802  if (!a_nh) {
803  return false;
804  }
805 
806  if (a_path->peer()->export_to_controller() &&
807  a_nh->GetType() == NextHop::INTERFACE) {
808  return true;
809  }
810 
811  if (a_path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
812  return true;
813  }
814 
815  return false;
816 }
817 
819  const AgentPath *intf_path = NULL;
820  const AgentPath *icom_path = NULL;
821  for (Route::PathList::const_iterator it =
822  this->GetPathList().begin();
823  it != this->GetPathList().end(); it++) {
824  const AgentPath *path = static_cast<const AgentPath *>
825  (it.operator->());
826 
827  if (intf_path == NULL &&
828  RtPathHasLocalInterface(path)) {
829  intf_path = path;
830  continue;
831  }
832  if (RtPathHasInterfaceComposite(path)) {
833  icom_path = path;
834  continue;
835  }
836  }
837  if (icom_path) {
838  return icom_path;
839  }
840  if (intf_path) {
841  return intf_path;
842  }
843  return NULL;
844 }
845 
847  for(Route::PathList::const_iterator it = GetPathList().begin();
848  it != GetPathList().end(); it++) {
849  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
850  if (path->peer() == NULL) {
851  continue;
852  }
853 
854  if (path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
855  return const_cast<AgentPath *>(path);
856  }
857  }
858  return NULL;
859 }
860 
862  const AgentRouteData *data) const {
863  return FindPath(key->peer());
864 }
865 
866 AgentPath *AgentRoute::FindPath(const Peer *peer) const {
867  for(Route::PathList::const_iterator it = GetPathList().begin();
868  it != GetPathList().end(); it++) {
869  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
870  if (path->peer() == peer) {
871  return const_cast<AgentPath *>(path);
872  }
873  }
874  return NULL;
875 }
876 
877 // First path in list is always treated as active path.
879  const AgentPath *path = static_cast<const AgentPath *>(front());
880  return (path ? path->UsablePath() : NULL);
881 }
882 
884  const AgentPath *path = GetActivePath();
885  if (path == NULL)
886  return NULL;
887 
888  return path->ComputeNextHop(static_cast<AgentRouteTable *>(get_table())->
889  agent());
890 }
891 
892 uint32_t AgentRoute::GetActiveLabel() const {
893  return GetActivePath()->label();
894 };
895 
896 // If a direct route has changed, invoke a change on tunnel NH dependent on it
899  tunnel_nh_list_.begin(); iter != tunnel_nh_list_.end(); iter++) {
900 
901  NextHop *nh = static_cast<NextHop *>(iter.operator->());
903  NextHopKey *nh_key = static_cast<NextHopKey *>(key.get());
904  nh_key->sub_op_ = AgentKey::RESYNC;
905 
907  req.key = std::move(key);
908  req.data.reset(NULL);
909  Agent *agent = (static_cast<AgentRouteTable *>(get_table()))->agent();
910  agent->nexthop_table()->Enqueue(&req);
911  }
912 }
913 
914 // Enqueue request to RESYNC a route
917  req.key = GetDBRequestKey();
918  (static_cast<AgentKey *>(req.key.get()))->sub_op_ = AgentKey::RESYNC;
919  Agent *agent = (static_cast<AgentRouteTable *>(get_table()))->agent();
920  /* Setting req.data only for default route */
921  if (agent->is_l3mh() && this->ToString().compare("0.0.0.0/0") == 0) {
922  VnListType vn_list;
923  vn_list.insert(agent->fabric_vn_name());
924  req.data.reset(new Inet4UnicastGatewayRoute(
925  agent->params()->gateway_list(), agent->fabric_vrf_name(),
927  TagList(), CommunityList(),
928  true));
929  }
930  agent->fabric_inet4_unicast_table()->Enqueue(&req);
931 }
932 
933 //If a direct route get modified invariably trigger change
934 //on all dependent indirect routes, coz if a nexthop has
935 //changed we need to update the same in datapath for indirect
936 //routes
939  dependant_routes_.begin(); iter != dependant_routes_.end(); iter++) {
940  AgentRoute *rt = iter.operator->();
941  rt->EnqueueRouteResync();
942  }
943 }
944 
946  for(Route::PathList::const_iterator it = GetPathList().begin();
947  it != GetPathList().end(); it++) {
948  const AgentPath *path =
949  static_cast<const AgentPath *>(it.operator->());
950  if (path->unresolved() == true) {
951  return true;
952  }
953  }
954 
955  return false;
956 }
957 
958 // Invoke SYNC on all paths to re-evaluate NH/active state
959 bool AgentRoute::Sync(void) {
960  bool ret = false;
961  for(Route::PathList::iterator it = GetPathList().begin();
962  it != GetPathList().end(); it++) {
963  AgentPath *path = static_cast<AgentPath *>(it.operator->());
964  if (path->Sync(this) == true) {
965  if (GetActivePath() == path) {
966  ret = true;
967  }
968  }
969  }
970  return ret;
971 }
972 
974  for(Route::PathList::const_iterator it = GetPathList().begin();
975  it != GetPathList().end(); it++) {
976  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
977  if (path->peer() && path->peer()->GetType() == Peer::INET_EVPN_PEER) {
978  continue;
979  }
980  if (path->path_preference().wait_for_traffic() == true) {
981  return true;
982  }
983  }
984  return false;
985 }
986 
988  AgentPath *path, AgentRouteData *data) {
989  bool ret = data->AddChangePath(agent, path, this);
990  if (RecomputeRoutePath(agent, part, path, data)) {
991  ret = true;
992  }
993  return ret;
994 }
995 
997  AgentRoute *rt) const {
998  return (new AgentPath(peer, rt));
999 }
1000 
1002  const AgentRoute *rt) {
1004 
1005  if (agent->tsn_enabled() && !agent->forwarding_enabled()) {
1006  bool is_inet_rt = false;
1007  bool service_address = false;
1008  if ((rt->GetTableType() == Agent::INET4_UNICAST) ||
1009  (rt->GetTableType() == Agent::INET6_UNICAST)) {
1010  is_inet_rt = true;
1011  service_address = agent->params()->
1012  IsConfiguredTsnHostRoute(rt->GetAddressString());
1013  }
1014  Peer::Type type = path->peer()->GetType();
1015  bool local_route = false;
1016  if ((type == Peer::LINKLOCAL_PEER) ||
1017  (type == Peer::LOCAL_PEER))
1018  local_route = true;
1019  if (rt->FindLocalPath())
1020  local_route = true;
1021  if (is_inet_rt && (!service_address && !local_route) &&
1022  (rt->vrf()->GetName().compare(agent->fabric_vrf_name()) != 0))
1023  path->set_inactive(true);
1024  }
1025 
1026  return AddChangePathExtended(agent, path, rt);
1027 }
1028 const string &AgentRoute::dest_vn_name() const {
1029  assert(GetActivePath()->dest_vn_list().size() <= 1);
1030  return *GetActivePath()->dest_vn_list().begin();
1031 };
1032 
1033 string AgentRoute::ToString() const {
1034  return "Route Entry";
1035 }
1036 
1037 bool AgentRoute::IsLess(const DBEntry &rhs) const {
1038  int cmp = CompareTo(static_cast<const Route &>(rhs));
1039  return (cmp < 0);
1040 };
1041 
1042 uint32_t AgentRoute::vrf_id() const {
1043  return vrf_->vrf_id();
1044 }
1045 
1047  const AgentPath *path = GetActivePath();
1048  if (path == NULL) {
1049  return false;
1050  }
1051 
1052  return path->is_subnet_discard();
1053 }
1054 
1056  Agent *agent = Agent::GetInstance();
1057  PhysicalDeviceTable *table = agent->physical_device_table();
1058  CompositeNH *nh = static_cast<CompositeNH *>(path->nexthop());
1059  ComponentNHList clist = nh->component_nh_list();
1060  table->UpdateDeviceMastership(vrf()->GetName(), clist, del);
1061 }
1062 
1064  AgentPath *path,
1065  const AgentPath *local_peer_path,
1066  const AgentPath *local_vm_peer_path,
1067  bool del, uint32_t *evpn_label) {
1068  *evpn_label = MplsTable::kInvalidLabel;
1069 
1070  //EVPN label is present in two paths:
1071  // local_vm_peer(courtesy: vmi) or local_peer(courtesy: vn)
1072  // Irrespective of delete/add operation if one of them is present and is not
1073  // the affected path, then extract the label from same.
1074  // By default pick it from available path (local or local_vm).
1075  switch (path->peer()->GetType()) {
1076  case Peer::LOCAL_VM_PEER:
1077  //Use local_peer path for label
1078  if (local_peer_path) {
1079  *evpn_label = local_peer_path->label();
1080  assert(*evpn_label != MplsTable::kInvalidLabel);
1081  }
1082  break;
1083  case Peer::LOCAL_PEER:
1084  //Use local_peer path for label
1085  if (local_vm_peer_path) {
1086  *evpn_label = local_vm_peer_path->label();
1087  assert(*evpn_label != MplsTable::kInvalidLabel);
1088  }
1089  break;
1090  default:
1091  if (local_vm_peer_path) {
1092  *evpn_label = local_vm_peer_path->label();
1093  assert(*evpn_label != MplsTable::kInvalidLabel);
1094  } else if (local_peer_path) {
1095  *evpn_label = local_peer_path->label();
1096  assert(*evpn_label != MplsTable::kInvalidLabel);
1097  }
1098  break;
1099  }
1100 
1101  //Delete path evpn label if path is local_peer or local_vm_peer.
1102  //Delete fabric label if path is multicast_fabric_tree
1103  if (del) {
1104  bool delete_label = false;
1105  // On deletion of fabric path delete fabric label.
1106  // Other type of label is evpn mcast label.
1107  // EVPN label is deleted when both local peer and local_vm_peer path are
1108  // gone.
1110  delete_label = true;
1111  else if ((path->peer() == agent->local_vm_peer()) ||
1112  (path->peer() == agent->local_peer())) {
1113  if (local_peer_path == NULL &&
1114  local_vm_peer_path == NULL) {
1115  delete_label = true;
1116  //Reset evpn label to invalid as it is freed
1117  if (*evpn_label == path->label()) {
1118  *evpn_label = MplsTable::kInvalidLabel;
1119  }
1120  }
1121  }
1122  if (delete_label) {
1123  agent->mpls_table()->FreeLabel(path->label(),
1124  vrf()->GetName());
1125  //Reset path label to invalid as it is freed
1127  }
1128  return;
1129  }
1130 
1131  // Currently other than evpn label no other multicast path requires dynamic
1132  // allocation so return.
1133  if ((path != local_peer_path) && (path != local_vm_peer_path))
1134  return;
1135 
1136  // Path already has label, return.
1137  if (path->label() != MplsTable::kInvalidLabel) {
1138  if (*evpn_label == MplsTable::kInvalidLabel) {
1139  *evpn_label = path->label();
1140  }
1141  return;
1142  }
1143 
1144  // If this is the first time i.e. local_peer has come with no local_vm_peer
1145  // and vice versa then allocate label.
1146  // If its not then we should have valid evpn label calculated above.
1147  if (*evpn_label == MplsTable::kInvalidLabel) {
1148  // XOR use - we shud never reach here when both are NULL or set.
1149  // Only one should be present.
1150  assert((local_vm_peer_path != NULL) ^ (local_peer_path != NULL));
1151  // Allocate route label with discard nh, nh in label gets updated
1152  // after composite-nh is created.
1153  DiscardNHKey key;
1154  *evpn_label = agent->mpls_table()->CreateRouteLabel(*evpn_label, &key,
1155  vrf()->GetName(),
1156  ToString());
1157  }
1158  assert(*evpn_label != MplsTable::kInvalidLabel);
1159  path->set_label(*evpn_label);
1160 }
1161 
1163  if (path->peer() == NULL) {
1164  return false;
1165  }
1166 
1167  //HACK: subnet route uses multicast NH. During IPAM delete
1168  //subnet discard is deleted. Consider this as delete of all
1169  //paths. Though this can be handled via multicast module
1170  //which can also issue delete of all peers, however
1171  //this is a temporary code as subnet route will not use
1172  //multicast NH.
1173  bool delete_all = false;
1174  if (path->is_subnet_discard() && del) {
1175  delete_all = true;
1176  }
1177 
1178  Agent *agent = (static_cast<AgentRouteTable *> (get_table()))->agent();
1179  if (del && (path->peer() == agent->multicast_peer()))
1180  return false;
1181 
1182  //Possible paths:
1183  //EVPN path - can be from multiple peers.
1184  //Fabric path - from multicast builder
1185  //Multicast peer
1186  AgentPath *multicast_peer_path = NULL;
1187  AgentPath *local_vm_peer_path = NULL;
1188  AgentPath *evpn_peer_path = NULL;
1189  AgentPath *fabric_peer_path = NULL;
1190  AgentPath *tor_peer_path = NULL;
1191  AgentPath *local_peer_path = NULL;
1192  bool tor_path = false;
1193 
1194  const CompositeNH *cnh =
1195  static_cast<const CompositeNH *>(path->nexthop());
1196  if (cnh && (cnh->composite_nh_type() == Composite::TOR)) {
1197  tor_path = true;
1198  }
1199 
1200  for (Route::PathList::iterator it = GetPathList().begin();
1201  it != GetPathList().end(); it++) {
1202  AgentPath *it_path =
1203  static_cast<AgentPath *>(it.operator->());
1204 
1205  if (delete_all && (it_path->peer() != agent->multicast_peer()))
1206  continue;
1207 
1208  //Handle deletions
1209  if (del && (path->peer() == it_path->peer())) {
1210  if (path->peer()->GetType() != Peer::BGP_PEER)
1211  continue;
1212 
1213  //Dive into comp NH type for BGP peer
1214  const CompositeNH *it_path_comp_nh =
1215  static_cast<const CompositeNH *>(it_path->nexthop());
1216  const CompositeNH *comp_nh =
1217  static_cast<const CompositeNH *>(path->nexthop());
1218  if (it_path_comp_nh->composite_nh_type() ==
1219  comp_nh->composite_nh_type())
1220  continue;
1221  }
1222 
1223  //Handle Add/Changes
1224  if (it_path->inactive())
1225  continue;
1226  if (it_path->peer() == agent->local_vm_peer()) {
1227  local_vm_peer_path = it_path;
1228  } else if (it_path->peer()->GetType() == Peer::BGP_PEER) {
1229  const CompositeNH *bgp_comp_nh =
1230  static_cast<const CompositeNH *>(it_path->nexthop());
1231  //Its a TOR NH
1232  if (bgp_comp_nh && (bgp_comp_nh->composite_nh_type() ==
1233  Composite::TOR)) {
1234  if (tor_peer_path == NULL)
1235  tor_peer_path = it_path;
1236  }
1237  //Pick up the first peer.
1238  if (bgp_comp_nh && (bgp_comp_nh->composite_nh_type() ==
1239  Composite::EVPN)) {
1240  if (evpn_peer_path == NULL)
1241  evpn_peer_path = it_path;
1242  }
1243  } else if (it_path->peer()->GetType() ==
1245  fabric_peer_path = it_path;
1246  } else if (it_path->peer() == agent->multicast_peer()) {
1247  multicast_peer_path = it_path;
1248  } else if (it_path->peer() == agent->local_peer()) {
1249  local_peer_path = it_path;
1250  }
1251  }
1252 
1253  if (tor_path) {
1254  if ((del && (tor_peer_path == NULL)) || !del) {
1255  HandleDeviceMastershipUpdate(path, del);
1256  }
1257  }
1258 
1259  uint32_t evpn_label = MplsTable::kInvalidLabel;
1260  HandleMulticastLabel(agent, path, local_peer_path, local_vm_peer_path, del,
1261  &evpn_label);
1262 
1263  //all paths are gone so delete multicast_peer path as well
1264  if ((local_vm_peer_path == NULL) &&
1265  (tor_peer_path == NULL) &&
1266  (evpn_peer_path == NULL) &&
1267  (fabric_peer_path == NULL)) {
1268  if (multicast_peer_path != NULL) {
1269  if ((evpn_label != MplsTable::kInvalidLabel) && (local_peer_path)) {
1270  // Make evpn label point to discard-nh as composite-nh gets
1271  // deleted.
1272  DiscardNHKey key;
1273  agent->mpls_table()->CreateRouteLabel(evpn_label, &key,
1274  vrf()->GetName(),
1275  ToString());
1276  }
1277  std::unique_ptr<AgentPath> path_ref(multicast_peer_path);
1278  RemovePath(multicast_peer_path);
1279  }
1280  return true;
1281  }
1282 
1283  bool learning_enabled = false;
1284  bool pbb_nh = false;
1285  uint32_t old_fabric_mpls_label = 0;
1286  if (multicast_peer_path == NULL) {
1287  multicast_peer_path = new MulticastRoutePath(agent->multicast_peer());
1288  InsertPath(multicast_peer_path);
1289  } else {
1290  //Multicast peer path can have evpn or fabric label.
1291  //Identify using isfabricmulticastlabel.
1292  if (agent->mpls_table()->
1293  IsFabricMulticastLabel(multicast_peer_path->label()))
1294  {
1295  old_fabric_mpls_label = multicast_peer_path->label();
1296  }
1297  }
1298 
1299  ComponentNHKeyList component_nh_list;
1300 
1301  if (tor_peer_path) {
1302  NextHopKey *tor_peer_key =
1303  static_cast<NextHopKey *>((tor_peer_path->
1304  ComputeNextHop(agent)->GetDBRequestKey()).release());
1305  std::unique_ptr<const NextHopKey> key4(tor_peer_key);
1306  ComponentNHKeyPtr component_nh_data4(new ComponentNHKey(0, std::move(key4)));
1307  component_nh_list.push_back(component_nh_data4);
1308  }
1309 
1310  if (evpn_peer_path) {
1311  NextHopKey *evpn_peer_key =
1312  static_cast<NextHopKey *>((evpn_peer_path->
1313  ComputeNextHop(agent)->GetDBRequestKey()).release());
1314  std::unique_ptr<const NextHopKey> key2(evpn_peer_key);
1315  ComponentNHKeyPtr component_nh_data2(new ComponentNHKey(0, std::move(key2)));
1316  component_nh_list.push_back(component_nh_data2);
1317  }
1318 
1319  if (fabric_peer_path) {
1320  NextHopKey *fabric_peer_key =
1321  static_cast<NextHopKey *>((fabric_peer_path->
1322  ComputeNextHop(agent)->GetDBRequestKey()).release());
1323  std::unique_ptr<const NextHopKey> key3(fabric_peer_key);
1324  ComponentNHKeyPtr component_nh_data3(new ComponentNHKey(0, std::move(key3)));
1325  component_nh_list.push_back(component_nh_data3);
1326  }
1327 
1328  if (local_vm_peer_path) {
1329  NextHopKey *local_vm_peer_key =
1330  static_cast<NextHopKey *>((local_vm_peer_path->
1331  ComputeNextHop(agent)->GetDBRequestKey()).release());
1332  std::unique_ptr<const NextHopKey> key4(local_vm_peer_key);
1333  ComponentNHKeyPtr component_nh_data4(new ComponentNHKey(0, std::move(key4)));
1334  component_nh_list.push_back(component_nh_data4);
1335 
1336  const CompositeNH *cnh = dynamic_cast<const CompositeNH *>(
1337  local_vm_peer_path->ComputeNextHop(agent));
1338  if (cnh && cnh->learning_enabled() == true) {
1339  learning_enabled = true;
1340  }
1341  if (cnh && cnh->pbb_nh() == true) {
1342  pbb_nh = true;
1343  }
1344  }
1345 
1347  nh_req.key.reset(new CompositeNHKey(GetMulticastCompType(),
1348  ValidateMcastSrc(), false,
1349  component_nh_list,
1350  vrf()->GetName()));
1351  nh_req.data.reset(new CompositeNHData(pbb_nh, learning_enabled,
1352  vrf()->layer2_control_word()));
1353  agent->nexthop_table()->Process(nh_req);
1354  NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
1355  FindActiveEntry(nh_req.key.get()));
1356  //NH may not get added if VRF is marked for delete. Route may be in
1357  //transition of getting deleted, skip NH modification.
1358  if (!nh) {
1359  return false;
1360  }
1361 
1362  // Since we holding a ref to composite NHs from FMG labels now,
1363  // it is possible for nh's ref to drop to zerp becuase of freelabel
1364  // call below. Hold a ref until the nh is updated in labels i.e.,
1365  // till the end of this function
1366  NextHopRef nh_ref = nh;
1367 
1368  if (nh->GetType() == NextHop::COMPOSITE) {
1369  CompositeNH *comp_nh = static_cast<CompositeNH *>(nh);
1371  }
1372 
1373  NextHopKey *key = static_cast<NextHopKey *>(nh_req.key.get());
1374  //Bake all MPLS label
1375  if (fabric_peer_path) {
1376  //Add new label
1377  agent->mpls_table()->CreateRouteLabel(fabric_peer_path->label(), key,
1378  vrf()->GetName(), ToString());
1379  //Delete Old label, in case label has changed for same peer.
1380  if (old_fabric_mpls_label != fabric_peer_path->label()) {
1381  agent->mpls_table()->FreeLabel(old_fabric_mpls_label,
1382  vrf()->GetName());
1383  }
1384  }
1385 
1386  // Rebake label with whatever comp NH has been calculated.
1387  if (evpn_label != MplsTable::kInvalidLabel) {
1388  evpn_label = agent->mpls_table()->CreateRouteLabel(evpn_label, key,
1389  vrf()->GetName(), ToString());
1390  }
1391 
1392  bool ret = false;
1393  //Identify parameters to be passed to populate multicast_peer path and
1394  //based on peer priorites for each attribute.
1395  std::string dest_vn_name = "";
1396  bool unresolved = false;
1397  uint32_t vxlan_id = 0;
1398  uint32_t tunnel_bmap = TunnelType::AllType();
1399 
1400  //Select based on priority of path peer.
1401  if (local_vm_peer_path) {
1402  dest_vn_name = local_vm_peer_path->dest_vn_name();
1403  unresolved = local_vm_peer_path->unresolved();
1404  vxlan_id = local_vm_peer_path->vxlan_id();
1405  tunnel_bmap = TunnelType::AllType();
1406  } else if (tor_peer_path) {
1407  dest_vn_name = tor_peer_path->dest_vn_name();
1408  unresolved = tor_peer_path->unresolved();
1409  vxlan_id = tor_peer_path->vxlan_id();
1410  tunnel_bmap = TunnelType::VxlanType();
1411  } else if (fabric_peer_path) {
1412  dest_vn_name = fabric_peer_path->dest_vn_name();
1413  unresolved = fabric_peer_path->unresolved();
1414  vxlan_id = fabric_peer_path->vxlan_id();
1415  tunnel_bmap = TunnelType::MplsType();
1416  } else if (evpn_peer_path) {
1417  dest_vn_name = evpn_peer_path->dest_vn_name();
1418  unresolved = evpn_peer_path->unresolved();
1419  vxlan_id = evpn_peer_path->vxlan_id();
1420  tunnel_bmap = TunnelType::VxlanType();
1421  }
1422 
1423  //By default mark label stored in multicast_peer path to be evpn label.
1424  uint32_t label = evpn_label;
1425  //Mpls label selection needs to be overridden by fabric label
1426  //if fabric peer is present.
1427  if (fabric_peer_path) {
1428  label = fabric_peer_path->label();
1429  }
1430 
1432  multicast_peer_path,
1433  dest_vn_name,
1434  unresolved,
1435  vxlan_id,
1436  label,
1437  tunnel_bmap,
1438  nh, this);
1439  MulticastRoutePath *multicast_route_path =
1440  dynamic_cast<MulticastRoutePath *>(multicast_peer_path);
1441  if (multicast_route_path) {
1442  multicast_route_path->UpdateLabels(evpn_label, label);
1443  }
1444 
1445  return ret;
1446 }
const std::string & GetName() const
Definition: peer.h:86
uint32_t vrf_id() const
AgentRouteTable * table_
Definition: agent_route.cc:57
uint64_t sequence_number_
Definition: agent_route.h:82
AgentPath * FindLocalVmPortPath() const
Definition: agent_route.cc:744
SandeshTraceBufferPtr OperDBTraceBuf
Definition: agent_route.h:208
static const std::string & GetSuffix(Agent::RouteTableType type)
Definition: agent_route.cc:99
void ResyncTunnelNextHop()
Definition: agent_route.cc:897
bool inactive() const
Definition: agent_path.h:420
void ConcurrencyCheck()
Definition: agent.cc:1044
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
void ResetEcmpHashFields()
Definition: agent_path.cc:2029
virtual bool ReComputePathDeletion(AgentPath *path)
Definition: agent_route.h:256
#define OPER_TRACE_ROUTE_ENTRY(obj, table,...)
Definition: agent_route.h:217
void UpdateEcmpHashFieldsUponRouteDelete(Agent *agent, const string &vrf_name)
Definition: nexthop.cc:2355
void Process(DBClient *client, DBRequest *req)
void Sort(Compare compare, const Path *prev_front)
Definition: route.cc:40
bool tsn_enabled() const
Definition: agent.h:1162
void EnqueueRouteResync() const
Definition: agent_route.cc:915
bool is_multicast() const
Definition: agent_route.h:77
AgentRouteTable * dependent_route_table_
Definition: agent_route.h:357
virtual bool UpdateRoute(AgentRoute *rt)
Definition: agent_route.h:74
const std::string & vrf_name() const
Definition: agent_route.cc:455
static Agent * GetInstance()
Definition: agent.h:436
void WalkTable(DBTableWalkRef walk)
Definition: db_table.cc:625
virtual bool CanDeletePath(Agent *agent, AgentPath *path, const AgentRoute *rt) const
Definition: agent_route.h:70
Definition: vrf.h:86
void AddUnresolvedRouteToTable(AgentRouteTable *table)
Definition: agent_route.cc:352
bool learning_enabled() const
Definition: nexthop.h:423
void UpdateDeviceMastership(const std::string &vrf, ComponentNHList clist, bool del)
const PathPreference & path_preference() const
Definition: agent_path.h:329
Definition: vrf.h:268
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *k) const
Definition: agent_route.cc:82
virtual const std::string GetAddressString() const =0
VrfEntry * FindVrfFromName(const string &name)
Definition: vrf.cc:873
InetUnicastAgentRouteTable * fabric_inet4_unicast_table() const
Definition: agent.h:578
NextHopTable * nexthop_table() const
Definition: agent.h:475
bool RouteNeedsSync()
Definition: agent_path.h:319
VrfEntry * vrf_
Definition: agent_route.h:351
DBTableBase * get_table() const
Definition: db_entry.cc:119
void ImportPrevActiveNH(Agent *agent, NextHop *nh)
Definition: agent_path.cc:299
DeleteActor(AgentRouteTable *rt_table)
Definition: agent_route.cc:37
bool WaitForTraffic() const
Definition: agent_route.cc:973
DBEntry * Find(const DBEntry *entry)
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge, EVPN (Type2/Type5). This base class contains common code for all types of route tables.
Definition: agent_route.h:109
virtual int CompareTo(const Route &rhs) const =0
AgentRoute * LocateRoute(DBTablePartition *part, VrfEntry *vrf, AgentRoute *rt, AgentRouteKey *key, AgentRouteData *data, bool *notify)
Definition: agent_route.cc:322
virtual ~AgentRouteTable()
Definition: agent_route.cc:78
PhysicalDeviceTable * physical_device_table() const
Definition: agent.h:628
bool is_l3mh() const
Definition: agent.h:725
bool IsDeleted() const
Definition: db_entry.h:49
bool SubOpAddChangeInput(VrfEntry *vrf, AgentRouteTable *table, AgentPath **path_ptr, AgentRouteKey *key, AgentRouteData *data, bool route_added)
Definition: agent_route.cc:501
virtual void RetryDelete()
Definition: agent_route.cc:164
const AddressList & gateway_list() const
Definition: agent_param.h:191
uint8_t sub_op_
Definition: agent_db.h:106
bool RtPathHasInterfaceComposite(const AgentPath *a_path)
returns true if the given path is not null and points
Definition: agent_route.cc:768
void EvaluateUnresolvedRoutes(void)
Definition: agent_route.cc:399
std::vector< int > SecurityGroupList
Definition: agent.h:201
bool SubOpResyncInput(VrfEntry *vrf, AgentRouteTable *table, AgentPath **path_ptr, AgentRouteKey *key, AgentRouteData *data)
Definition: agent_route.cc:468
virtual bool AddChangePathExtended(Agent *agent, AgentPath *path, const AgentRoute *rt)=0
Definition: route.h:14
const std::string & dest_vn_name() const
Definition: agent_path.h:251
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
DBTableWalkRef AllocWalker(WalkFn walk_fn, WalkCompleteFn walk_complete)
Definition: db_table.cc:613
#define AGENT_ROUTE_LOG(table, msg, route, vrf, peer_info)
Definition: agent_route.h:402
const std::string & origin_vn_name() const
Definition: agent_route.h:281
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
void DeletePathFromPeer(DBTablePartBase *part, AgentRouteTable *table, AgentPath *path)
Definition: agent_route.cc:656
static TypeBmap MplsType()
Definition: nexthop.h:312
virtual AgentPath * FindPathUsingKeyData(const AgentRouteKey *key, const AgentRouteData *data) const
Definition: agent_route.cc:861
virtual uint32_t GetActiveLabel() const
Definition: agent_route.cc:892
boost::shared_ptr< const ComponentNHKey > ComponentNHKeyPtr
Definition: nexthop.h:1639
const string & GetName() const
Definition: vrf.h:100
uint32_t vrf_id_
Definition: agent_route.h:200
LifetimeActor * deleter()
Definition: agent_route.cc:451
const std::string & dest_vn_name() const
void Delete(DBEntryBase *)
MplsTable * mpls_table() const
Definition: agent.h:510
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
virtual void RetryDelete()
Definition: vrf.cc:544
Type GetType() const
Definition: nexthop.h:405
Base class for all Route entries in agent.
Definition: agent_route.h:224
virtual KeyPtr GetDBRequestKey() const =0
virtual bool MayDelete() const
Definition: agent_route.cc:43
static bool CopyPathParameters(Agent *agent, AgentPath *path, const std::string &dest_vn_name, bool unresolved, uint32_t vxlan_id, uint32_t label, uint32_t tunnel_type, NextHop *nh, const AgentRoute *rt, bool ha_stale=false)
Definition: agent_path.cc:1417
virtual bool IsLess(const AgentPath &right) const
Definition: agent_path.cc:561
virtual AgentRoute * AllocRouteEntry(VrfEntry *vrf, bool is_multicast) const =0
virtual bool SkipAddChangeRequest() const
Definition: peer.h:89
virtual const AgentPath * UsablePath() const
Definition: agent_path.cc:574
void ReleaseWalker(DBTableWalkRef &walk)
Definition: db_table.cc:619
void RetryDelete()
Definition: lifetime.cc:71
std::vector< ComponentNHKeyPtr > ComponentNHKeyList
Definition: nexthop.h:1641
virtual bool IsDeleted() const
Definition: peer.h:91
AgentRoute * FindActiveEntry(const AgentRouteKey *key)
Definition: agent_route.cc:417
LifetimeRef< AgentRouteTable > vrf_delete_ref_
Definition: agent_route.h:203
const std::string & fabric_vrf_name() const
Definition: agent.h:903
Definition: db.h:24
const Type GetType() const
Definition: peer.h:87
const AgentPath * GetActivePath() const
Definition: agent_route.cc:878
NextHop * nexthop() const
Definition: agent_path.cc:87
bool HasUnresolvedPath()
Definition: agent_route.cc:945
virtual Agent::RouteTableType GetTableType() const =0
VrfEntry * vrf_entry() const
Definition: agent_route.cc:459
void FillTrace(RouteInfo &route, Trace event, const AgentPath *path) const
Definition: agent_path.cc:1583
VrfEntryRef vrf_entry_
Definition: agent_route.h:201
bool Sync(void)
Definition: agent_route.cc:959
uint8_t type
Definition: load_balance.h:109
virtual AgentPath * CreateAgentPath(const Peer *peer, AgentRoute *rt) const
Definition: agent_route.cc:996
void set_validate_mcast_src(bool validate_mcast_src)
Definition: nexthop.h:1846
boost::scoped_ptr< DeleteActor > deleter_
Definition: agent_route.h:202
virtual void ProcessAdd(AgentRoute *rt)
Definition: agent_route.h:127
Definition: agent.h:358
AgentRoute * FindActiveEntryNoLock(const AgentRouteKey *key)
Definition: agent_route.cc:425
Definition: path.h:10
void Reset(LifetimeActor *actor)
Definition: lifetime.h:82
Definition: vrf.h:22
AgentPath * FindLocalPath() const
Definition: agent_route.cc:729
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:883
bool is_subnet_discard() const
Definition: agent_path.h:273
uint32_t label() const
Definition: agent_path.h:264
bool allow_route_add_on_deleted_vrf() const
Definition: vrf.h:186
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
void Input(DBTablePartition *part, DBClient *client, DBRequest *req)
Definition: agent_route.cc:199
void RemovePath(AgentPath *path)
Definition: agent_route.cc:608
virtual Agent::RouteTableType GetRouteTableType()=0
DBOperation oper
Definition: db_table.h:42
void UpdateLabels(uint32_t evpn_label, uint32_t fabric_label)
Definition: agent_path.h:862
static const std::string & NullString()
Definition: agent.h:437
static TypeBmap AllType()
Definition: nexthop.h:321
const Peer * peer() const
Definition: agent_path.h:263
virtual bool ReComputeMulticastPaths(AgentPath *path, bool del)
const Peer * multicast_peer() const
Definition: agent.h:1030
static bool PathSelection(const Path &path1, const Path &path2)
Definition: agent_route.cc:93
virtual void ProcessDelete(AgentRoute *rt)
Definition: agent_route.h:126
void DeleteRouteDone(DBTable::DBTableWalkRef walk_ref, DBTableBase *base, RouteTableWalkerState *state)
Definition: agent_route.cc:147
const ComponentNHList & component_nh_list() const
Definition: nexthop.h:1869
bool AddChangePath(Agent *agent, AgentPath *path, const AgentRoute *rt)
const Peer * local_peer() const
Definition: agent.h:1022
const bool unresolved() const
Definition: agent_path.h:271
DBEntry * FindNoLock(const DBEntry *entry)
Definition: db_table.cc:462
void InsertPath(const AgentPath *path)
Definition: agent_route.cc:602
const std::string & name() const
Definition: db_table.h:110
std::vector< std::string > CommunityList
Definition: bgp_config.h:347
void set_peer_sequence_number(uint64_t sequence_number)
Definition: agent_path.h:416
COMPOSITETYPE composite_nh_type() const
Definition: nexthop.h:1842
AgentParam * params() const
Definition: agent.h:1218
void ClearDelete()
Definition: db_entry.h:48
Definition: peer.h:44
const uint32_t vrf_id() const
Definition: vrf.h:99
std::set< std::string > VnListType
Definition: agent.h:212
bool is_ecmp() const
Definition: agent_path.h:49
virtual KeyPtr GetDBRequestKey() const =0
void RemoveUnresolvedRouteFromTable(AgentRouteTable *table)
Definition: agent_route.cc:364
virtual void DeleteDerivedRoutes(AgentRouteTable *table)
Definition: agent_route.h:272
bool DelExplicitRouteWalkerCb(DBTablePartBase *part, DBEntryBase *entry)
Definition: agent_route.cc:155
virtual std::string ToString() const =0
static const uint32_t kInvalidLabel
Definition: mpls.h:101
const AgentPath * FindIntfOrCompLocalVmPortPath() const
Finds path to an interface or a composite of interfaces and returns it. The priority is given to comp...
Definition: agent_route.cc:818
VrfTable * vrf_table() const
Definition: agent.h:485
virtual bool Sync(AgentRoute *sync_route)
Definition: agent_path.cc:440
AgentPath * GetLocalVmPortPath() const
Definition: agent_route.cc:846
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
virtual void NotifyEntry(AgentRoute *entry)
Definition: agent_route.cc:174
uint32_t CreateRouteLabel(uint32_t label, const NextHopKey *nh_key, const std::string &vrf_name, const std::string &route)
Definition: mpls.cc:341
void set_inactive(bool inactive)
Definition: agent_path.h:421
const Path * front() const
Definition: route.cc:16
bool routing_vrf() const
Definition: vrf.h:223
virtual std::string ToString() const =0
virtual bool RecomputeRoutePath(Agent *agent, DBTablePartition *part, AgentPath *path, AgentRouteData *data)
Definition: agent_route.h:262
UnresolvedRouteTree unresolved_rt_tree_
Definition: agent_route.h:204
void RemoveUnresolvedRoute(const AgentRoute *rt)
Definition: agent_route.cc:412
void DeleteInput(DBTablePartition *part, AgentRouteTable *table, AgentRouteKey *key, AgentRouteData *data)
Definition: agent_route.cc:557
void RemoveUnresolvedNH(const NextHop *)
Definition: agent_route.cc:393
bool IsRPFInvalid() const
LifetimeActor * deleter()
Definition: vrf.cc:264
void Process(DBRequest &req)
Definition: nexthop.cc:367
bool ProcessPath(Agent *agent, DBTablePartition *part, AgentPath *path, AgentRouteData *data)
Definition: agent_route.cc:987
virtual bool ReComputePathAdd(AgentPath *path)
Definition: agent_route.h:257
void UpdateDependantRoutes()
Definition: agent_route.cc:937
const Peer * peer() const
Definition: agent_route.h:47
DBEntry * Find(const DBEntry *entry)
Definition: db_table.cc:469
virtual bool ValidateMcastSrc() const
Definition: agent_route.h:341
bool empty() const
Definition: db_table.h:101
const std::string & vrf_name() const
Definition: agent_route.h:46
bool forwarding_enabled() const
Definition: agent.h:1166
#define LOG(_Level, _Msg)
Definition: logging.h:33
VrfEntry * vrf() const
Definition: agent_route.h:275
AgentRouteTable * GetRouteTable(uint8_t table_type) const
Definition: vrf.cc:285
void set_label(uint32_t label)
Definition: agent_path.h:282
Agent * agent() const
Definition: agent_route.h:159
void Process(DBRequest &req)
Definition: agent_route.cc:186
bool pbb_nh() const
Definition: nexthop.h:1914
const Peer * local_vm_peer() const
Definition: agent.h:1023
AgentRouteTable(DB *db, const std::string &name)
Definition: agent_route.cc:71
bool DeleteAllBgpPath(DBTablePartBase *part, AgentRouteTable *table)
Definition: agent_route.cc:616
void AddChangeInput(DBTablePartition *part, VrfEntry *vrf, AgentRoute *rt, AgentRouteKey *key, AgentRouteData *data)
Definition: agent_route.cc:243
virtual const NextHop * ComputeNextHop(Agent *agent) const
Definition: agent_path.cc:91
bool wait_for_traffic() const
Definition: agent_path.h:42
void set_origin_vn_name(const std::string &origin_vn_name)
Definition: agent_route.h:282
virtual void Add(DBEntry *entry)
std::vector< ComponentNHPtr > ComponentNHList
Definition: nexthop.h:1637
virtual bool export_to_controller() const
Definition: peer.h:82
void EvaluateUnresolvedNH(void)
Definition: agent_route.cc:375
boost::intrusive_ptr< DBTableWalk > DBTableWalkRef
Definition: db_table.h:169
void Notify(DBEntryBase *entry)
RouteTableType
Definition: agent.h:415
void AddUnresolvedNH(const NextHop *)
Definition: agent_route.cc:389
const std::string & fabric_vn_name() const
Definition: agent.h:901
virtual void HandleDeviceMastershipUpdate(AgentPath *path, bool del)
virtual void HandleMulticastLabel(const Agent *agent, AgentPath *path, const AgentPath *local_peer_path, const AgentPath *local_vm_peer_path, bool del, uint32_t *evpn_label)
virtual AgentPath * FindPath(const Peer *peer) const
Definition: agent_route.cc:866
bool RtPathHasLocalInterface(const AgentPath *a_path)
returns true if the given path is not null and points
Definition: agent_route.cc:794
void AddUnresolvedRoute(const AgentRoute *rt)
Definition: agent_route.cc:408
bool operator()(const NextHop *nh1, const NextHop *nh2) const
Definition: agent_route.cc:64
virtual Composite::Type GetMulticastCompType()
Definition: agent_route.h:337
virtual void UpdateDerivedRoutes(AgentRouteTable *table, const AgentPath *path, bool active_path_changed)
Definition: agent_route.h:267
bool operator()(const AgentRoute *rt1, const AgentRoute *rt2) const
Definition: agent_route.cc:60
static TypeBmap VxlanType()
Definition: nexthop.h:311
UnresolvedNHTree unresolved_nh_tree_
Definition: agent_route.h:205
void insert(const Path *path)
Definition: route.cc:24
void ManagedDelete()
Definition: agent_route.cc:135
uint32_t vxlan_id() const
Definition: agent_path.h:265
virtual bool IsLess(const DBEntry &rhs) const
virtual bool IsLess(const DBEntry &rhs) const
Definition: nexthop.h:378
virtual Agent::RouteTableType GetTableType() const =0
Type
Definition: peer.h:48
void FreeLabel(uint32_t label)
Definition: mpls.cc:267
AgentRouteTable * GetDependentTable() const
Definition: agent_path.h:432
void SetVrf(VrfEntry *vrf)
Definition: agent_route.cc:126
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
const PathList & GetPathList() const
Definition: route.h:46
boost::intrusive_ptr< NextHop > NextHopRef
Definition: agent.h:124
std::vector< int > TagList
Definition: agent.h:202