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  EvpnAgentRouteTable *evpn_table = NULL;
182  if (withdraw) {
183  const VrfEntry *bridge_vrf = vn->GetVrf();
184  if (bridge_vrf && routing_vrf) {
185  evpn_table =
186  static_cast<EvpnAgentRouteTable *>(
187  bridge_vrf->GetEvpnRouteTable());
188  }
189  if (!evpn_table) {
190  return;
191  }
192  walk_ref = evpn_table->
194  mgr_, routing_vrf, _1, _2),
196  this, _1, _2));
197  evpn_table->WalkAgain(walk_ref);
198  } else {
199  if (routing_vrf) {
200  evpn_table =
201  static_cast<EvpnAgentRouteTable *>(
202  routing_vrf->GetEvpnRouteTable());
203  }
204  if (!evpn_table) {
205  return;
206  }
207 
208  walk_ref = evpn_table->
209  AllocWalker(boost::bind(&VxlanRoutingManager::LeakRoutesIntoBridgeTables,
210  mgr_, _1, _2, lr_uuid, vn, update),
212  this, _1, _2));
213  evpn_table->WalkAgain(walk_ref);
214  }
215 }
216 
218  DBTableBase *partition) {
219  if (walk_ref.get() != NULL)
220  (static_cast<DBTable *>(partition))->ReleaseWalker(walk_ref);
221 }
222 
224  DBTableBase *partition) {
225  const InetUnicastAgentRouteTable *table = static_cast<const InetUnicastAgentRouteTable *>
226  (walk_ref->table());
227  InetTableWalker::iterator it = inet4_table_walker_.find(table);
228  if(it == inet4_table_walker_.end()) {
229  LOG(ERROR, "Error in VxlanRoutingManager::BridgeInet4RouteWalkDone"
230  << ", it == inet4_table_walker_.end()");
231  assert(it != inet4_table_walker_.end());
232  }
233  inet4_table_walker_.erase(it);
234 }
235 
237  DBTableBase *partition) {
238  const InetUnicastAgentRouteTable *table = static_cast<const InetUnicastAgentRouteTable *>
239  (walk_ref->table());
240  InetTableWalker::iterator it = inet6_table_walker_.find(table);
241  if(it == inet6_table_walker_.end()){
242  LOG(ERROR, "Error in VxlanRoutingManager::BridgeInet6RouteWalkDone"
243  << ", it == inet6_table_walker_.end()");
244  assert(it != inet6_table_walker_.end());
245  }
246 
247  inet6_table_walker_.erase(it);
248 }
249 
251 (const VxlanRoutingVrfMapper::RoutedVrfInfo &routed_vrf_info)
252 {
253  // Start walk on all l3 tables
255  routed_vrf_info.bridge_vn_list_.begin();
256  while (it != routed_vrf_info.bridge_vn_list_.end()) {
257  const VnEntry *vn = static_cast<const VnEntry *>(*it);
258  const VrfEntry *vrf = vn->GetVrf();
259  if (vrf) {
260  InetUnicastAgentRouteTable *inet4_table =
261  static_cast<InetUnicastAgentRouteTable *>
262  (vrf->GetInet4UnicastRouteTable());
263  InetUnicastAgentRouteTable *inet6_table =
264  static_cast<InetUnicastAgentRouteTable *>
265  (vrf->GetInet6UnicastRouteTable());
266  if (!inet4_table || !inet6_table)
267  continue;
268  WalkBridgeInetTables(inet4_table, inet6_table);
269  }
270  it++;
271  }
272 }
273 
275 (const VnEntry *vn) {
276  VnLrSetIter it = vn_lr_set_.find(vn);
277  if (it != vn_lr_set_.end()) {
278  return GetRoutingVrfUsingUuid(it->second);
279  }
280  return NULL;
281 }
282 
284 (const AgentRoute *rt) {
286 }
287 
289 (const boost::uuids::uuid &lr_uuid) {
290  LrVrfInfoMapIter it = lr_vrf_info_map_.find(lr_uuid);
291  if (it != lr_vrf_info_map_.end()) {
292  return it->second.routing_vrf_;
293  }
294  return NULL;
295 }
296 
298 (const AgentRoute *rt) {
299  using boost::uuids::nil_uuid;
300 
302  return rt->vrf()->vn()->logical_router_uuid();
303  }
304 
305  const VnEntry* rt_vn = rt->vrf()->vn();
306  if (!rt_vn) {
307  return nil_uuid();
308  }
309 
310  const VxlanRoutingVnState *vn_state =
311  dynamic_cast<const VxlanRoutingVnState *>(rt_vn->
312  GetAgentDBEntryState(mgr_->vn_listener_id()));
313  if ((vn_state == NULL) || (vn_state->vmi_list_.size() == 0)) {
314  return nil_uuid();
315  }
316 
317  return vn_state->logical_router_uuid_;
318 }
319 
320 // Invoked everytime when a vrf is pulled out of use.
321 // Holds on object till all bridge and routing vrf are gone.
323  if ((it->second.routing_vrf_ == NULL) &&
324  (it->second.bridge_vn_list_.size() == 0)) {
325  lr_vrf_info_map_.erase(it);
326  }
327 }
328 
331 
336  agent_(agent), walker_(), vn_listener_id_(),
337  vrf_listener_id_(), vmi_listener_id_(), vrf_mapper_(this) {
338  //routing_vrf_interface_peer_ = agent_->evpn_routing_peer();
341 }
342 
344 }
345 
347  // Walker to go through routes in bridge evpn tables.
348  walker_.reset(new VxlanRoutingRouteWalker("VxlanRoutingManager", this,
349  agent_));
351  RegisterWalker(static_cast<AgentRouteWalker *>(walker_.get()));
352 
353  // Register all listener ids.
356  this, _1, _2));
358  boost::bind(&VxlanRoutingManager::VrfNotify, this, _1, _2));
360  boost::bind(&VxlanRoutingManager::VmiNotify, this, _1, _2));
361 }
362 
368  ReleaseWalker(walker_.get());
369  walker_.reset(NULL);
370 }
371 
384  VnEntry *vn = dynamic_cast<VnEntry *>(e);
385  VxlanRoutingVnState *vn_state = dynamic_cast<VxlanRoutingVnState *>
387 
388  if (vn->IsDeleted() && vn_state != NULL) {
389  if (vn_state->is_routing_vn_) {
390  RoutingVnNotify(vn, vn_state);
391  } else {
392  BridgeVnNotify(vn, vn_state);
393  }
394 
395  //Delete State
396  vn->ClearState(partition->parent(), vn_listener_id_);
397  delete vn_state;
398  return;
399  }
400 
401  // if the VN had been deleted previously
402  if (!vn_state && vn->IsDeleted()) {
403  return;
404  }
405 
406  if (!vn_state) {
407  vn_state = new VxlanRoutingVnState(this);
408  vn->SetState(partition->parent(), vn_listener_id_, vn_state);
409  }
410 
411  if (vn->vxlan_routing_vn()) {
412  vn_state->is_routing_vn_ = vn->vxlan_routing_vn();
413  }
414 
415  vn_state->vrf_ref_ = vn->GetVrf();
416  if (vn_state->is_routing_vn_) {
417  vn_state->logical_router_uuid_ = vn->logical_router_uuid();
418  RoutingVnNotify(vn, vn_state);
419  } else {
420  BridgeVnNotify(vn, vn_state);
421  }
422 
423  return;
424 }
425 
427  VxlanRoutingVnState *vn_state) {
428  using boost::uuids::nil_uuid;
429 
430  if (vn_state->vmi_list_.size() == 0) {
431  vn_state->logical_router_uuid_ = nil_uuid();
432  }
433 
434  VxlanRoutingVnState::VmiListIter it = vn_state->vmi_list_.begin();
435  while (it != vn_state->vmi_list_.end()) {
436  vn_state->logical_router_uuid_ = (*it)->logical_router_uuid();
437  if ((*it)->logical_router_uuid() != nil_uuid()) {
438  return;
439  }
440  //Delete VMI with no lr uuid, vmi update will handle rest.
441  vn_state->vmi_list_.erase(it);
442  if (vn_state->vmi_list_.size() == 0) {
443  vn_state->logical_router_uuid_ = nil_uuid();
444  return;
445  }
446  it = vn_state->vmi_list_.begin();
447  }
448  return;
449 }
450 
452  VxlanRoutingVnState *vn_state) {
453  using boost::uuids::nil_uuid;
454 
455  if (vn->logical_router_uuid() != nil_uuid()) {
456  return;
457  }
458 
462  bool withdraw = false;
463  bool update = true;
464 
465  // Update lr uuid in case some vmi is deleted or added.
466  UpdateLogicalRouterUuid(vn, vn_state);
467  if (vn->IsDeleted() || (vn->GetVrf() == NULL)) {
468  withdraw = true;
469  update = false;
470  }
471 
472  if (it != vrf_mapper_.vn_lr_set_.end() &&
473  (it->second != vn_state->logical_router_uuid_) &&
474  (vn_state->logical_router_uuid_ != nil_uuid())) {
475  withdraw = true;
476  }
477 
478  if (vn_state->logical_router_uuid_ == nil_uuid()) {
479  withdraw = true;
480  update = false;
481  }
482 
483  if (it != vrf_mapper_.vn_lr_set_.end()) {
484  routing_info_it = vrf_mapper_.lr_vrf_info_map_.find(it->second);
485  }
486 
487  // Handles deletion case
488  if (withdraw) {
489  if (routing_info_it != vrf_mapper_.lr_vrf_info_map_.end()) {
491  routing_info_it->second.bridge_vn_list_.find(vn);
492  std::string vrf_name = "";
493  if (routing_info_it->second.bridge_vrf_names_list_.count(vn) == 1) {
494  vrf_name = routing_info_it->second.bridge_vrf_names_list_.at(vn);
495  DeleteSubnetRoute(vn, vrf_name);
496  }
497  if (br_it != routing_info_it->second.bridge_vn_list_.end()) {
498  vrf_mapper_.WalkRoutingVrf(it->second, vn, false, true);
499  routing_info_it->second.bridge_vn_list_.erase(br_it);
500  routing_info_it->second.bridge_vrf_names_list_.erase(vn);
501  }
502  // Trigger delete of logical router
503  vrf_mapper_.TryDeleteLogicalRouter(routing_info_it);
504  }
505  vrf_mapper_.vn_lr_set_.erase(vn);
506  }
507 
508  if (update) {
510  if (vrf_mapper_.vn_lr_set_[vn] == nil_uuid()) {
511  return;
512  }
513 
516  lr_vrf_info.bridge_vn_list_.insert(vn);
517  if (vn->GetVrf())
518  lr_vrf_info.bridge_vrf_names_list_[vn] = vn->GetVrf()->GetName();
519  vrf_mapper_.WalkRoutingVrf(vrf_mapper_.vn_lr_set_[vn], vn, true, false);
520  }
521 
522  // Without vrf walks cant be scheduled
523  if (!vn_state->vrf_ref_.get()) {
524  return;
525  }
526 
527  // Walk Evpn table if withdraw or update was done
528  if (update || withdraw) {
529  InetUnicastAgentRouteTable *inet4_table =
530  static_cast<InetUnicastAgentRouteTable *>(vn_state->vrf_ref_.get()->
531  GetInet4UnicastRouteTable());
532  InetUnicastAgentRouteTable *inet6_table =
533  static_cast<InetUnicastAgentRouteTable *>(vn_state->vrf_ref_.get()->
534  GetInet6UnicastRouteTable());
535  if (inet4_table && inet6_table) {
536  vrf_mapper_.WalkBridgeInetTables(inet4_table, inet6_table);
537  }
538  }
539  return;
540 }
541 
543  if (rt_vrf == nullptr) {
544  return;
545  }
546  // Loop over all EVPN routes and delete them
547 
548  EvpnAgentRouteTable *evpn_table = dynamic_cast<EvpnAgentRouteTable *>
549  (rt_vrf->GetEvpnRouteTable());
550  if (evpn_table == nullptr) {
551  return;
552  }
553  EvpnRouteEntry *c_entry = dynamic_cast<EvpnRouteEntry *>
554  (evpn_table->GetTablePartition(0)->GetFirst());
555 
556  const std::string vrf_name = rt_vrf->GetName();
557  const uint32_t ethernet_tag = 0;
558  const MacAddress mac_addr;
559  while (c_entry != nullptr) {
560  const IpAddress &prefix_ip = c_entry->prefix_address();
561  const uint8_t plen = c_entry->prefix_length();
562  const AgentPath *rt_active_path = c_entry->GetActivePath();
563  const Peer *rt_active_peer = rt_active_path->peer();
564  const auto &path_list = c_entry->GetPathList();
565 
566  // Compute next entry in advance
567  if (c_entry != nullptr && c_entry->get_table_partition()) {
568  c_entry = dynamic_cast<EvpnRouteEntry *>
569  (c_entry->get_table_partition()->GetNext(c_entry));
570  } else {
571  break;
572  }
573 
575  vrf_name, prefix_ip, plen,
576  nullptr);
578  vrf_name, prefix_ip, plen,
579  nullptr);
580 
581  if (rt_active_peer->GetType() != Peer::BGP_PEER) {
582  // Delete routes originated from bridge networks
583  EvpnAgentRouteTable::DeleteReq(rt_active_peer,
584  vrf_name,
585  mac_addr,
586  prefix_ip,
587  plen,
588  ethernet_tag, // ethernet_tag = 0 for Type5
589  nullptr);
590  } else {
591  for (auto &path_ref : path_list) {
593  static_cast<const AgentPath*>
594  (&path_ref)->peer(),
595  vrf_name,
596  mac_addr,
597  prefix_ip,
598  plen,
599  ethernet_tag, // ethernet_tag = 0 for Type5
600  nullptr);
601  }
602  }
603  }
604 }
605 
607  VxlanRoutingVnState *vn_state) {
608 
609  bool withdraw = false;
610  bool update = false;
612 
613  if (vn->IsDeleted() ||
614  (vn->GetVrf() == NULL) ||
615  (vn_state->is_routing_vn_ == false)) {
616  update = false;
617  withdraw = true;
618  } else {
619  update = true;
620  if (it != vrf_mapper_.vn_lr_set_.end()) {
621  // LR uuid changed, so withdraw from old and add new.
622  if (it->second != vn_state->logical_router_uuid_) {
623  withdraw = true;
624  }
625  }
626  }
627 
628  if (withdraw && (it != vrf_mapper_.vn_lr_set_.end())) {
630  vrf_mapper_.lr_vrf_info_map_.find(it->second);
631  // Delete only if parent VN is same as notified VN coz it may so happen
632  // that some other VN has taken the ownership of this LR and
633  // notification of same came before this VN.
634  if (routing_info_it != vrf_mapper_.lr_vrf_info_map_.end()) {
635  if (routing_info_it->second.routing_vn_ == vn) {
637  routing_info_it->second.routing_vrf_);
638  // Routing VN/VRF
639  // Reset parent vn and routing vrf
640  routing_info_it->second.routing_vn_ = nullptr;
641  routing_info_it->second.routing_vrf_ = nullptr;
642  }
643  // Trigger delete of logical router
644  vrf_mapper_.TryDeleteLogicalRouter(routing_info_it);
645  }
646  vrf_mapper_.vn_lr_set_.erase(it);
647  }
648 
649  if (update) {
650  if (vn_state->logical_router_uuid_ == boost::uuids::nil_uuid()) {
651  return;
652  }
653 
654  if (it == vrf_mapper_.vn_lr_set_.end()) {
656  }
657 
658  VxlanRoutingVrfMapper::RoutedVrfInfo &routed_vrf_info =
660  // Take the ownership of LR
661  routed_vrf_info.routing_vn_ = vn;
662  if (routed_vrf_info.routing_vrf_ != vn->GetVrf()) {
663  routed_vrf_info.routing_vrf_ = vn->GetVrf();
664  vrf_mapper_.WalkBridgeVrfs(routed_vrf_info);
665  }
666  }
667 }
668 
674  DBEntryBase *e) {
675  VrfEntry *vrf = static_cast<VrfEntry *>(e);
676  if (vrf->GetName().compare(agent_->fabric_vrf_name()) == 0)
677  return;
678  if (vrf->GetName().compare(agent_->fabric_policy_vrf_name()) == 0)
679  return;
680 
681  VxlanRoutingState *state = dynamic_cast<VxlanRoutingState *>(vrf->
682  GetState(partition->parent(), vrf_listener_id_));
683  if (vrf->IsDeleted()) {
684  if (state) {
685  vrf->ClearState(partition->parent(), vrf_listener_id_);
686  delete state;
687  }
688  } else {
689  // Vrf was added/changed.
690  if (!state) {
691  state = new VxlanRoutingState(this, vrf);
692  vrf->SetState(partition->parent(), vrf_listener_id_, state);
693  }
694  if (vrf->vn() && vrf->vn()->vxlan_routing_vn()) {
695  vrf->set_routing_vrf(true);
696  }
697  }
698 }
699 
701  DBEntryBase *e) {
702  VmInterface *vmi = dynamic_cast<VmInterface *>(e);
703  if (!vmi) {
704  return;
705  }
706 
707  VnEntry *vn = vmi->GetNonConstVn();
708  VxlanRoutingVnState *vn_state = NULL;
709  VxlanRoutingVmiState *vmi_state = dynamic_cast<VxlanRoutingVmiState *>(vmi->
710  GetAgentDBEntryState(vmi_listener_id_));
711  if (vmi->IsDeleted() || (vn == NULL) ||
712  (vmi->logical_router_uuid() == boost::uuids::nil_uuid())) {
713  if (!vmi_state) {
714  return;
715  }
716  vn = vmi_state->vn_entry_.get();
717  vn_state = dynamic_cast<VxlanRoutingVnState *>
719  if (vn_state)
720  vn_state->DeleteVmi(vn, vmi);
721  vmi->ClearState(partition->parent(), vmi_listener_id_);
722  delete vmi_state;
723  return;
724  }
725 
726  if ((vmi->device_type() != VmInterface::VMI_ON_LR) ||
727  (vmi->vmi_type() != VmInterface::ROUTER)) {
728  return;
729  }
730 
731  if (vmi->logical_router_uuid() == boost::uuids::nil_uuid()) {
732  return;
733  }
734 
735  // Without VN no point of update
736  if (!vn) {
737  return;
738  }
739 
740  if (!vmi_state) {
741  vmi_state = new VxlanRoutingVmiState();
742  vmi->SetState(partition->parent(), vmi_listener_id_, vmi_state);
743  vmi_state->vn_entry_ = vn;
744  }
745  // Update logical_router_uuid
746  vmi_state->logical_router_uuid_ = vmi->logical_router_uuid();
747 
748  // Its necessary to add state on VN so as to push VMI. VN notify can come
749  // after VMI notify.
750  VnNotify(vn->get_table_partition(), vn);
751  // Now get VN state and add/delete VMI there
752  vn_state = dynamic_cast<VxlanRoutingVnState *>
754  if (vn_state) {
755  vn_state->AddVmi(vn, vmi);
756  }
757 }
758 
759 void VxlanRoutingManager::HandleSubnetRoute(const VrfEntry *vrf, bool bridge_vrf) {
760  //
761  // New version
762  //
763  if (vrf->vn() && vrf->vn()->vxlan_routing_vn() == false) {
764  const VrfEntry *routing_vrf =
766  if (!routing_vrf || vrf->IsDeleted()) {
767  DeleteSubnetRoute(vrf);
768  vrf->vn()->set_lr_vrf(NULL);
769  } else {
770  UpdateSubnetRoute(vrf, routing_vrf);
771  vrf->vn()->set_lr_vrf(routing_vrf);
772  }
773  }
774 }
775 
777  const std::string& vrf_name,
778  const IpAddress& ipam_prefix,
779  const uint32_t plen) {
780  if (vn == NULL || vrf_name == std::string(""))
781  return;
782 
784 
785  if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
786  lr_it->second == boost::uuids::nil_uuid())
787  return;
788 
790  vrf_mapper_.lr_vrf_info_map_[lr_it->second];
791 
792  if (lr_vrf_info.bridge_vn_list_.size() == 0)
793  return;
794 
796  lr_vrf_info.bridge_vn_list_.begin();
797  while (it != lr_vrf_info.bridge_vn_list_.end()) {
798  if (vn == *it) {
799  it++;
800  continue;
801  }
802 
803  (*it)->GetVrf()->GetInetUnicastRouteTable(ipam_prefix)->
804  Delete(agent_->evpn_routing_peer(), (*it)->GetVrf()->GetName(),
805  ipam_prefix, plen, NULL);
806  it++;
807  }
808 }
809 
810 void VxlanRoutingManager::DeleteSubnetRoute(const VnEntry *vn, const std::string& vrf_name) {
811  if (vn == NULL || vrf_name == std::string(""))
812  return;
813  std::vector<VnIpam> bridge_vn_ipam = vn->GetVnIpam();
814 
815  if (bridge_vn_ipam.size() == 0)
816  return;
817 
819 
820  if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
821  lr_it->second == boost::uuids::nil_uuid())
822  return;
823 
825  vrf_mapper_.lr_vrf_info_map_[lr_it->second];
826 
827  if (lr_vrf_info.bridge_vn_list_.size() == 0)
828  return;
829 
831  lr_vrf_info.bridge_vn_list_.begin();
832  while (it != lr_vrf_info.bridge_vn_list_.end()) {
833  if (vn == *it) {
834  it++;
835  continue;
836  }
837 
838  for (std::vector<VnIpam>::iterator ipam_itr = bridge_vn_ipam.begin();
839  ipam_itr < bridge_vn_ipam.end(); ipam_itr++) {
840  (*it)->GetVrf()->GetInetUnicastRouteTable(ipam_itr->ip_prefix)->
841  Delete(agent_->evpn_routing_peer(), (*it)->GetVrf()->GetName(),
842  ipam_itr->GetSubnetAddress(), ipam_itr->plen, NULL);
843  }
844  std::vector<VnIpam> vn_ipam = (*it)->GetVnIpam();
845 
846  if (vn_ipam.size() == 0) {
847  it++;
848  continue;
849  }
850  for (std::vector<VnIpam>::iterator vn_ipam_itr = vn_ipam.begin();
851  vn_ipam_itr < vn_ipam.end(); vn_ipam_itr++) {
853  vrf_name, vn_ipam_itr->GetSubnetAddress(),
854  vn_ipam_itr->plen, NULL);
855  }
856  it++;
857  }
858 }
859 
860 //void VxlanRoutingManager::DeleteSubnetRoute(const VrfEntry *vrf, VnIpam *ipam) {
862  if (vrf == NULL)
863  return;
864  DeleteSubnetRoute(vrf->vn(), vrf->GetName());
865 }
866 
868  const VrfEntry *routing_vrf) {
869  if (!bridge_vrf->vn())
870  return;
871 
872  std::vector<VnIpam> bridge_vn_ipam = bridge_vrf->vn()->GetVnIpam();
873 
874  if (bridge_vn_ipam.size() == 0)
875  return;
876 
878  vrf_mapper_.vn_lr_set_.find(bridge_vrf->vn());
879 
880  if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
881  lr_it->second == boost::uuids::nil_uuid())
882  return;
883 
885  vrf_mapper_.lr_vrf_info_map_[lr_it->second];
886 
887  if (lr_vrf_info.bridge_vn_list_.size() == 0)
888  return;
889 
891  lr_vrf_info.bridge_vn_list_.begin();
892  while (it != lr_vrf_info.bridge_vn_list_.end()) {
893  if (bridge_vrf->vn() == *it) {
894  it++;
895  continue;
896  }
897 
898  for (std::vector<VnIpam>::iterator ipam_itr = bridge_vn_ipam.begin();
899  ipam_itr < bridge_vn_ipam.end(); ipam_itr++) {
901  nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
902  nh_req.data.reset(new VrfNHData(false, false, false));
903  (*it)->GetVrf()->GetInetUnicastRouteTable(ipam_itr->ip_prefix)->
904  AddEvpnRoutingRoute(ipam_itr->ip_prefix, ipam_itr->plen, routing_vrf,
907  CommunityList(),
908  PathPreference(),
909  EcmpLoadBalance(),
910  TagList(),
911  nh_req,
912  routing_vrf->vxlan_id(),
913  VnListType());
914  }
915 
916  std::vector<VnIpam> vn_ipam = (*it)->GetVnIpam();
917  for (std::vector<VnIpam>::iterator vn_ipam_itr = vn_ipam.begin();
918  vn_ipam_itr != vn_ipam.end(); vn_ipam_itr++) {
919 
921  nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
922  nh_req.data.reset(new VrfNHData(false, false, false));
923  bridge_vrf->GetInetUnicastRouteTable(vn_ipam_itr->ip_prefix)->
924  AddEvpnRoutingRoute(vn_ipam_itr->ip_prefix, vn_ipam_itr->plen, routing_vrf,
927  CommunityList(),
928  PathPreference(),
929  EcmpLoadBalance(),
930  TagList(),
931  nh_req,
932  routing_vrf->vxlan_id(),
933  VnListType());
934  }
935  it++;
936  }
937 }
938 
942 void VxlanRoutingManager::FillSandeshInfo(VxlanRoutingResp *resp) {
945  std::vector<VxlanRoutingMap> vr_map;
946  while (it1 != vrf_mapper_.lr_vrf_info_map_.end()) {
947  VxlanRoutingMap vxlan_routing_map;
948  vxlan_routing_map.set_logical_router_uuid(UuidToString(it1->first));
949  vxlan_routing_map.set_routing_vrf(it1->second.routing_vrf_->
950  GetName());
951  vxlan_routing_map.set_parent_routing_vn(it1->second.routing_vn_->
952  GetName());
954  it1->second.bridge_vn_list_.begin();
955  while (it2 != it1->second.bridge_vn_list_.end()) {
956  VxlanRoutingBridgeVrf bridge_vrf;
957  if ((*it2)->GetVrf()) {
958  bridge_vrf.set_bridge_vrf((*it2)->GetVrf()->GetName());
959  }
960  bridge_vrf.set_bridge_vn((*it2)->GetName());
961  vxlan_routing_map.bridge_vrfs.push_back(bridge_vrf);
962  it2++;
963  }
964  vr_map.push_back(vxlan_routing_map);
965  it1++;
966  }
967  resp->set_vr_map(vr_map);
968 }
969 
970 void VxlanRoutingReq::HandleRequest() const {
971  VxlanRoutingResp *resp = new VxlanRoutingResp();
972  Agent *agent = Agent::GetInstance();
973  VxlanRoutingManager *vxlan_routing_mgr =
974  agent->oper_db()->vxlan_routing_manager();
975  if (vxlan_routing_mgr) {
976  resp->set_context(context());
977  vxlan_routing_mgr->FillSandeshInfo(resp);
978  }
979  resp->set_more(false);
980  resp->Response();
981  return;
982 }
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 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:44
const Type GetType() const
Definition: peer.h:87
@ BGP_PEER
Definition: peer.h:51
const std::string & GetName() const
Definition: peer.h:86
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:266
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:257
bool vxlan_routing_vn() const
Definition: vn.h:256
Definition: vrf.h:86
const string & GetName() const
Definition: vrf.h:100
void set_routing_vrf(bool val)
Definition: vrf.h:222
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:165
VnEntry * vn() const
Definition: vrf.h:101
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:33
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)