OpenSDN source code
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);
517  ret = true;
518  event = AgentRoute::ADD_PATH;
519  } else {
520  bool ecmp = path->path_preference().is_ecmp();
521  if (data->AddChangePath(table->agent(), path, this))
522  ret = true;
523 
524  // Transition from ECMP to non-ECMP should result in removal of member
525  // from ECMP path
526  if (ecmp && ecmp != path->path_preference().is_ecmp()) {
527  ReComputePathDeletion(path);
528  }
529  event = AgentRoute::CHANGE_PATH;
530  }
531 
532  // Trace log for path add/change
533  RouteInfo rt_info;
534  FillTrace(rt_info, event, path);
535  OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info);
536 
537  if (path->RouteNeedsSync())
538  ret |= Sync();
539 
540  if (route_added) {
541  table->EvaluateUnresolvedRoutes();
542  table->EvaluateUnresolvedNH();
543  }
544 
545  // Do necessary recompute on addition of path
546  if (ReComputePathAdd(path))
547  ret = true;
548 
549  *path_ptr = path;
550  return ret;
551 }
552 
553 // Handle DELETE operation for a route. Deletes path created by peer in key.
554 // Ideally only peer match is required in path however for few cases
555 // more than peer comparision be required.
557  AgentRouteKey *key, AgentRouteData *data) {
558  assert (key->sub_op_ == AgentKey::ADD_DEL_CHANGE);
559  bool force_delete = false;
560  // If peer in key is deleted, set force_delete to true.
561  if (key->peer()->IsDeleted() || key->peer()->SkipAddChangeRequest())
562  force_delete = true;
563 
564  // In case of multicast routes, BGP can give multiple paths.
565  // So, iterate thru all paths and identify paths that can be deleted
566  for (Route::PathList::iterator it = GetPathList().begin();
567  it != GetPathList().end(); ) {
568  AgentPath *path = static_cast<AgentPath *>(it.operator->());
569  // Current path can be deleted below. Incremnt the iterator and dont
570  // use it again below
571  it++;
572 
573  if (key->peer() != path->peer())
574  continue;
575 
576  bool check_can_delete =
577  ((key->peer()->GetType() == Peer::BGP_PEER) ||
578  (key->peer()->GetType() == Peer::EVPN_ROUTING_PEER) ||
579  (key->peer()->GetType() == Peer::EVPN_PEER) ||
580  (key->peer()->GetType() == Peer::INET_EVPN_PEER));
581 
582  if (force_delete)
583  check_can_delete = false;
584 
585  // There are two ways to receive delete of BGP peer path in l2 route.
586  // First is via withdraw meesage from control node in which
587  // force_delete will be false and vxlan_id will be matched to
588  // decide.
589  // Second can be via route walkers where on peer going down or vrf
590  // delete, paths from BGP peer should be deleted irrespective of
591  // vxlan_id.
592  if (check_can_delete && data &&
593  data->CanDeletePath(table->agent(), path, this) == false) {
594  continue;
595  }
596 
597  DeletePathFromPeer(part, table, path);
598  }
599 }
600 
602  const Path *prev_front = front();
603  insert(path);
604  Sort(&AgentRouteTable::PathSelection, prev_front);
605 }
606 
608  const Path *prev_front = front();
609  remove(path);
610  Sort(&AgentRouteTable::PathSelection, prev_front);
611  return;
612 }
613 
614 // Delete all paths from BGP Peer. Delete route if no path left
616  AgentRouteTable *table) {
617  for(Route::PathList::iterator it = GetPathList().begin();
618  it != GetPathList().end();) {
619  AgentPath *path = static_cast<AgentPath *>(it.operator->());
620  it++;
621 
622  const Peer *peer = path->peer();
623  if (peer == NULL)
624  continue;
625 
626  if (peer->GetType() == Peer::BGP_PEER ||
627  peer->GetType() == Peer::EVPN_ROUTING_PEER ||
629  DeletePathFromPeer(part, table, path);
630  } else if (peer->GetType() == Peer::LOCAL_VM_PEER) {
631  // Delete LOCAL_VM_PEER paths only from routes belonging to
632  // routing VRFs
633  VrfEntry *vrf = vrf_;
634  if (vrf && vrf->routing_vrf() && (table->GetTableType() == Agent::EVPN)) {
635  DeletePathFromPeer(part, table, path);
636  }
637  }
638  }
639 
640  return true;
641 }
642 
643 // Delete path from the given peer.
644 // If all paths are deleted,
645 // delete the route and notify
646 // Else
647 // Notify the DBEntry if any path is deleted
648 //
649 // Ideally, route must be notified only when active-path is deleted,
650 // But, notification of deleting non-active path is needed in one case.
651 //
652 // For VM spawned locally, we path BGP_PEER path with higher priority than
653 // LOCAL_VM peer path. But, controller-peer needs to know deletion of
654 // LOCAL_VM path to retract the route. So, force notify deletion of any path.
656  AgentRouteTable *table, AgentPath *path) {
657 
658  RouteInfo rt_info;
659  FillTrace(rt_info, AgentRoute::DELETE_PATH, path);
660  OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info);
661 
662  if (path == NULL) {
663  return;
664  }
665 
666  // Assign path to auto-pointer to delete it on return
667  std::unique_ptr<AgentPath> path_ref(path);
668 
669  // TODO : Move this to end of delete processing?
670  // Path deletion can result in changes such as ECMP-NH, Mulitcast NH etc
671  // The algirthms expect path to be present in route still. So, do the
672  // necessary recompute before path is deleted from route
673  ReComputePathDeletion(path);
674 
675  // Store if this was active path
676  bool active_path = (GetActivePath() == path);
677  const Peer *old_active_path_peer = path->peer();
678  // Remove path from the route
679  RemovePath(path);
680 
681  // TODO : Move this code to ECMP Hash management code.
682  CompositeNH *cnh = dynamic_cast<CompositeNH *>(path->nexthop());
683  if (cnh) {
684  path->ResetEcmpHashFields();
686  table->vrf_name());
687  }
688 
689  // Delete route if no more paths
690  if (GetActivePath() == NULL) {
691  RouteInfo rt_info_del;
692  FillTrace(rt_info_del, AgentRoute::DEL, NULL);
693  OPER_TRACE_ROUTE_ENTRY(Route, table, rt_info_del);
694  DeleteDerivedRoutes(table);
695  table->RemoveUnresolvedRoute(this); // TODO: remove this call and make changes in gw route
699  table->ProcessDelete(this);
700  part->Delete(this);
701  } else {
702  // change to support flow stickiness for ecmp paths
703  // find new active path peer
704  // if peer type is same, and it is composite NH
705  // then import previous active NH to current active path
706  // Note: Change is limited to paths of same type
707  const Peer *new_active_path_peer = GetActivePath()->peer();
708  AgentPath *new_active_path = FindPath(new_active_path_peer);
709  CompositeNH *new_cnh = NULL;
710  if (new_active_path && new_active_path->nexthop()) {
711  new_cnh =
712  dynamic_cast<CompositeNH *>(new_active_path->nexthop());
713  }
714  if (active_path &&
715  cnh && new_cnh &&
716  (old_active_path_peer->GetType() == Peer::BGP_PEER) &&
717  (new_active_path_peer->GetType() == Peer::BGP_PEER) &&
718  (cnh->composite_nh_type() == Composite::ECMP) &&
719  (new_cnh->composite_nh_type() == Composite::ECMP)) {
720  new_active_path->ImportPrevActiveNH(table->agent(), cnh);
721  }
722  // Notify deletion of path.
723  part->Notify(this);
724  UpdateDerivedRoutes(table, NULL, active_path);
725  }
726 }
727 
729  for(Route::PathList::const_iterator it = GetPathList().begin();
730  it != GetPathList().end(); it++) {
731  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
732  if (path->peer() == NULL) {
733  continue;
734  }
735  if (path->peer()->GetType() == Peer::LOCAL_PEER ||
736  path->peer()->GetType() == Peer::LINKLOCAL_PEER) {
737  return const_cast<AgentPath *>(path);
738  }
739  }
740  return NULL;
741 }
742 
744  for(Route::PathList::const_iterator it = GetPathList().begin();
745  it != GetPathList().end(); it++) {
746  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
747  if (path->peer() == NULL) {
748  continue;
749  }
750  if (path->peer()->export_to_controller()) {
751  return const_cast<AgentPath *>(path);
752  }
753 
754  if (path->peer()->GetType() == Peer::ECMP_PEER ||
755  path->peer()->GetType() == Peer::VGW_PEER ||
756  path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER ||
757  path->peer()->GetType() == Peer::MULTICAST_TOR_PEER ||
758  path->peer()->GetType() == Peer::OVS_PEER) {
759  return const_cast<AgentPath *>(path);
760  }
761  }
762  return NULL;
763 }
764 
766 // to a local composite interface
768  const NextHop *a_nh = NULL;
769 
770  if (!a_path) {
771  return false;
772  }
773 
774  a_nh = a_path->nexthop();
775  if (!a_nh) {
776  return false;
777  }
778 
779  if (a_path->peer()->export_to_controller() &&
780  a_nh->GetType() == NextHop::COMPOSITE) {
781  return true;
782  }
783 
784  if (a_path->peer()->GetType() == Peer::ECMP_PEER) {
785  return true;
786  }
787 
788  return false;
789 }
790 
792 // to a local interface
793 bool RtPathHasLocalInterface(const AgentPath* a_path) {
794  const NextHop *a_nh = NULL;
795 
796  if (!a_path) {
797  return false;
798  }
799 
800  a_nh = a_path->nexthop();
801  if (!a_nh) {
802  return false;
803  }
804 
805  if (a_path->peer()->export_to_controller() &&
806  a_nh->GetType() == NextHop::INTERFACE) {
807  return true;
808  }
809 
810  if (a_path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
811  return true;
812  }
813 
814  return false;
815 }
816 
818  const AgentPath *intf_path = NULL;
819  const AgentPath *icom_path = NULL;
820  for (Route::PathList::const_iterator it =
821  this->GetPathList().begin();
822  it != this->GetPathList().end(); it++) {
823  const AgentPath *path = static_cast<const AgentPath *>
824  (it.operator->());
825 
826  if (intf_path == NULL &&
827  RtPathHasLocalInterface(path)) {
828  intf_path = path;
829  continue;
830  }
831  if (RtPathHasInterfaceComposite(path)) {
832  icom_path = path;
833  continue;
834  }
835  }
836  if (icom_path) {
837  return icom_path;
838  }
839  if (intf_path) {
840  return intf_path;
841  }
842  return NULL;
843 }
844 
846  for(Route::PathList::const_iterator it = GetPathList().begin();
847  it != GetPathList().end(); it++) {
848  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
849  if (path->peer() == NULL) {
850  continue;
851  }
852 
853  if (path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
854  return const_cast<AgentPath *>(path);
855  }
856  }
857  return NULL;
858 }
859 
861  const AgentRouteData *data) const {
862  return FindPath(key->peer());
863 }
864 
865 AgentPath *AgentRoute::FindPath(const Peer *peer) const {
866  for(Route::PathList::const_iterator it = GetPathList().begin();
867  it != GetPathList().end(); it++) {
868  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
869  if (path->peer() == peer) {
870  return const_cast<AgentPath *>(path);
871  }
872  }
873  return NULL;
874 }
875 
876 // First path in list is always treated as active path.
878  const AgentPath *path = static_cast<const AgentPath *>(front());
879  return (path ? path->UsablePath() : NULL);
880 }
881 
883  const AgentPath *path = GetActivePath();
884  if (path == NULL)
885  return NULL;
886 
887  return path->ComputeNextHop(static_cast<AgentRouteTable *>(get_table())->
888  agent());
889 }
890 
891 uint32_t AgentRoute::GetActiveLabel() const {
892  return GetActivePath()->label();
893 };
894 
895 // If a direct route has changed, invoke a change on tunnel NH dependent on it
898  tunnel_nh_list_.begin(); iter != tunnel_nh_list_.end(); iter++) {
899 
900  NextHop *nh = static_cast<NextHop *>(iter.operator->());
902  NextHopKey *nh_key = static_cast<NextHopKey *>(key.get());
903  nh_key->sub_op_ = AgentKey::RESYNC;
904 
906  req.key = std::move(key);
907  req.data.reset(NULL);
908  Agent *agent = (static_cast<AgentRouteTable *>(get_table()))->agent();
909  agent->nexthop_table()->Enqueue(&req);
910  }
911 }
912 
913 // Enqueue request to RESYNC a route
916  req.key = GetDBRequestKey();
917  (static_cast<AgentKey *>(req.key.get()))->sub_op_ = AgentKey::RESYNC;
918  Agent *agent = (static_cast<AgentRouteTable *>(get_table()))->agent();
919  /* Setting req.data only for default route */
920  if (agent->is_l3mh() && this->ToString().compare("0.0.0.0/0") == 0) {
921  VnListType vn_list;
922  vn_list.insert(agent->fabric_vn_name());
923  req.data.reset(new Inet4UnicastGatewayRoute(
924  agent->params()->gateway_list(), agent->fabric_vrf_name(),
926  TagList(), CommunityList(),
927  true));
928  }
929  agent->fabric_inet4_unicast_table()->Enqueue(&req);
930 }
931 
932 //If a direct route get modified invariably trigger change
933 //on all dependent indirect routes, coz if a nexthop has
934 //changed we need to update the same in datapath for indirect
935 //routes
938  dependant_routes_.begin(); iter != dependant_routes_.end(); iter++) {
939  AgentRoute *rt = iter.operator->();
940  rt->EnqueueRouteResync();
941  }
942 }
943 
945  for(Route::PathList::const_iterator it = GetPathList().begin();
946  it != GetPathList().end(); it++) {
947  const AgentPath *path =
948  static_cast<const AgentPath *>(it.operator->());
949  if (path->unresolved() == true) {
950  return true;
951  }
952  }
953 
954  return false;
955 }
956 
957 // Invoke SYNC on all paths to re-evaluate NH/active state
958 bool AgentRoute::Sync(void) {
959  bool ret = false;
960  for(Route::PathList::iterator it = GetPathList().begin();
961  it != GetPathList().end(); it++) {
962  AgentPath *path = static_cast<AgentPath *>(it.operator->());
963  if (path->Sync(this) == true) {
964  if (GetActivePath() == path) {
965  ret = true;
966  }
967  }
968  }
969  return ret;
970 }
971 
973  for(Route::PathList::const_iterator it = GetPathList().begin();
974  it != GetPathList().end(); it++) {
975  const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
976  if (path->peer() && path->peer()->GetType() == Peer::INET_EVPN_PEER) {
977  continue;
978  }
979  if (path->path_preference().wait_for_traffic() == true) {
980  return true;
981  }
982  }
983  return false;
984 }
985 
987  AgentPath *path, AgentRouteData *data) {
988  bool ret = data->AddChangePath(agent, path, this);
989  if (RecomputeRoutePath(agent, part, path, data)) {
990  ret = true;
991  }
992  return ret;
993 }
994 
996  AgentRoute *rt) const {
997  return (new AgentPath(peer, rt));
998 }
999 
1001  const AgentRoute *rt) {
1003 
1004  if (agent->tsn_enabled() && !agent->forwarding_enabled()) {
1005  bool is_inet_rt = false;
1006  bool service_address = false;
1007  if ((rt->GetTableType() == Agent::INET4_UNICAST) ||
1008  (rt->GetTableType() == Agent::INET6_UNICAST)) {
1009  is_inet_rt = true;
1010  service_address = agent->params()->
1011  IsConfiguredTsnHostRoute(rt->GetAddressString());
1012  }
1013  Peer::Type type = path->peer()->GetType();
1014  bool local_route = false;
1015  if ((type == Peer::LINKLOCAL_PEER) ||
1016  (type == Peer::LOCAL_PEER))
1017  local_route = true;
1018  if (rt->FindLocalPath())
1019  local_route = true;
1020  if (is_inet_rt && (!service_address && !local_route) &&
1021  (rt->vrf()->GetName().compare(agent->fabric_vrf_name()) != 0))
1022  path->set_inactive(true);
1023  }
1024 
1025  return AddChangePathExtended(agent, path, rt);
1026 }
1027 const string &AgentRoute::dest_vn_name() const {
1028  assert(GetActivePath()->dest_vn_list().size() <= 1);
1029  return *GetActivePath()->dest_vn_list().begin();
1030 };
1031 
1032 string AgentRoute::ToString() const {
1033  return "Route Entry";
1034 }
1035 
1036 bool AgentRoute::IsLess(const DBEntry &rhs) const {
1037  int cmp = CompareTo(static_cast<const Route &>(rhs));
1038  return (cmp < 0);
1039 };
1040 
1041 uint32_t AgentRoute::vrf_id() const {
1042  return vrf_->vrf_id();
1043 }
1044 
1046  const AgentPath *path = GetActivePath();
1047  if (path == NULL) {
1048  return false;
1049  }
1050 
1051  return path->is_subnet_discard();
1052 }
1053 
1055  Agent *agent = Agent::GetInstance();
1056  PhysicalDeviceTable *table = agent->physical_device_table();
1057  CompositeNH *nh = static_cast<CompositeNH *>(path->nexthop());
1058  ComponentNHList clist = nh->component_nh_list();
1059  table->UpdateDeviceMastership(vrf()->GetName(), clist, del);
1060 }
1061 
1063  AgentPath *path,
1064  const AgentPath *local_peer_path,
1065  const AgentPath *local_vm_peer_path,
1066  bool del, uint32_t *evpn_label) {
1067  *evpn_label = MplsTable::kInvalidLabel;
1068 
1069  //EVPN label is present in two paths:
1070  // local_vm_peer(courtesy: vmi) or local_peer(courtesy: vn)
1071  // Irrespective of delete/add operation if one of them is present and is not
1072  // the affected path, then extract the label from same.
1073  // By default pick it from available path (local or local_vm).
1074  switch (path->peer()->GetType()) {
1075  case Peer::LOCAL_VM_PEER:
1076  //Use local_peer path for label
1077  if (local_peer_path) {
1078  *evpn_label = local_peer_path->label();
1079  assert(*evpn_label != MplsTable::kInvalidLabel);
1080  }
1081  break;
1082  case Peer::LOCAL_PEER:
1083  //Use local_peer path for label
1084  if (local_vm_peer_path) {
1085  *evpn_label = local_vm_peer_path->label();
1086  assert(*evpn_label != MplsTable::kInvalidLabel);
1087  }
1088  break;
1089  default:
1090  if (local_vm_peer_path) {
1091  *evpn_label = local_vm_peer_path->label();
1092  assert(*evpn_label != MplsTable::kInvalidLabel);
1093  } else if (local_peer_path) {
1094  *evpn_label = local_peer_path->label();
1095  assert(*evpn_label != MplsTable::kInvalidLabel);
1096  }
1097  break;
1098  }
1099 
1100  //Delete path evpn label if path is local_peer or local_vm_peer.
1101  //Delete fabric label if path is multicast_fabric_tree
1102  if (del) {
1103  bool delete_label = false;
1104  // On deletion of fabric path delete fabric label.
1105  // Other type of label is evpn mcast label.
1106  // EVPN label is deleted when both local peer and local_vm_peer path are
1107  // gone.
1109  delete_label = true;
1110  else if ((path->peer() == agent->local_vm_peer()) ||
1111  (path->peer() == agent->local_peer())) {
1112  if (local_peer_path == NULL &&
1113  local_vm_peer_path == NULL) {
1114  delete_label = true;
1115  //Reset evpn label to invalid as it is freed
1116  if (*evpn_label == path->label()) {
1117  *evpn_label = MplsTable::kInvalidLabel;
1118  }
1119  }
1120  }
1121  if (delete_label) {
1122  agent->mpls_table()->FreeLabel(path->label(),
1123  vrf()->GetName());
1124  //Reset path label to invalid as it is freed
1126  }
1127  return;
1128  }
1129 
1130  // Currently other than evpn label no other multicast path requires dynamic
1131  // allocation so return.
1132  if ((path != local_peer_path) && (path != local_vm_peer_path))
1133  return;
1134 
1135  // Path already has label, return.
1136  if (path->label() != MplsTable::kInvalidLabel) {
1137  if (*evpn_label == MplsTable::kInvalidLabel) {
1138  *evpn_label = path->label();
1139  }
1140  return;
1141  }
1142 
1143  // If this is the first time i.e. local_peer has come with no local_vm_peer
1144  // and vice versa then allocate label.
1145  // If its not then we should have valid evpn label calculated above.
1146  if (*evpn_label == MplsTable::kInvalidLabel) {
1147  // XOR use - we shud never reach here when both are NULL or set.
1148  // Only one should be present.
1149  assert((local_vm_peer_path != NULL) ^ (local_peer_path != NULL));
1150  // Allocate route label with discard nh, nh in label gets updated
1151  // after composite-nh is created.
1152  DiscardNHKey key;
1153  *evpn_label = agent->mpls_table()->CreateRouteLabel(*evpn_label, &key,
1154  vrf()->GetName(),
1155  ToString());
1156  }
1157  assert(*evpn_label != MplsTable::kInvalidLabel);
1158  path->set_label(*evpn_label);
1159 }
1160 
1162  if (path->peer() == NULL) {
1163  return false;
1164  }
1165 
1166  //HACK: subnet route uses multicast NH. During IPAM delete
1167  //subnet discard is deleted. Consider this as delete of all
1168  //paths. Though this can be handled via multicast module
1169  //which can also issue delete of all peers, however
1170  //this is a temporary code as subnet route will not use
1171  //multicast NH.
1172  bool delete_all = false;
1173  if (path->is_subnet_discard() && del) {
1174  delete_all = true;
1175  }
1176 
1177  Agent *agent = (static_cast<AgentRouteTable *> (get_table()))->agent();
1178  if (del && (path->peer() == agent->multicast_peer()))
1179  return false;
1180 
1181  //Possible paths:
1182  //EVPN path - can be from multiple peers.
1183  //Fabric path - from multicast builder
1184  //Multicast peer
1185  AgentPath *multicast_peer_path = NULL;
1186  AgentPath *local_vm_peer_path = NULL;
1187  AgentPath *evpn_peer_path = NULL;
1188  AgentPath *fabric_peer_path = NULL;
1189  AgentPath *tor_peer_path = NULL;
1190  AgentPath *local_peer_path = NULL;
1191  bool tor_path = false;
1192 
1193  const CompositeNH *cnh =
1194  static_cast<const CompositeNH *>(path->nexthop());
1195  if (cnh && (cnh->composite_nh_type() == Composite::TOR)) {
1196  tor_path = true;
1197  }
1198 
1199  for (Route::PathList::iterator it = GetPathList().begin();
1200  it != GetPathList().end(); it++) {
1201  AgentPath *it_path =
1202  static_cast<AgentPath *>(it.operator->());
1203 
1204  if (delete_all && (it_path->peer() != agent->multicast_peer()))
1205  continue;
1206 
1207  //Handle deletions
1208  if (del && (path->peer() == it_path->peer())) {
1209  if (path->peer()->GetType() != Peer::BGP_PEER)
1210  continue;
1211 
1212  //Dive into comp NH type for BGP peer
1213  const CompositeNH *it_path_comp_nh =
1214  static_cast<const CompositeNH *>(it_path->nexthop());
1215  const CompositeNH *comp_nh =
1216  static_cast<const CompositeNH *>(path->nexthop());
1217  if (it_path_comp_nh->composite_nh_type() ==
1218  comp_nh->composite_nh_type())
1219  continue;
1220  }
1221 
1222  //Handle Add/Changes
1223  if (it_path->inactive())
1224  continue;
1225  if (it_path->peer() == agent->local_vm_peer()) {
1226  local_vm_peer_path = it_path;
1227  } else if (it_path->peer()->GetType() == Peer::BGP_PEER) {
1228  const CompositeNH *bgp_comp_nh =
1229  static_cast<const CompositeNH *>(it_path->nexthop());
1230  //Its a TOR NH
1231  if (bgp_comp_nh && (bgp_comp_nh->composite_nh_type() ==
1232  Composite::TOR)) {
1233  if (tor_peer_path == NULL)
1234  tor_peer_path = it_path;
1235  }
1236  //Pick up the first peer.
1237  if (bgp_comp_nh && (bgp_comp_nh->composite_nh_type() ==
1238  Composite::EVPN)) {
1239  if (evpn_peer_path == NULL)
1240  evpn_peer_path = it_path;
1241  }
1242  } else if (it_path->peer()->GetType() ==
1244  fabric_peer_path = it_path;
1245  } else if (it_path->peer() == agent->multicast_peer()) {
1246  multicast_peer_path = it_path;
1247  } else if (it_path->peer() == agent->local_peer()) {
1248  local_peer_path = it_path;
1249  }
1250  }
1251 
1252  if (tor_path) {
1253  if ((del && (tor_peer_path == NULL)) || !del) {
1254  HandleDeviceMastershipUpdate(path, del);
1255  }
1256  }
1257 
1258  uint32_t evpn_label = MplsTable::kInvalidLabel;
1259  HandleMulticastLabel(agent, path, local_peer_path, local_vm_peer_path, del,
1260  &evpn_label);
1261 
1262  //all paths are gone so delete multicast_peer path as well
1263  if ((local_vm_peer_path == NULL) &&
1264  (tor_peer_path == NULL) &&
1265  (evpn_peer_path == NULL) &&
1266  (fabric_peer_path == NULL)) {
1267  if (multicast_peer_path != NULL) {
1268  if ((evpn_label != MplsTable::kInvalidLabel) && (local_peer_path)) {
1269  // Make evpn label point to discard-nh as composite-nh gets
1270  // deleted.
1271  DiscardNHKey key;
1272  agent->mpls_table()->CreateRouteLabel(evpn_label, &key,
1273  vrf()->GetName(),
1274  ToString());
1275  }
1276  std::unique_ptr<AgentPath> path_ref(multicast_peer_path);
1277  RemovePath(multicast_peer_path);
1278  }
1279  return true;
1280  }
1281 
1282  bool learning_enabled = false;
1283  bool pbb_nh = false;
1284  uint32_t old_fabric_mpls_label = 0;
1285  if (multicast_peer_path == NULL) {
1286  multicast_peer_path = new MulticastRoutePath(agent->multicast_peer());
1287  InsertPath(multicast_peer_path);
1288  } else {
1289  //Multicast peer path can have evpn or fabric label.
1290  //Identify using isfabricmulticastlabel.
1291  if (agent->mpls_table()->
1292  IsFabricMulticastLabel(multicast_peer_path->label()))
1293  {
1294  old_fabric_mpls_label = multicast_peer_path->label();
1295  }
1296  }
1297 
1298  ComponentNHKeyList component_nh_list;
1299 
1300  if (tor_peer_path) {
1301  NextHopKey *tor_peer_key =
1302  static_cast<NextHopKey *>((tor_peer_path->
1303  ComputeNextHop(agent)->GetDBRequestKey()).release());
1304  std::unique_ptr<const NextHopKey> key4(tor_peer_key);
1305  ComponentNHKeyPtr component_nh_data4(new ComponentNHKey(0, std::move(key4)));
1306  component_nh_list.push_back(component_nh_data4);
1307  }
1308 
1309  if (evpn_peer_path) {
1310  NextHopKey *evpn_peer_key =
1311  static_cast<NextHopKey *>((evpn_peer_path->
1312  ComputeNextHop(agent)->GetDBRequestKey()).release());
1313  std::unique_ptr<const NextHopKey> key2(evpn_peer_key);
1314  ComponentNHKeyPtr component_nh_data2(new ComponentNHKey(0, std::move(key2)));
1315  component_nh_list.push_back(component_nh_data2);
1316  }
1317 
1318  if (fabric_peer_path) {
1319  NextHopKey *fabric_peer_key =
1320  static_cast<NextHopKey *>((fabric_peer_path->
1321  ComputeNextHop(agent)->GetDBRequestKey()).release());
1322  std::unique_ptr<const NextHopKey> key3(fabric_peer_key);
1323  ComponentNHKeyPtr component_nh_data3(new ComponentNHKey(0, std::move(key3)));
1324  component_nh_list.push_back(component_nh_data3);
1325  }
1326 
1327  if (local_vm_peer_path) {
1328  NextHopKey *local_vm_peer_key =
1329  static_cast<NextHopKey *>((local_vm_peer_path->
1330  ComputeNextHop(agent)->GetDBRequestKey()).release());
1331  std::unique_ptr<const NextHopKey> key4(local_vm_peer_key);
1332  ComponentNHKeyPtr component_nh_data4(new ComponentNHKey(0, std::move(key4)));
1333  component_nh_list.push_back(component_nh_data4);
1334 
1335  const CompositeNH *cnh = dynamic_cast<const CompositeNH *>(
1336  local_vm_peer_path->ComputeNextHop(agent));
1337  if (cnh && cnh->learning_enabled() == true) {
1338  learning_enabled = true;
1339  }
1340  if (cnh && cnh->pbb_nh() == true) {
1341  pbb_nh = true;
1342  }
1343  }
1344 
1346  nh_req.key.reset(new CompositeNHKey(GetMulticastCompType(),
1347  ValidateMcastSrc(), false,
1348  component_nh_list,
1349  vrf()->GetName()));
1350  nh_req.data.reset(new CompositeNHData(pbb_nh, learning_enabled,
1351  vrf()->layer2_control_word()));
1352  agent->nexthop_table()->Process(nh_req);
1353  NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
1354  FindActiveEntry(nh_req.key.get()));
1355  //NH may not get added if VRF is marked for delete. Route may be in
1356  //transition of getting deleted, skip NH modification.
1357  if (!nh) {
1358  return false;
1359  }
1360 
1361  // Since we holding a ref to composite NHs from FMG labels now,
1362  // it is possible for nh's ref to drop to zerp becuase of freelabel
1363  // call below. Hold a ref until the nh is updated in labels i.e.,
1364  // till the end of this function
1365  NextHopRef nh_ref = nh;
1366 
1367  if (nh->GetType() == NextHop::COMPOSITE) {
1368  CompositeNH *comp_nh = static_cast<CompositeNH *>(nh);
1370  }
1371 
1372  NextHopKey *key = static_cast<NextHopKey *>(nh_req.key.get());
1373  //Bake all MPLS label
1374  if (fabric_peer_path) {
1375  //Add new label
1376  agent->mpls_table()->CreateRouteLabel(fabric_peer_path->label(), key,
1377  vrf()->GetName(), ToString());
1378  //Delete Old label, in case label has changed for same peer.
1379  if (old_fabric_mpls_label != fabric_peer_path->label()) {
1380  agent->mpls_table()->FreeLabel(old_fabric_mpls_label,
1381  vrf()->GetName());
1382  }
1383  }
1384 
1385  // Rebake label with whatever comp NH has been calculated.
1386  if (evpn_label != MplsTable::kInvalidLabel) {
1387  evpn_label = agent->mpls_table()->CreateRouteLabel(evpn_label, key,
1388  vrf()->GetName(), ToString());
1389  }
1390 
1391  bool ret = false;
1392  //Identify parameters to be passed to populate multicast_peer path and
1393  //based on peer priorites for each attribute.
1394  std::string dest_vn_name = "";
1395  bool unresolved = false;
1396  uint32_t vxlan_id = 0;
1397  uint32_t tunnel_bmap = TunnelType::AllType();
1398 
1399  //Select based on priority of path peer.
1400  if (local_vm_peer_path) {
1401  dest_vn_name = local_vm_peer_path->dest_vn_name();
1402  unresolved = local_vm_peer_path->unresolved();
1403  vxlan_id = local_vm_peer_path->vxlan_id();
1404  tunnel_bmap = TunnelType::AllType();
1405  } else if (tor_peer_path) {
1406  dest_vn_name = tor_peer_path->dest_vn_name();
1407  unresolved = tor_peer_path->unresolved();
1408  vxlan_id = tor_peer_path->vxlan_id();
1409  tunnel_bmap = TunnelType::VxlanType();
1410  } else if (fabric_peer_path) {
1411  dest_vn_name = fabric_peer_path->dest_vn_name();
1412  unresolved = fabric_peer_path->unresolved();
1413  vxlan_id = fabric_peer_path->vxlan_id();
1414  tunnel_bmap = TunnelType::MplsType();
1415  } else if (evpn_peer_path) {
1416  dest_vn_name = evpn_peer_path->dest_vn_name();
1417  unresolved = evpn_peer_path->unresolved();
1418  vxlan_id = evpn_peer_path->vxlan_id();
1419  tunnel_bmap = TunnelType::VxlanType();
1420  }
1421 
1422  //By default mark label stored in multicast_peer path to be evpn label.
1423  uint32_t label = evpn_label;
1424  //Mpls label selection needs to be overridden by fabric label
1425  //if fabric peer is present.
1426  if (fabric_peer_path) {
1427  label = fabric_peer_path->label();
1428  }
1429 
1431  multicast_peer_path,
1432  dest_vn_name,
1433  unresolved,
1434  vxlan_id,
1435  label,
1436  tunnel_bmap,
1437  nh, this);
1438  MulticastRoutePath *multicast_route_path =
1439  dynamic_cast<MulticastRoutePath *>(multicast_peer_path);
1440  if (multicast_route_path) {
1441  multicast_route_path->UpdateLabels(evpn_label, label);
1442  }
1443 
1444  return ret;
1445 }
std::vector< int > TagList
Definition: agent.h:202
boost::intrusive_ptr< NextHop > NextHopRef
Definition: agent.h:124
std::vector< int > SecurityGroupList
Definition: agent.h:201
std::set< std::string > VnListType
Definition: agent.h:212
bool RtPathHasInterfaceComposite(const AgentPath *a_path)
returns true if the given path is not null and points
Definition: agent_route.cc:767
bool RtPathHasLocalInterface(const AgentPath *a_path)
returns true if the given path is not null and points
Definition: agent_route.cc:793
#define AGENT_ROUTE_LOG(table, msg, route, vrf, peer_info)
Definition: agent_route.h:413
#define OPER_TRACE_ROUTE_ENTRY(obj, table,...)
Definition: agent_route.h:217
std::vector< std::string > CommunityList
Definition: bgp_config.h:347
const AddressList & gateway_list() const
Definition: agent_param.h:191
void set_label(uint32_t label)
Definition: agent_path.h:282
void ResetEcmpHashFields()
Definition: agent_path.cc:2029
virtual bool Sync(AgentRoute *sync_route)
Definition: agent_path.cc:440
bool RouteNeedsSync()
Definition: agent_path.h:319
const VnListType & dest_vn_list() const
Definition: agent_path.h:258
void set_inactive(bool inactive)
Definition: agent_path.h:421
void ImportPrevActiveNH(Agent *agent, NextHop *nh)
Definition: agent_path.cc:299
NextHop * nexthop() const
Definition: agent_path.cc:87
bool is_subnet_discard() const
Definition: agent_path.h:273
AgentRouteTable * GetDependentTable() const
Definition: agent_path.h:432
virtual bool IsLess(const AgentPath &right) const
Definition: agent_path.cc:561
void set_peer_sequence_number(uint64_t sequence_number)
Definition: agent_path.h:416
const PathPreference & path_preference() const
Definition: agent_path.h:329
virtual const AgentPath * UsablePath() const
Definition: agent_path.cc:574
uint32_t vxlan_id() const
Definition: agent_path.h:265
const Peer * peer() const
Definition: agent_path.h:263
const bool unresolved() const
Definition: agent_path.h:271
uint32_t label() const
Definition: agent_path.h:264
const std::string & dest_vn_name() const
Definition: agent_path.h:251
virtual const NextHop * ComputeNextHop(Agent *agent) const
Definition: agent_path.cc:91
bool inactive() const
Definition: agent_path.h:420
AgentRouteTable * table_
Definition: agent_route.cc:57
DeleteActor(AgentRouteTable *rt_table)
Definition: agent_route.cc:37
virtual bool MayDelete() const
Definition: agent_route.cc:43
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge,...
Definition: agent_route.h:109
void RemoveUnresolvedNH(const NextHop *)
Definition: agent_route.cc:393
void ManagedDelete()
Definition: agent_route.cc:135
bool DelExplicitRouteWalkerCb(DBTablePartBase *part, DBEntryBase *entry)
Definition: agent_route.cc:155
UnresolvedRouteTree unresolved_rt_tree_
Definition: agent_route.h:204
static bool PathSelection(const Path &path1, const Path &path2)
Definition: agent_route.cc:93
virtual void ProcessAdd(AgentRoute *rt)
Definition: agent_route.h:127
const std::string & vrf_name() const
Definition: agent_route.cc:455
void Process(DBRequest &req)
Definition: agent_route.cc:186
VrfEntryRef vrf_entry_
Definition: agent_route.h:201
Agent * agent() const
Definition: agent_route.h:159
void SetVrf(VrfEntry *vrf)
Definition: agent_route.cc:126
AgentRoute * LocateRoute(DBTablePartition *part, VrfEntry *vrf, AgentRoute *rt, AgentRouteKey *key, AgentRouteData *data, bool *notify)
Definition: agent_route.cc:322
virtual Agent::RouteTableType GetTableType() const =0
SandeshTraceBufferPtr OperDBTraceBuf
Definition: agent_route.h:208
virtual void RetryDelete()
Definition: agent_route.cc:164
virtual void ProcessDelete(AgentRoute *rt)
Definition: agent_route.h:126
LifetimeActor * deleter()
Definition: agent_route.cc:451
void DeleteRouteDone(DBTable::DBTableWalkRef walk_ref, DBTableBase *base, RouteTableWalkerState *state)
Definition: agent_route.cc:147
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *k) const
Definition: agent_route.cc:82
void AddUnresolvedRoute(const AgentRoute *rt)
Definition: agent_route.cc:408
void EvaluateUnresolvedRoutes(void)
Definition: agent_route.cc:399
boost::scoped_ptr< DeleteActor > deleter_
Definition: agent_route.h:202
LifetimeRef< AgentRouteTable > vrf_delete_ref_
Definition: agent_route.h:203
VrfEntry * vrf_entry() const
Definition: agent_route.cc:459
AgentRoute * FindActiveEntryNoLock(const AgentRouteKey *key)
Definition: agent_route.cc:425
void Input(DBTablePartition *part, DBClient *client, DBRequest *req)
Definition: agent_route.cc:199
uint32_t vrf_id_
Definition: agent_route.h:200
UnresolvedNHTree unresolved_nh_tree_
Definition: agent_route.h:205
virtual void NotifyEntry(AgentRoute *entry)
Definition: agent_route.cc:174
AgentRouteTable(DB *db, const std::string &name)
Definition: agent_route.cc:71
void EvaluateUnresolvedNH(void)
Definition: agent_route.cc:375
virtual ~AgentRouteTable()
Definition: agent_route.cc:78
static const std::string & GetSuffix(Agent::RouteTableType type)
Definition: agent_route.cc:99
void RemoveUnresolvedRoute(const AgentRoute *rt)
Definition: agent_route.cc:412
AgentRoute * FindActiveEntry(const AgentRouteKey *key)
Definition: agent_route.cc:417
void AddChangeInput(DBTablePartition *part, VrfEntry *vrf, AgentRoute *rt, AgentRouteKey *key, AgentRouteData *data)
Definition: agent_route.cc:243
void AddUnresolvedNH(const NextHop *)
Definition: agent_route.cc:389
Base class for all Route entries in agent.
Definition: agent_route.h:224
virtual int CompareTo(const Route &rhs) const =0
AgentPath * GetLocalVmPortPath() const
Definition: agent_route.cc:845
virtual void DeleteDerivedRoutes(AgentRouteTable *table)
Definition: agent_route.h:272
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:817
virtual bool ReComputeMulticastPaths(AgentPath *path, bool del)
virtual AgentPath * FindPathUsingKeyData(const AgentRouteKey *key, const AgentRouteData *data) const
Definition: agent_route.cc:860
virtual void UpdateDerivedRoutes(AgentRouteTable *table, const AgentPath *path, bool active_path_changed)
Definition: agent_route.h:267
bool IsRPFInvalid() const
VrfEntry * vrf_
Definition: agent_route.h:362
bool ProcessPath(Agent *agent, DBTablePartition *part, AgentPath *path, AgentRouteData *data)
Definition: agent_route.cc:986
void AddUnresolvedRouteToTable(AgentRouteTable *table)
Definition: agent_route.cc:352
AgentPath * FindLocalPath() const
Definition: agent_route.cc:728
void FillTrace(RouteInfo &route, Trace event, const AgentPath *path) const
Definition: agent_path.cc:1583
void ResyncTunnelNextHop()
Definition: agent_route.cc:896
virtual bool IsLess(const DBEntry &rhs) const
void InsertPath(const AgentPath *path)
Definition: agent_route.cc:601
const AgentPath * GetActivePath() const
Definition: agent_route.cc:877
virtual void HandleDeviceMastershipUpdate(AgentPath *path, bool del)
VrfEntry * vrf() const
Definition: agent_route.h:275
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)
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:882
virtual const std::string GetAddressString() const =0
virtual uint32_t GetActiveLabel() const
Definition: agent_route.cc:891
bool HasUnresolvedPath()
Definition: agent_route.cc:944
bool WaitForTraffic() const
Definition: agent_route.cc:972
void DeleteInput(DBTablePartition *part, AgentRouteTable *table, AgentRouteKey *key, AgentRouteData *data)
Definition: agent_route.cc:556
bool DeleteAllBgpPath(DBTablePartBase *part, AgentRouteTable *table)
Definition: agent_route.cc:615
bool SubOpResyncInput(VrfEntry *vrf, AgentRouteTable *table, AgentPath **path_ptr, AgentRouteKey *key, AgentRouteData *data)
Definition: agent_route.cc:468
void UpdateDependantRoutes()
Definition: agent_route.cc:936
AgentRouteTable * dependent_route_table_
Definition: agent_route.h:368
virtual bool ReComputePathAdd(AgentPath *path)
Definition: agent_route.h:257
uint32_t vrf_id() const
virtual std::string ToString() const =0
virtual KeyPtr GetDBRequestKey() const =0
bool Sync(void)
Definition: agent_route.cc:958
void RemovePath(AgentPath *path)
Definition: agent_route.cc:607
void DeletePathFromPeer(DBTablePartBase *part, AgentRouteTable *table, AgentPath *path)
Definition: agent_route.cc:655
virtual Composite::Type GetMulticastCompType()
Definition: agent_route.h:348
virtual AgentPath * FindPath(const Peer *peer) const
Definition: agent_route.cc:865
void EnqueueRouteResync() const
Definition: agent_route.cc:914
void set_origin_vn_name(const VnListType &dest_vn_list)
Definition: agent_route.h:282
virtual Agent::RouteTableType GetTableType() const =0
void RemoveUnresolvedRouteFromTable(AgentRouteTable *table)
Definition: agent_route.cc:364
bool SubOpAddChangeInput(VrfEntry *vrf, AgentRouteTable *table, AgentPath **path_ptr, AgentRouteKey *key, AgentRouteData *data, bool route_added)
Definition: agent_route.cc:501
virtual bool ValidateMcastSrc() const
Definition: agent_route.h:352
virtual bool RecomputeRoutePath(Agent *agent, DBTablePartition *part, AgentPath *path, AgentRouteData *data)
Definition: agent_route.h:262
AgentPath * FindLocalVmPortPath() const
Definition: agent_route.cc:743
virtual bool ReComputePathDeletion(AgentPath *path)
Definition: agent_route.h:256
const std::string & dest_vn_name() const
Definition: agent.h:360
AgentParam * params() const
Definition: agent.h:1226
RouteTableType
Definition: agent.h:417
@ INET4_MULTICAST
Definition: agent.h:420
@ INET6_UNICAST
Definition: agent.h:423
@ BRIDGE
Definition: agent.h:422
@ INET4_MPLS
Definition: agent.h:424
@ INET4_UNICAST
Definition: agent.h:419
@ EVPN
Definition: agent.h:421
VrfTable * vrf_table() const
Definition: agent.h:487
const Peer * local_peer() const
Definition: agent.h:1024
bool tsn_enabled() const
Definition: agent.h:1164
void ConcurrencyCheck()
Definition: agent.cc:1047
const Peer * local_vm_peer() const
Definition: agent.h:1025
const std::string & fabric_vn_name() const
Definition: agent.h:903
const Peer * multicast_peer() const
Definition: agent.h:1032
bool is_l3mh() const
Definition: agent.h:727
static const std::string & NullString()
Definition: agent.h:439
PhysicalDeviceTable * physical_device_table() const
Definition: agent.h:630
NextHopTable * nexthop_table() const
Definition: agent.h:477
static Agent * GetInstance()
Definition: agent.h:438
InetUnicastAgentRouteTable * fabric_inet4_unicast_table() const
Definition: agent.h:580
bool forwarding_enabled() const
Definition: agent.h:1168
const std::string & fabric_vrf_name() const
Definition: agent.h:905
MplsTable * mpls_table() const
Definition: agent.h:512
const ComponentNHList & component_nh_list() const
Definition: nexthop.h:1869
void UpdateEcmpHashFieldsUponRouteDelete(Agent *agent, const string &vrf_name)
Definition: nexthop.cc:2355
COMPOSITETYPE composite_nh_type() const
Definition: nexthop.h:1842
bool pbb_nh() const
Definition: nexthop.h:1914
void set_validate_mcast_src(bool validate_mcast_src)
Definition: nexthop.h:1846
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
DBTableBase * get_table() const
Definition: db_entry.cc:119
void ClearDelete()
Definition: db_entry.h:48
bool IsDeleted() const
Definition: db_entry.h:49
virtual KeyPtr GetDBRequestKey() const =0
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
bool empty() const
Definition: db_table.h:101
const std::string & name() const
Definition: db_table.h:110
void Notify(DBEntryBase *entry)
void Delete(DBEntryBase *)
void Process(DBClient *client, DBRequest *req)
virtual void Add(DBEntry *entry)
DBEntry * Find(const DBEntry *entry)
DBTableWalkRef AllocWalker(WalkFn walk_fn, WalkCompleteFn walk_complete)
Definition: db_table.cc:613
void WalkTable(DBTableWalkRef walk)
Definition: db_table.cc:625
DBEntry * Find(const DBEntry *entry)
Definition: db_table.cc:469
void ReleaseWalker(DBTableWalkRef &walk)
Definition: db_table.cc:619
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
DBEntry * FindNoLock(const DBEntry *entry)
Definition: db_table.cc:462
boost::intrusive_ptr< DBTableWalk > DBTableWalkRef
Definition: db_table.h:169
Definition: db.h:24
void RetryDelete()
Definition: lifetime.cc:71
void Reset(LifetimeActor *actor)
Definition: lifetime.h:82
void FreeLabel(uint32_t label)
Definition: mpls.cc:267
static const uint32_t kInvalidLabel
Definition: mpls.h:101
uint32_t CreateRouteLabel(uint32_t label, const NextHopKey *nh_key, const std::string &vrf_name, const std::string &route)
Definition: mpls.cc:341
void UpdateLabels(uint32_t evpn_label, uint32_t fabric_label)
Definition: agent_path.h:862
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
void Process(DBRequest &req)
Definition: nexthop.cc:367
bool learning_enabled() const
Definition: nexthop.h:423
virtual bool IsLess(const DBEntry &rhs) const
Definition: nexthop.h:378
@ COMPOSITE
Definition: nexthop.h:354
@ INTERFACE
Definition: nexthop.h:351
Type GetType() const
Definition: nexthop.h:405
bool is_ecmp() const
Definition: agent_path.h:49
bool wait_for_traffic() const
Definition: agent_path.h:42
Definition: path.h:10
Definition: peer.h:44
virtual bool IsDeleted() const
Definition: peer.h:91
const Type GetType() const
Definition: peer.h:87
Type
Definition: peer.h:48
@ LOCAL_PEER
Definition: peer.h:58
@ BGP_PEER
Definition: peer.h:51
@ EVPN_PEER
Definition: peer.h:50
@ LINKLOCAL_PEER
Definition: peer.h:53
@ VGW_PEER
Definition: peer.h:60
@ LOCAL_VM_PEER
Definition: peer.h:57
@ ECMP_PEER
Definition: peer.h:54
@ INET_EVPN_PEER
Definition: peer.h:65
@ LOCAL_VM_PORT_PEER
Definition: peer.h:56
@ OVS_PEER
Definition: peer.h:62
@ MULTICAST_FABRIC_TREE_BUILDER
Definition: peer.h:61
@ MULTICAST_TOR_PEER
Definition: peer.h:63
@ EVPN_ROUTING_PEER
Definition: peer.h:52
const std::string & GetName() const
Definition: peer.h:86
virtual bool SkipAddChangeRequest() const
Definition: peer.h:89
virtual bool export_to_controller() const
Definition: peer.h:82
void UpdateDeviceMastership(const std::string &vrf, ComponentNHList clist, bool del)
Definition: route.h:14
void Sort(Compare compare, const Path *prev_front)
Definition: route.cc:40
const PathList & GetPathList() const
Definition: route.h:46
const Path * front() const
Definition: route.cc:16
void insert(const Path *path)
Definition: route.cc:24
void remove(const Path *path)
Definition: route.cc:32
static TypeBmap VxlanType()
Definition: nexthop.h:311
static TypeBmap AllType()
Definition: nexthop.h:321
static TypeBmap MplsType()
Definition: nexthop.h:312
Definition: vrf.h:86
const string & GetName() const
Definition: vrf.h:100
bool allow_route_add_on_deleted_vrf() const
Definition: vrf.h:186
const uint32_t vrf_id() const
Definition: vrf.h:99
LifetimeActor * deleter()
Definition: vrf.cc:264
virtual void RetryDelete()
Definition: vrf.cc:544
bool routing_vrf() const
Definition: vrf.h:223
AgentRouteTable * GetRouteTable(uint8_t table_type) const
Definition: vrf.cc:285
Definition: vrf.h:268
VrfEntry * FindVrfFromName(const string &name)
Definition: vrf.cc:873
uint8_t type
Definition: load_balance.h:2
#define LOG(_Level, _Msg)
Definition: logging.h:33
std::vector< ComponentNHPtr > ComponentNHList
Definition: nexthop.h:1637
boost::shared_ptr< const ComponentNHKey > ComponentNHKeyPtr
Definition: nexthop.h:1639
std::vector< ComponentNHKeyPtr > ComponentNHKeyList
Definition: nexthop.h:1641
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
@ ADD_DEL_CHANGE
Definition: agent_db.h:98
@ RESYNC
Definition: agent_db.h:101
uint8_t sub_op_
Definition: agent_db.h:106
virtual bool UpdateRoute(AgentRoute *rt)
Definition: agent_route.h:74
virtual bool AddChangePathExtended(Agent *agent, AgentPath *path, const AgentRoute *rt)=0
virtual bool CanDeletePath(Agent *agent, AgentPath *path, const AgentRoute *rt) const
Definition: agent_route.h:70
virtual AgentPath * CreateAgentPath(const Peer *peer, AgentRoute *rt) const
Definition: agent_route.cc:995
uint64_t sequence_number_
Definition: agent_route.h:82
bool AddChangePath(Agent *agent, AgentPath *path, const AgentRoute *rt)
bool is_multicast() const
Definition: agent_route.h:77
const Peer * peer() const
Definition: agent_route.h:47
virtual Agent::RouteTableType GetRouteTableType()=0
virtual AgentRoute * AllocRouteEntry(VrfEntry *vrf, bool is_multicast) const =0
const std::string & vrf_name() const
Definition: agent_route.h:46
virtual std::string ToString() const =0
DBOperation oper
Definition: db_table.h:42
@ DB_ENTRY_DELETE
Definition: db_table.h:39
@ DB_ENTRY_ADD_CHANGE
Definition: db_table.h:38
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
bool operator()(const NextHop *nh1, const NextHop *nh2) const
Definition: agent_route.cc:64
bool operator()(const AgentRoute *rt1, const AgentRoute *rt2) const
Definition: agent_route.cc:60
Definition: vrf.h:22