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