OpenSDN source code
vxlan_routing_manager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/uuid/uuid_io.hpp>
6 #include <cmn/agent_cmn.h>
7 
8 #include <base/logging.h>
9 #include <oper/operdb_init.h>
10 #include <oper/route_common.h>
11 #include <oper/vrf.h>
12 #include <oper/bridge_route.h>
14 #include <oper/evpn_route.h>
15 #include <oper/agent_route.h>
17 #include <oper/vn.h>
18 #include <oper/vrf.h>
20 #include <oper/tunnel_nh.h> //for tunnel interception
21 
22 using namespace std;
23 
25  VrfEntry *vrf) {
26  inet4_table_ = vrf->GetInet4UnicastRouteTable();
27  inet6_table_ = vrf->GetInet6UnicastRouteTable();
28  evpn_table_ = vrf->GetEvpnRouteTable();
29  std::string nm4 = std::string("vxlan_lstnr.") + inet4_table_->name();
30  std::string nm6 = std::string("vxlan_lstnr.") + inet6_table_->name();
31  std::string nme = std::string("vxlan_lstnr.") + evpn_table_->name();
32 
33  inet4_id_ = inet4_table_->
34  Register(boost::bind(&VxlanRoutingManager::RouteNotify,
35  mgr, _1, _2), nm4);
36  inet6_id_ = inet6_table_->
37  Register(boost::bind(&VxlanRoutingManager::RouteNotify,
38  mgr, _1, _2), nm6);
39  evpn_id_ = evpn_table_->
40  Register(boost::bind(&VxlanRoutingManager::RouteNotify,
41  mgr, _1, _2), nme);
42 }
43 
45  evpn_table_->Unregister(evpn_id_);
46  inet4_table_->Unregister(inet4_id_);
47  inet6_table_->Unregister(inet6_id_);
48 }
49 
51  vmi_list_(), is_routing_vn_(false),
52  logical_router_uuid_(boost::uuids::nil_uuid()), mgr_(mgr) {
53 }
54 
56 }
57 
58 void VxlanRoutingVnState::AddVmi(const VnEntry *vn, const VmInterface *vmi) {
59  if (vmi->logical_router_uuid() == boost::uuids::nil_uuid()) {
60  LOG(ERROR, "Error in VxlanRoutingManager::AddVmi"
61  << ", vmi->logical_router_uuid() == boost::uuids::nil_uuid()");
62  assert(vmi->logical_router_uuid() != boost::uuids::nil_uuid());
63  }
64  VmiListIter it = vmi_list_.find(vmi);
65  if (it != vmi_list_.end()) {
66  return;
67  }
68 
69  vmi_list_.insert(vmi);
70  if ((logical_router_uuid_ != vmi->logical_router_uuid()) &&
71  (*(vmi_list_.begin()) == vmi)) {
72  mgr_->BridgeVnNotify(vn, this);
73  }
74 }
75 
76 void VxlanRoutingVnState::DeleteVmi(const VnEntry *vn, const VmInterface *vmi) {
77  VmiListIter it = vmi_list_.find(vmi);
78  if (it == vmi_list_.end()) {
79  return;
80  }
81  vmi_list_.erase(vmi);
82  mgr_->BridgeVnNotify(vn, this);
83 }
84 
86  vn_entry_(NULL), logical_router_uuid_(boost::uuids::nil_uuid()) {
87 }
88 
90 }
91 
93  if (vmi_list_.size() == 0)
94  return boost::uuids::nil_uuid();
95 
96  return (*(vmi_list_.begin()))->logical_router_uuid();
97 }
98 
100  VxlanRoutingManager *mgr, Agent *agent) :
101  AgentRouteWalker(name, agent), mgr_(mgr) {
102 }
103 
105 }
106 
107 // Only take notification of bridge inet routes.
108 // Change in them will trigger change in rest.
110  DBEntryBase *e) {
111  // Now route leaking is triggered by changes in the Inet table of
112  // a bridge VRF instance
113  const InetUnicastRouteEntry *inet_rt =
114  dynamic_cast<const InetUnicastRouteEntry*>(e);
115  if (inet_rt) {
116  const VrfEntry *vrf = inet_rt->vrf();
117  if (vrf && vrf->vn() && !mgr_->IsRoutingVrf(vrf)) {
118  mgr_->InetRouteNotify(partition, e);
119  }
120  }
121  return true;
122 }
123 
125  mgr_(mgr), lr_vrf_info_map_(), vn_lr_set_(),
126  inet4_table_walker_(), inet6_table_walker_() {
127 }
128 
130 }
131 
133  InetUnicastAgentRouteTable *inet4_table,
134  InetUnicastAgentRouteTable *inet6_table) {
135  // Inet 4
136  {
137  DBTable::DBTableWalkRef walk_ref;
138  InetTableWalker::iterator it = inet4_table_walker_.find(inet4_table);
139  if (it == inet4_table_walker_.end()) {
140  walk_ref = inet4_table->
141  AllocWalker(boost::bind(&VxlanRoutingManager::RouteNotify,
142  mgr_, _1, _2),
144  this, _1, _2));
145  inet4_table_walker_[inet4_table] = walk_ref;
146  } else {
147  walk_ref = it->second;
148  }
149  inet4_table->WalkAgain(walk_ref);
150  //Every time walk is issued for bridge table revisit subnet routes
151  mgr_->HandleSubnetRoute(inet4_table->vrf_entry());
152  }
153  // Inet 6
154  {
155  DBTable::DBTableWalkRef walk_ref;
156  InetTableWalker::iterator it = inet6_table_walker_.find(inet6_table);
157  if (it == inet6_table_walker_.end()) {
158  walk_ref = inet6_table->
159  AllocWalker(boost::bind(&VxlanRoutingManager::RouteNotify,
160  mgr_, _1, _2),
162  this, _1, _2));
163  inet6_table_walker_[inet6_table] = walk_ref;
164  } else {
165  walk_ref = it->second;
166  }
167  inet6_table->WalkAgain(walk_ref);
168  //Every time walk is issued for bridge table revisit subnet routes
169  mgr_->HandleSubnetRoute(inet6_table->vrf_entry());
170  }
171 }
172 
174  const VnEntry *vn, bool update, bool withdraw) {
175  if (lr_uuid == boost::uuids::nil_uuid())
176  return;
177  VxlanRoutingVrfMapper::RoutedVrfInfo &routing_vrf_info =
178  lr_vrf_info_map_[lr_uuid];
179  const VrfEntry *routing_vrf = routing_vrf_info.routing_vrf_;
180  DBTable::DBTableWalkRef walk_ref;
181 
182  if (withdraw) {
183  InetUnicastAgentRouteTable *inet4_table = nullptr;
184  InetUnicastAgentRouteTable *inet6_table = nullptr;
185  const VrfEntry *bridge_vrf = vn->GetVrf();
186  if (bridge_vrf && routing_vrf) {
187  inet4_table = bridge_vrf->GetInet4UnicastRouteTable();
188  inet6_table = bridge_vrf->GetInet6UnicastRouteTable();
189  }
190  if (inet4_table) {
191  walk_ref = inet4_table->
192  AllocWalker(boost::bind(
194  mgr_, routing_vrf, _1, _2),
196  this, _1, _2));
197  inet4_table->WalkAgain(walk_ref);
198  }
199  if (inet6_table) {
200  walk_ref = inet6_table->
201  AllocWalker(boost::bind(
203  mgr_, routing_vrf, _1, _2),
205  this, _1, _2));
206  inet6_table->WalkAgain(walk_ref);
207  }
208  } else {
209  EvpnAgentRouteTable *evpn_table = NULL;
210  if (routing_vrf) {
211  evpn_table =
212  static_cast<EvpnAgentRouteTable *>(
213  routing_vrf->GetEvpnRouteTable());
214  }
215  if (!evpn_table) {
216  return;
217  }
218 
219  walk_ref = evpn_table->
220  AllocWalker(boost::bind(&VxlanRoutingManager::LeakRoutesIntoBridgeTables,
221  mgr_, _1, _2, lr_uuid, vn, update),
223  this, _1, _2));
224  evpn_table->WalkAgain(walk_ref);
225  }
226 }
227 
229  DBTableBase *partition) {
230  if (walk_ref.get() != NULL)
231  (static_cast<DBTable *>(partition))->ReleaseWalker(walk_ref);
232 }
233 
235  DBTableBase *partition) {
236  const InetUnicastAgentRouteTable *table = static_cast<const InetUnicastAgentRouteTable *>
237  (walk_ref->table());
238  InetTableWalker::iterator it = inet4_table_walker_.find(table);
239  if(it == inet4_table_walker_.end()) {
240  LOG(ERROR, "Error in VxlanRoutingManager::BridgeInet4RouteWalkDone"
241  << ", it == inet4_table_walker_.end()");
242  assert(it != inet4_table_walker_.end());
243  }
244  inet4_table_walker_.erase(it);
245 }
246 
248  DBTableBase *partition) {
249  const InetUnicastAgentRouteTable *table = static_cast<const InetUnicastAgentRouteTable *>
250  (walk_ref->table());
251  InetTableWalker::iterator it = inet6_table_walker_.find(table);
252  if(it == inet6_table_walker_.end()){
253  LOG(ERROR, "Error in VxlanRoutingManager::BridgeInet6RouteWalkDone"
254  << ", it == inet6_table_walker_.end()");
255  assert(it != inet6_table_walker_.end());
256  }
257 
258  inet6_table_walker_.erase(it);
259 }
260 
262 (const VxlanRoutingVrfMapper::RoutedVrfInfo &routed_vrf_info)
263 {
264  // Start walk on all l3 tables
266  routed_vrf_info.bridge_vn_list_.begin();
267  while (it != routed_vrf_info.bridge_vn_list_.end()) {
268  const VnEntry *vn = static_cast<const VnEntry *>(*it);
269  const VrfEntry *vrf = vn->GetVrf();
270  if (vrf) {
271  InetUnicastAgentRouteTable *inet4_table =
272  static_cast<InetUnicastAgentRouteTable *>
273  (vrf->GetInet4UnicastRouteTable());
274  InetUnicastAgentRouteTable *inet6_table =
275  static_cast<InetUnicastAgentRouteTable *>
276  (vrf->GetInet6UnicastRouteTable());
277  if (!inet4_table || !inet6_table)
278  continue;
279  WalkBridgeInetTables(inet4_table, inet6_table);
280  }
281  it++;
282  }
283 }
284 
286 (const VnEntry *vn) {
287  VnLrSetIter it = vn_lr_set_.find(vn);
288  if (it != vn_lr_set_.end()) {
289  return GetRoutingVrfUsingUuid(it->second);
290  }
291  return NULL;
292 }
293 
295 (const AgentRoute *rt) {
297 }
298 
300 (const boost::uuids::uuid &lr_uuid) {
301  LrVrfInfoMapIter it = lr_vrf_info_map_.find(lr_uuid);
302  if (it != lr_vrf_info_map_.end()) {
303  return it->second.routing_vrf_;
304  }
305  return NULL;
306 }
307 
309 (const AgentRoute *rt) {
310  using boost::uuids::nil_uuid;
311 
313  return rt->vrf()->vn()->logical_router_uuid();
314  }
315 
316  const VnEntry* rt_vn = rt->vrf()->vn();
317  if (!rt_vn) {
318  return nil_uuid();
319  }
320 
321  const VxlanRoutingVnState *vn_state =
322  dynamic_cast<const VxlanRoutingVnState *>(rt_vn->
323  GetAgentDBEntryState(mgr_->vn_listener_id()));
324  if ((vn_state == NULL) || (vn_state->vmi_list_.size() == 0)) {
325  return nil_uuid();
326  }
327 
328  return vn_state->logical_router_uuid_;
329 }
330 
331 // Invoked everytime when a vrf is pulled out of use.
332 // Holds on object till all bridge and routing vrf are gone.
334  if ((it->second.routing_vrf_ == NULL) &&
335  (it->second.bridge_vn_list_.size() == 0)) {
336  lr_vrf_info_map_.erase(it);
337  }
338 }
339 
342 
347  agent_(agent), walker_(), vn_listener_id_(),
348  vrf_listener_id_(), vmi_listener_id_(), vrf_mapper_(this) {
349  //routing_vrf_interface_peer_ = agent_->evpn_routing_peer();
352 }
353 
355 }
356 
358  // Walker to go through routes in bridge evpn tables.
359  walker_.reset(new VxlanRoutingRouteWalker("VxlanRoutingManager", this,
360  agent_));
362  RegisterWalker(static_cast<AgentRouteWalker *>(walker_.get()));
363 
364  // Register all listener ids.
367  this, _1, _2));
369  boost::bind(&VxlanRoutingManager::VrfNotify, this, _1, _2));
371  boost::bind(&VxlanRoutingManager::VmiNotify, this, _1, _2));
372 }
373 
379  ReleaseWalker(walker_.get());
380  walker_.reset(NULL);
381 }
382 
395  VnEntry *vn = dynamic_cast<VnEntry *>(e);
396  VxlanRoutingVnState *vn_state = dynamic_cast<VxlanRoutingVnState *>
398 
399  if (vn->IsDeleted() && vn_state != NULL) {
400  if (vn_state->is_routing_vn_) {
401  RoutingVnNotify(vn, vn_state);
402  } else {
403  BridgeVnNotify(vn, vn_state);
404  }
405 
406  //Delete State
407  vn->ClearState(partition->parent(), vn_listener_id_);
408  delete vn_state;
409  return;
410  }
411 
412  // if the VN had been deleted previously
413  if (!vn_state && vn->IsDeleted()) {
414  return;
415  }
416 
417  if (!vn_state) {
418  vn_state = new VxlanRoutingVnState(this);
419  vn->SetState(partition->parent(), vn_listener_id_, vn_state);
420  }
421 
422  if (vn->vxlan_routing_vn()) {
423  vn_state->is_routing_vn_ = vn->vxlan_routing_vn();
424  }
425 
426  vn_state->vrf_ref_ = vn->GetVrf();
427  if (vn_state->is_routing_vn_) {
428  vn_state->logical_router_uuid_ = vn->logical_router_uuid();
429  RoutingVnNotify(vn, vn_state);
430  } else {
431  BridgeVnNotify(vn, vn_state);
432  }
433 
434  return;
435 }
436 
438  VxlanRoutingVnState *vn_state) {
439  using boost::uuids::nil_uuid;
440 
441  if (vn_state->vmi_list_.size() == 0) {
442  vn_state->logical_router_uuid_ = nil_uuid();
443  }
444 
445  VxlanRoutingVnState::VmiListIter it = vn_state->vmi_list_.begin();
446  while (it != vn_state->vmi_list_.end()) {
447  vn_state->logical_router_uuid_ = (*it)->logical_router_uuid();
448  if ((*it)->logical_router_uuid() != nil_uuid()) {
449  return;
450  }
451  //Delete VMI with no lr uuid, vmi update will handle rest.
452  vn_state->vmi_list_.erase(it);
453  if (vn_state->vmi_list_.size() == 0) {
454  vn_state->logical_router_uuid_ = nil_uuid();
455  return;
456  }
457  it = vn_state->vmi_list_.begin();
458  }
459  return;
460 }
461 
463  VxlanRoutingVnState *vn_state) {
464  using boost::uuids::nil_uuid;
465 
466  if (vn->logical_router_uuid() != nil_uuid()) {
467  return;
468  }
469 
473  bool withdraw = false;
474  bool update = true;
475 
476  // Update lr uuid in case some vmi is deleted or added.
477  UpdateLogicalRouterUuid(vn, vn_state);
478  if (vn->IsDeleted() || (vn->GetVrf() == NULL)) {
479  withdraw = true;
480  update = false;
481  }
482 
483  if (it != vrf_mapper_.vn_lr_set_.end() &&
484  (it->second != vn_state->logical_router_uuid_) &&
485  (vn_state->logical_router_uuid_ != nil_uuid())) {
486  withdraw = true;
487  }
488 
489  if (vn_state->logical_router_uuid_ == nil_uuid()) {
490  withdraw = true;
491  update = false;
492  }
493 
494  if (it != vrf_mapper_.vn_lr_set_.end()) {
495  routing_info_it = vrf_mapper_.lr_vrf_info_map_.find(it->second);
496  }
497 
498  // Handles deletion case
499  if (withdraw) {
500  if (routing_info_it != vrf_mapper_.lr_vrf_info_map_.end()) {
502  routing_info_it->second.bridge_vn_list_.find(vn);
503  std::string vrf_name = "";
504  if (routing_info_it->second.bridge_vrf_names_list_.count(vn) == 1) {
505  vrf_name = routing_info_it->second.bridge_vrf_names_list_.at(vn);
506  DeleteSubnetRoute(vn, vrf_name);
507  }
508  if (br_it != routing_info_it->second.bridge_vn_list_.end()) {
509  vrf_mapper_.WalkRoutingVrf(it->second, vn, false, true);
510  routing_info_it->second.bridge_vn_list_.erase(br_it);
511  routing_info_it->second.bridge_vrf_names_list_.erase(vn);
512  }
513  // Trigger delete of logical router
514  vrf_mapper_.TryDeleteLogicalRouter(routing_info_it);
515  }
516  vrf_mapper_.vn_lr_set_.erase(vn);
517  }
518 
519  if (update) {
521  if (vrf_mapper_.vn_lr_set_[vn] == nil_uuid()) {
522  return;
523  }
524 
527  lr_vrf_info.bridge_vn_list_.insert(vn);
528  if (vn->GetVrf())
529  lr_vrf_info.bridge_vrf_names_list_[vn] = vn->GetVrf()->GetName();
530  vrf_mapper_.WalkRoutingVrf(vrf_mapper_.vn_lr_set_[vn], vn, true, false);
531  }
532 
533  // Without vrf walks cant be scheduled
534  if (!vn_state->vrf_ref_.get()) {
535  return;
536  }
537 
538  // Walk Evpn table if withdraw or update was done
539  if (update || withdraw) {
540  InetUnicastAgentRouteTable *inet4_table =
541  static_cast<InetUnicastAgentRouteTable *>(vn_state->vrf_ref_.get()->
542  GetInet4UnicastRouteTable());
543  InetUnicastAgentRouteTable *inet6_table =
544  static_cast<InetUnicastAgentRouteTable *>(vn_state->vrf_ref_.get()->
545  GetInet6UnicastRouteTable());
546  if (inet4_table && inet6_table) {
547  vrf_mapper_.WalkBridgeInetTables(inet4_table, inet6_table);
548  }
549  }
550  return;
551 }
552 
554  if (rt_vrf == nullptr) {
555  return;
556  }
557  // Loop over all EVPN routes and delete them
558 
559  EvpnAgentRouteTable *evpn_table = dynamic_cast<EvpnAgentRouteTable *>
560  (rt_vrf->GetEvpnRouteTable());
561  if (evpn_table == nullptr) {
562  return;
563  }
564  EvpnRouteEntry *c_entry = dynamic_cast<EvpnRouteEntry *>
565  (evpn_table->GetTablePartition(0)->GetFirst());
566 
567  const std::string vrf_name = rt_vrf->GetName();
568  const uint32_t ethernet_tag = 0;
569  const MacAddress mac_addr;
570  while (c_entry != nullptr) {
571  const IpAddress &prefix_ip = c_entry->prefix_address();
572  const uint8_t plen = c_entry->prefix_length();
573  const AgentPath *rt_active_path = c_entry->GetActivePath();
574  const Peer *rt_active_peer = rt_active_path->peer();
575  const auto &path_list = c_entry->GetPathList();
576 
577  // Compute next entry in advance
578  if (c_entry != nullptr && c_entry->get_table_partition()) {
579  c_entry = dynamic_cast<EvpnRouteEntry *>
580  (c_entry->get_table_partition()->GetNext(c_entry));
581  } else {
582  break;
583  }
584 
586  vrf_name, prefix_ip, plen,
587  nullptr);
589  vrf_name, prefix_ip, plen,
590  nullptr);
591 
592  if (rt_active_peer->GetType() != Peer::BGP_PEER) {
593  // Delete routes originated from bridge networks
594  EvpnAgentRouteTable::DeleteReq(rt_active_peer,
595  vrf_name,
596  mac_addr,
597  prefix_ip,
598  plen,
599  ethernet_tag, // ethernet_tag = 0 for Type5
600  nullptr);
601  } else {
602  for (auto &path_ref : path_list) {
604  static_cast<const AgentPath*>
605  (&path_ref)->peer(),
606  vrf_name,
607  mac_addr,
608  prefix_ip,
609  plen,
610  ethernet_tag, // ethernet_tag = 0 for Type5
611  nullptr);
612  }
613  }
614  }
615 }
616 
618  VxlanRoutingVnState *vn_state) {
619 
620  bool withdraw = false;
621  bool update = false;
623 
624  if (vn->IsDeleted() ||
625  (vn->GetVrf() == NULL) ||
626  (vn_state->is_routing_vn_ == false)) {
627  update = false;
628  withdraw = true;
629  } else {
630  update = true;
631  if (it != vrf_mapper_.vn_lr_set_.end()) {
632  // LR uuid changed, so withdraw from old and add new.
633  if (it->second != vn_state->logical_router_uuid_) {
634  withdraw = true;
635  }
636  }
637  }
638 
639  if (withdraw && (it != vrf_mapper_.vn_lr_set_.end())) {
641  vrf_mapper_.lr_vrf_info_map_.find(it->second);
642  // Delete only if parent VN is same as notified VN coz it may so happen
643  // that some other VN has taken the ownership of this LR and
644  // notification of same came before this VN.
645  if (routing_info_it != vrf_mapper_.lr_vrf_info_map_.end()) {
646  if (routing_info_it->second.routing_vn_ == vn) {
648  routing_info_it->second.routing_vrf_);
649  // Routing VN/VRF
650  // Reset parent vn and routing vrf
651  routing_info_it->second.routing_vn_ = nullptr;
652  routing_info_it->second.routing_vrf_ = nullptr;
653  }
654  // Trigger delete of logical router
655  vrf_mapper_.TryDeleteLogicalRouter(routing_info_it);
656  }
657  vrf_mapper_.vn_lr_set_.erase(it);
658  }
659 
660  if (update) {
661  if (vn_state->logical_router_uuid_ == boost::uuids::nil_uuid()) {
662  return;
663  }
664 
665  if (it == vrf_mapper_.vn_lr_set_.end()) {
667  }
668 
669  VxlanRoutingVrfMapper::RoutedVrfInfo &routed_vrf_info =
671  // Take the ownership of LR
672  routed_vrf_info.routing_vn_ = vn;
673  if (routed_vrf_info.routing_vrf_ != vn->GetVrf()) {
674  routed_vrf_info.routing_vrf_ = vn->GetVrf();
675  vrf_mapper_.WalkBridgeVrfs(routed_vrf_info);
676  }
677  }
678 }
679 
685  DBEntryBase *e) {
686  VrfEntry *vrf = static_cast<VrfEntry *>(e);
687  if (vrf->GetName().compare(agent_->fabric_vrf_name()) == 0)
688  return;
689  if (vrf->GetName().compare(agent_->fabric_policy_vrf_name()) == 0)
690  return;
691 
692  VxlanRoutingState *state = dynamic_cast<VxlanRoutingState *>(vrf->
693  GetState(partition->parent(), vrf_listener_id_));
694  if (vrf->IsDeleted()) {
695  if (state) {
696  vrf->ClearState(partition->parent(), vrf_listener_id_);
697  delete state;
698  }
699  } else {
700  // Vrf was added/changed.
701  if (!state) {
702  state = new VxlanRoutingState(this, vrf);
703  vrf->SetState(partition->parent(), vrf_listener_id_, state);
704  }
705  if (vrf->vn() && vrf->vn()->vxlan_routing_vn()) {
706  vrf->set_routing_vrf(true);
707  }
708  }
709 }
710 
712  DBEntryBase *e) {
713  VmInterface *vmi = dynamic_cast<VmInterface *>(e);
714  if (!vmi) {
715  return;
716  }
717 
718  VnEntry *vn = vmi->GetNonConstVn();
719  VxlanRoutingVnState *vn_state = NULL;
720  VxlanRoutingVmiState *vmi_state = dynamic_cast<VxlanRoutingVmiState *>(vmi->
721  GetAgentDBEntryState(vmi_listener_id_));
722  if (vmi->IsDeleted() || (vn == NULL) ||
723  (vmi->logical_router_uuid() == boost::uuids::nil_uuid())) {
724  if (!vmi_state) {
725  return;
726  }
727  vn = vmi_state->vn_entry_.get();
728  vn_state = dynamic_cast<VxlanRoutingVnState *>
730  if (vn_state)
731  vn_state->DeleteVmi(vn, vmi);
732  vmi->ClearState(partition->parent(), vmi_listener_id_);
733  delete vmi_state;
734  return;
735  }
736 
737  if ((vmi->device_type() != VmInterface::VMI_ON_LR) ||
738  (vmi->vmi_type() != VmInterface::ROUTER)) {
739  return;
740  }
741 
742  if (vmi->logical_router_uuid() == boost::uuids::nil_uuid()) {
743  return;
744  }
745 
746  // Without VN no point of update
747  if (!vn) {
748  return;
749  }
750 
751  if (!vmi_state) {
752  vmi_state = new VxlanRoutingVmiState();
753  vmi->SetState(partition->parent(), vmi_listener_id_, vmi_state);
754  vmi_state->vn_entry_ = vn;
755  }
756  // Update logical_router_uuid
757  vmi_state->logical_router_uuid_ = vmi->logical_router_uuid();
758 
759  // Its necessary to add state on VN so as to push VMI. VN notify can come
760  // after VMI notify.
761  VnNotify(vn->get_table_partition(), vn);
762  // Now get VN state and add/delete VMI there
763  vn_state = dynamic_cast<VxlanRoutingVnState *>
765  if (vn_state) {
766  vn_state->AddVmi(vn, vmi);
767  }
768 }
769 
770 void VxlanRoutingManager::HandleSubnetRoute(const VrfEntry *vrf, bool bridge_vrf) {
771  //
772  // New version
773  //
774  if (vrf->vn() && vrf->vn()->vxlan_routing_vn() == false) {
775  const VrfEntry *routing_vrf =
777  if (!routing_vrf || vrf->IsDeleted()) {
778  DeleteSubnetRoute(vrf);
779  vrf->vn()->set_lr_vrf(NULL);
780  } else {
781  UpdateSubnetRoute(vrf, routing_vrf);
782  vrf->vn()->set_lr_vrf(routing_vrf);
783  }
784  }
785 }
786 
788  const std::string& vrf_name,
789  const IpAddress& ipam_prefix,
790  const uint32_t plen) {
791  if (vn == NULL || vrf_name == std::string(""))
792  return;
793 
795 
796  if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
797  lr_it->second == boost::uuids::nil_uuid())
798  return;
799 
801  vrf_mapper_.lr_vrf_info_map_[lr_it->second];
802 
803  if (lr_vrf_info.bridge_vn_list_.size() == 0)
804  return;
805 
807  lr_vrf_info.bridge_vn_list_.begin();
808  while (it != lr_vrf_info.bridge_vn_list_.end()) {
809  if (vn == *it) {
810  it++;
811  continue;
812  }
813 
814  (*it)->GetVrf()->GetInetUnicastRouteTable(ipam_prefix)->
815  Delete(agent_->evpn_routing_peer(), (*it)->GetVrf()->GetName(),
816  ipam_prefix, plen, NULL);
817  it++;
818  }
819 }
820 
821 void VxlanRoutingManager::DeleteSubnetRoute(const VnEntry *vn, const std::string& vrf_name) {
822  if (vn == NULL || vrf_name == std::string(""))
823  return;
824  std::vector<VnIpam> bridge_vn_ipam = vn->GetVnIpam();
825 
826  if (bridge_vn_ipam.size() == 0)
827  return;
828 
830 
831  if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
832  lr_it->second == boost::uuids::nil_uuid())
833  return;
834 
836  vrf_mapper_.lr_vrf_info_map_[lr_it->second];
837 
838  if (lr_vrf_info.bridge_vn_list_.size() == 0)
839  return;
840 
842  lr_vrf_info.bridge_vn_list_.begin();
843  while (it != lr_vrf_info.bridge_vn_list_.end()) {
844  if (vn == *it) {
845  it++;
846  continue;
847  }
848 
849  for (std::vector<VnIpam>::iterator ipam_itr = bridge_vn_ipam.begin();
850  ipam_itr < bridge_vn_ipam.end(); ipam_itr++) {
851  std::string it_vrf_name = "";
852  if (lr_vrf_info.bridge_vrf_names_list_.count((*it)) == 1) {
853  it_vrf_name = lr_vrf_info.bridge_vrf_names_list_.at((*it));
854  if (it_vrf_name != std::string("")) {
856  it_vrf_name, ipam_itr->GetSubnetAddress(),
857  ipam_itr->plen);
858  }
859  }
860  }
861  std::vector<VnIpam> vn_ipam = (*it)->GetVnIpam();
862 
863  if (vn_ipam.size() == 0) {
864  it++;
865  continue;
866  }
867  for (std::vector<VnIpam>::iterator vn_ipam_itr = vn_ipam.begin();
868  vn_ipam_itr < vn_ipam.end(); vn_ipam_itr++) {
870  vrf_name, vn_ipam_itr->GetSubnetAddress(),
871  vn_ipam_itr->plen, NULL);
872  }
873  it++;
874  }
875 }
876 
877 //void VxlanRoutingManager::DeleteSubnetRoute(const VrfEntry *vrf, VnIpam *ipam) {
879  if (vrf == NULL)
880  return;
881  DeleteSubnetRoute(vrf->vn(), vrf->GetName());
882 }
883 
885  const VrfEntry *routing_vrf) {
886  if (!bridge_vrf->vn())
887  return;
888 
889  std::vector<VnIpam> bridge_vn_ipam = bridge_vrf->vn()->GetVnIpam();
890 
891  if (bridge_vn_ipam.size() == 0)
892  return;
893 
895  vrf_mapper_.vn_lr_set_.find(bridge_vrf->vn());
896 
897  if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
898  lr_it->second == boost::uuids::nil_uuid())
899  return;
900 
902  vrf_mapper_.lr_vrf_info_map_[lr_it->second];
903 
904  if (lr_vrf_info.bridge_vn_list_.size() == 0)
905  return;
906 
908  lr_vrf_info.bridge_vn_list_.begin();
909  while (it != lr_vrf_info.bridge_vn_list_.end()) {
910  if (bridge_vrf->vn() == *it) {
911  it++;
912  continue;
913  }
914 
915  for (std::vector<VnIpam>::iterator ipam_itr = bridge_vn_ipam.begin();
916  ipam_itr < bridge_vn_ipam.end(); ipam_itr++) {
918  nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
919  nh_req.data.reset(new VrfNHData(false, false, false));
920  (*it)->GetVrf()->GetInetUnicastRouteTable(ipam_itr->ip_prefix)->
921  AddEvpnRoutingRoute(ipam_itr->ip_prefix, ipam_itr->plen, routing_vrf,
924  CommunityList(),
925  PathPreference(),
926  EcmpLoadBalance(),
927  TagList(),
928  nh_req,
929  routing_vrf->vxlan_id(),
930  VnListType());
931  }
932 
933  std::vector<VnIpam> vn_ipam = (*it)->GetVnIpam();
934  for (std::vector<VnIpam>::iterator vn_ipam_itr = vn_ipam.begin();
935  vn_ipam_itr != vn_ipam.end(); vn_ipam_itr++) {
936 
938  nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
939  nh_req.data.reset(new VrfNHData(false, false, false));
940  bridge_vrf->GetInetUnicastRouteTable(vn_ipam_itr->ip_prefix)->
941  AddEvpnRoutingRouteReq(vn_ipam_itr->ip_prefix, vn_ipam_itr->plen, routing_vrf,
944  CommunityList(),
945  PathPreference(),
946  EcmpLoadBalance(),
947  TagList(),
948  nh_req,
949  routing_vrf->vxlan_id(),
950  VnListType());
951  }
952  it++;
953  }
954 }
955 
959 void VxlanRoutingManager::FillSandeshInfo(VxlanRoutingResp *resp) {
962  std::vector<VxlanRoutingMap> vr_map;
963  while (it1 != vrf_mapper_.lr_vrf_info_map_.end()) {
964  VxlanRoutingMap vxlan_routing_map;
965  vxlan_routing_map.set_logical_router_uuid(UuidToString(it1->first));
966  vxlan_routing_map.set_routing_vrf(it1->second.routing_vrf_->
967  GetName());
968  vxlan_routing_map.set_parent_routing_vn(it1->second.routing_vn_->
969  GetName());
971  it1->second.bridge_vn_list_.begin();
972  while (it2 != it1->second.bridge_vn_list_.end()) {
973  VxlanRoutingBridgeVrf bridge_vrf;
974  if ((*it2)->GetVrf()) {
975  bridge_vrf.set_bridge_vrf((*it2)->GetVrf()->GetName());
976  }
977  bridge_vrf.set_bridge_vn((*it2)->GetName());
978  vxlan_routing_map.bridge_vrfs.push_back(bridge_vrf);
979  it2++;
980  }
981  vr_map.push_back(vxlan_routing_map);
982  it1++;
983  }
984  resp->set_vr_map(vr_map);
985 }
986 
987 void VxlanRoutingReq::HandleRequest() const {
988  VxlanRoutingResp *resp = new VxlanRoutingResp();
989  Agent *agent = Agent::GetInstance();
990  VxlanRoutingManager *vxlan_routing_mgr =
991  agent->oper_db()->vxlan_routing_manager();
992  if (vxlan_routing_mgr) {
993  resp->set_context(context());
994  vxlan_routing_mgr->FillSandeshInfo(resp);
995  }
996  resp->set_more(false);
997  resp->Response();
998  return;
999 }
boost::asio::ip::address IpAddress
Definition: address.h:13
std::vector< int > TagList
Definition: agent.h:202
std::vector< int > SecurityGroupList
Definition: agent.h:201
std::set< std::string > VnListType
Definition: agent.h:212
std::vector< std::string > CommunityList
Definition: bgp_config.h:347
DBState * GetAgentDBEntryState(int listener_id)
Definition: agent_db.cc:31
const Peer * peer() const
Definition: agent_path.h:263
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:389
VrfEntry * vrf_entry() const
Definition: agent_route.cc:459
Base class for all Route entries in agent.
Definition: agent_route.h:224
const AgentPath * GetActivePath() const
Definition: agent_route.cc:877
VrfEntry * vrf() const
Definition: agent_route.h:275
Definition: agent.h:360
InterfaceTable * interface_table() const
Definition: agent.h:467
OperDB * oper_db() const
Definition: agent.cc:1016
const std::string & fabric_policy_vrf_name() const
Definition: agent.h:910
VrfTable * vrf_table() const
Definition: agent.h:487
const Peer * local_vm_export_peer() const
Definition: agent.h:1042
const Peer * vxlan_bgp_peer() const
Definition: agent.h:1030
const Peer * evpn_routing_peer() const
Definition: agent.h:1029
VnTable * vn_table() const
Definition: agent.h:497
static Agent * GetInstance()
Definition: agent.h:438
const std::string & fabric_vrf_name() const
Definition: agent.h:905
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
bool IsDeleted() const
Definition: db_entry.h:49
DBTablePartBase * get_table_partition() const
Definition: db_entry.cc:115
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
void Unregister(ListenerId listener)
Definition: db_table.cc:186
const std::string & name() const
Definition: db_table.h:110
DBTableBase * parent()
virtual DBEntryBase * GetNext(const DBEntryBase *)=0
virtual DBEntryBase * GetFirst()=0
void WalkAgain(DBTableWalkRef walk)
Definition: db_table.cc:631
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
boost::intrusive_ptr< DBTableWalk > DBTableWalkRef
Definition: db_table.h:169
static void DeleteReq(const Peer *peer, const std::string &vrf_name, const MacAddress &mac, const IpAddress &ip_addr, uint32_t plen, uint32_t ethernet_tag, AgentRouteData *data)
uint8_t prefix_length() const
!
static void Delete(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen)
static void DeleteReq(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen, AgentRouteData *data)
const boost::uuids::uuid & logical_router_uuid() const
Definition: interface.h:146
VxlanRoutingManager * vxlan_routing_manager() const
Definition: operdb_init.h:98
AgentRouteWalkerManager * agent_route_walk_manager() const
Definition: operdb_init.h:91
Definition: peer.h:45
const Type GetType() const
Definition: peer.h:88
@ BGP_PEER
Definition: peer.h:52
const std::string & GetName() const
Definition: peer.h:87
const PathList & GetPathList() const
Definition: route.h:46
VmInterface::VmiType vmi_type() const
VnEntry * GetNonConstVn() const
VmInterface::DeviceType device_type() const
Definition: vn.h:151
void set_lr_vrf(const VrfEntry *vrf)
Definition: vn.h:269
const std::vector< VnIpam > & GetVnIpam() const
Definition: vn.h:171
VrfEntry * GetVrf() const
Definition: vn.h:170
const boost::uuids::uuid & logical_router_uuid() const
Definition: vn.h:260
bool vxlan_routing_vn() const
Definition: vn.h:259
Definition: vrf.h:88
const string & GetName() const
Definition: vrf.h:102
void set_routing_vrf(bool val)
Definition: vrf.h:224
InetUnicastAgentRouteTable * GetInet4UnicastRouteTable() const
Definition: vrf.cc:319
InetUnicastAgentRouteTable * GetInet6UnicastRouteTable() const
Definition: vrf.cc:338
InetUnicastAgentRouteTable * GetInetUnicastRouteTable(const IpAddress &addr) const
Definition: vrf.cc:575
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
uint32_t vxlan_id() const
Definition: vrf.h:167
VnEntry * vn() const
Definition: vrf.h:103
This class manages routes leaking between bridge VRF instances and the routing VRF instance....
void DeleteIpamRoutes(const VnEntry *vn, const std::string &vrf_name, const IpAddress &ipam_prefix, const uint32_t plen)
Delete routes to IPAM, specified by IP prefix and prefix length.
bool LeakRoutesIntoBridgeTables(DBTablePartBase *partition, DBEntryBase *e, const boost::uuids::uuid &uuid, const VnEntry *vn, bool update=false)
Performs advertisement and deletion of routing routes (with VrfNH) in bridge VRF instances....
bool RouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Handler for changes (new/update/delete) in a route (EVPN or Inet). Main entry point for routes leakin...
void VnNotify(DBTablePartBase *partition, DBEntryBase *e)
A handler for changes (new/update/delete) in a virtual network (VnEntry class).
void HandleSubnetRoute(const VrfEntry *vrf, bool bridge_vrf=false)
Handles routing routes (with VrfNH) update in the routing VRF instance.
void BridgeVnNotify(const VnEntry *vn, VxlanRoutingVnState *vn_state)
A handler for changes (new/update/delete) in the virtual network from a bridge VRF.
void VmiNotify(DBTablePartBase *partition, DBEntryBase *e)
Handler for changes (new/update/delete) in a VMI (VmInterface class).
void RoutingVnNotify(const VnEntry *vn, VxlanRoutingVnState *vn_state)
A handler for changes (new/update/delete) in the virtual network from a routing VRF.
DBTable::ListenerId vrf_listener_id_
An ID of the listener to changes in VrfTable.
DBTable::ListenerId vn_listener_id() const
Returns the ID of the listener to changes in the VnTable.
void UpdateSubnetRoute(const VrfEntry *vrf, const VrfEntry *routing_vrf)
Updates subnet routes (actually, paths with VrfNH) in the given bridge VRF.
bool WithdrawEvpnRouteFromRoutingVrf(const VrfEntry *routing_vrf, DBTablePartBase *partition, DBEntryBase *e)
Deletes a given EVPN route from EVPN table of the routing VRF instance.
static const Peer * routing_vrf_interface_peer_
Internal data of this class.
void Shutdown()
Unregisters handlers for events associated with changes in virtual networks (VnTable class) and VRF i...
friend class VxlanRoutingRouteWalker
Friends declarations.
static const Peer * routing_vrf_vxlan_bgp_peer_
A pointer to the Peer where all BGP routes are stored.
void Register()
Registers handlers for events associated with changes in virtual networks (VnTable class) and VRF ins...
static bool IsRoutingVrf(const VrfEntry *vrf)
Determines whether the pointer to the VRF instance is of routing type.
void VrfNotify(DBTablePartBase *partition, DBEntryBase *e)
A handler for changes (new/update/delete) in a VRF instance (VrfEntry class).
Agent * agent_
A pointer to the Agent instance.
DBTable::ListenerId vn_listener_id_
An ID of the listener to changes in VnTable.
void DeleteSubnetRoute(const VrfEntry *vrf)
Deletes subnet routes (actually, paths with VrfNH) in the given bridge VRF. This function is demanded...
AgentRouteWalkerPtr walker_
A pointer to the walker to loop over INET tables in bridge VRF instances.
VxlanRoutingManager(Agent *agent)
Constructs instance of the class and links to the Agent class instance. Since only one agent class in...
virtual ~VxlanRoutingManager()
Destroys the VxlanRoutingManager instance.
void RoutingVrfDeleteAllRoutes(VrfEntry *rt_vrf)
deletes all routes in EVPN table of routing VRF
bool InetRouteNotify(DBTablePartBase *partition, DBEntryBase *e)
Routes leaking functions.
VxlanRoutingVrfMapper vrf_mapper_
A map between LR uuids and associated bridge and routing VRF instances.
void FillSandeshInfo(VxlanRoutingResp *resp)
Updates Sandesh response.
DBTable::ListenerId vmi_listener_id_
An ID of the listener to changes in InterfaceTable.
VxlanRoutingRouteWalker(const std::string &name, VxlanRoutingManager *mgr, Agent *agent)
Constructs a new instance using the given name, pointer to the VxlanRoutingManager and pointer to the...
VxlanRoutingManager * mgr_
A pointer to the VxlanRoutingManager instance.
virtual ~VxlanRoutingRouteWalker()
Destructs an instance of VxlanRoutingRouteWalker.
virtual bool RouteWalkNotify(DBTablePartBase *partition, DBEntryBase *e)
Runs route leaking process when L3 VRF instance is added/deleted or when a bridge VRF is attached / d...
LrVrfInfoMap::iterator LrVrfInfoMapIter
A typedef for iterator of LrVrfInfoMap.
const VrfEntry * GetRoutingVrfUsingUuid(const boost::uuids::uuid &lr_uuid)
Find the routing VRF instance using a given LR UUID.
void WalkBridgeVrfs(const RoutedVrfInfo &routing_vrf_info)
Walks Inet tables of all bridge VRF instances connected to a LR (given in routing_vrf_info parameter)...
InetTableWalker inet4_table_walker_
The set of walkers for Inet IPv4 tables of bridge VRF instances.
LrVrfInfoMap lr_vrf_info_map_
The map between Logical router UUID and RoutedVrfInfo.
void TryDeleteLogicalRouter(LrVrfInfoMapIter &it)
Attempts to delete the given LR.
const boost::uuids::uuid GetLogicalRouterUuidUsingRoute(const AgentRoute *rt)
Find the UUID of the LR using a given route (AgentRoute).
void BridgeInet6RouteWalkDone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition)
Handles completion of route walk in an Inet IPv6 table of a bridge VRF instance.
const VrfEntry * GetRoutingVrfUsingAgentRoute(const AgentRoute *rt)
Find the routing VRF instance using a given route (AgentRoute).
const VrfEntry * GetRoutingVrfUsingVn(const VnEntry *vn)
Find the routing VRF instance using a given virtual network.
VnLrSet vn_lr_set_
The map between pointer to VirtualNetwork (a bridge or routing virtual network connected to some LR) ...
void RoutingVrfRouteWalkDone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition)
Handles completion of route walk in the EVPN table of a routing VRF instance.
InetTableWalker inet6_table_walker_
The set of walkers for Inet IPv6 tables of bridge VRF instances.
VxlanRoutingVrfMapper(VxlanRoutingManager *mgr)
Constructs a new instance of VxlanRoutingVrfMapper using the given pointer to VxlanRoutingManager.
void BridgeInet4RouteWalkDone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition)
Handles completion of route walk in the Inet IPv4 table of a bridge VRF instance.
void WalkRoutingVrf(const boost::uuids::uuid &lr_uuid, const VnEntry *vn, bool update, bool withdraw)
Walks the EVPN table of the routing VRF instance of a given LR.
virtual ~VxlanRoutingVrfMapper()
Destroys an instance of VxlanRoutingVrfMapper().
VxlanRoutingManager * mgr_
A pointer to the VxlanRoutingManager instance.
void WalkBridgeInetTables(InetUnicastAgentRouteTable *inet4, InetUnicastAgentRouteTable *inet6)
Walks given Inet tables (IPv4 and IPv6).
VnLrSet::iterator VnLrSetIter
A typedef for iterator of VnLrSet.
#define LOG(_Level, _Msg)
Definition: logging.h:34
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
@ 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
This state tracks inet and evpn table listeners. The state establishes link between Inet tables of a ...
VxlanRoutingState(VxlanRoutingManager *mgr, VrfEntry *vrf)
Construct new instance using the given VxlanRoutingManager and VRF instance (VrfEntry).
virtual ~VxlanRoutingState()
Destroys an instance.
Tracks movement of a VmInterface amongth LRs. This is used to associate VmInterface with a LR and a V...
VnEntryRef vn_entry_
Reference (smart pointer) to the virtual network (VirtualNetwork) to which VmInterface belongs to.
virtual ~VxlanRoutingVmiState()
Destroys an instance of VxlanRoutingVmiState.
boost::uuids::uuid logical_router_uuid_
UUID of the LR to which this VmInterface is connected.
VxlanRoutingVmiState()
Constructs new instance of VxlanRoutingVmiState.
This state tracks all virtual machine interfaces (VmInterface) attached to a Logical Router (LR)....
VrfEntryRef vrf_ref_
Holds a reference to a VrfEntry when VirtualNetwork's reference stored in VrfGet() is null.
bool is_routing_vn_
Returns true when state is associated with a routing VirtualNetwork.
boost::uuids::uuid logical_router_uuid() const
Returns the UUID of the Logical Router.
void AddVmi(const VnEntry *vn, const VmInterface *vmi)
Adds a VmInterface (LR port) to a Logical Router and connects the given VirtualNetwork (to which the ...
VxlanRoutingManager * mgr_
A pointer to the instance of VxlanRoutingManager.
VxlanRoutingVnState(VxlanRoutingManager *mgr)
Constructs new instance using VxlanRoutingManager.
void DeleteVmi(const VnEntry *vn, const VmInterface *vmi)
Deletes the VmInterface from set of connected interfaces and disconnects the given VirtualNetwork fro...
virtual ~VxlanRoutingVnState()
Destroys a VxlanRoutingVnState object.
VmiList::iterator VmiListIter
A typedef for the iterator of VxlanRoutingVnState::VmiList.
boost::uuids::uuid logical_router_uuid_
A UUID of the Logical Router.
std::set< const VmInterface * > vmi_list_
A list of VmInterface (router's ports) connected to a Logical Router (LR)
The structure holds information about virtual networks connected to a logical router (LR)
BridgeVnList::iterator BridgeVnListIter
A type for iterator of the list of bridge virtual networks connected to a LR.
BridgeVnList bridge_vn_list_
The list of bridge virtual networks (VirtualNetwork) connected to a LR.
BridgeVrfNamesList bridge_vrf_names_list_
The list of bridge virtual networks (VirtualNetwork) names connected to a LR.
const VnEntry * routing_vn_
A pointer to the routing virtual network (VirtualNetwork) connected to a LR.
VrfEntry * routing_vrf_
A pointer to the routing VRF instance (L3 VRF) connected to a LR.
boost::uuids::uuid uuid
void UpdateLogicalRouterUuid(const VnEntry *vn, VxlanRoutingVnState *vn_state)