Line data Source code
1 : /*
2 : * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3 : * Copyright (c) 2022 - 2026 Matvey Kraposhin.
4 : * Copyright (c) 2024 - 2026 Elena Zizganova.
5 : */
6 :
7 : #include <boost/uuid/uuid_io.hpp>
8 : #include <cmn/agent_cmn.h>
9 :
10 : #include <base/logging.h>
11 : #include <oper/operdb_init.h>
12 : #include <oper/route_common.h>
13 : #include <oper/vrf.h>
14 : #include <oper/bridge_route.h>
15 : #include <oper/inet_unicast_route.h>
16 : #include <oper/evpn_route.h>
17 : #include <oper/agent_route.h>
18 : #include <oper/agent_route_walker.h>
19 : #include <oper/vn.h>
20 : #include <oper/vrf.h>
21 : #include <oper/vxlan_routing_manager.h>
22 : #include <oper/tunnel_nh.h> //for tunnel interception
23 :
24 : using namespace std;
25 :
26 6 : VxlanRoutingState::VxlanRoutingState(VxlanRoutingManager *mgr,
27 6 : VrfEntry *vrf) {
28 6 : inet4_table_ = vrf->GetInet4UnicastRouteTable();
29 6 : inet6_table_ = vrf->GetInet6UnicastRouteTable();
30 6 : evpn_table_ = vrf->GetEvpnRouteTable();
31 12 : std::string nm4 = std::string("vxlan_lstnr.") + inet4_table_->name();
32 12 : std::string nm6 = std::string("vxlan_lstnr.") + inet6_table_->name();
33 12 : std::string nme = std::string("vxlan_lstnr.") + evpn_table_->name();
34 :
35 12 : inet4_id_ = inet4_table_->
36 6 : Register(boost::bind(&VxlanRoutingManager::RouteNotify,
37 : mgr, _1, _2), nm4);
38 12 : inet6_id_ = inet6_table_->
39 6 : Register(boost::bind(&VxlanRoutingManager::RouteNotify,
40 : mgr, _1, _2), nm6);
41 12 : evpn_id_ = evpn_table_->
42 6 : Register(boost::bind(&VxlanRoutingManager::RouteNotify,
43 : mgr, _1, _2), nme);
44 6 : }
45 :
46 12 : VxlanRoutingState::~VxlanRoutingState() {
47 6 : evpn_table_->Unregister(evpn_id_);
48 6 : inet4_table_->Unregister(inet4_id_);
49 6 : inet6_table_->Unregister(inet6_id_);
50 12 : }
51 :
52 6 : VxlanRoutingVnState::VxlanRoutingVnState(VxlanRoutingManager *mgr) :
53 12 : vmi_list_(), is_routing_vn_(false),
54 6 : logical_router_uuid_(boost::uuids::nil_uuid()), mgr_(mgr) {
55 6 : }
56 :
57 12 : VxlanRoutingVnState::~VxlanRoutingVnState() {
58 12 : }
59 :
60 0 : void VxlanRoutingVnState::AddVmi(const VnEntry *vn, const VmInterface *vmi) {
61 0 : if (vmi->logical_router_uuid() == boost::uuids::nil_uuid()) {
62 0 : LOG(ERROR, "Error in VxlanRoutingManager::AddVmi"
63 : << ", vmi->logical_router_uuid() == boost::uuids::nil_uuid()");
64 0 : assert(vmi->logical_router_uuid() != boost::uuids::nil_uuid());
65 : }
66 0 : VmiListIter it = vmi_list_.find(vmi);
67 0 : if (it != vmi_list_.end()) {
68 0 : return;
69 : }
70 :
71 0 : vmi_list_.insert(vmi);
72 0 : if ((logical_router_uuid_ != vmi->logical_router_uuid()) &&
73 0 : (*(vmi_list_.begin()) == vmi)) {
74 0 : mgr_->BridgeVnNotify(vn, this);
75 : }
76 : }
77 :
78 0 : void VxlanRoutingVnState::DeleteVmi(const VnEntry *vn, const VmInterface *vmi) {
79 0 : VmiListIter it = vmi_list_.find(vmi);
80 0 : if (it == vmi_list_.end()) {
81 0 : return;
82 : }
83 0 : vmi_list_.erase(vmi);
84 0 : mgr_->BridgeVnNotify(vn, this);
85 : }
86 :
87 0 : VxlanRoutingVmiState::VxlanRoutingVmiState() :
88 0 : vn_entry_(NULL), logical_router_uuid_(boost::uuids::nil_uuid()) {
89 0 : }
90 :
91 0 : VxlanRoutingVmiState::~VxlanRoutingVmiState() {
92 0 : }
93 :
94 0 : boost::uuids::uuid VxlanRoutingVnState::logical_router_uuid() const {
95 0 : if (vmi_list_.size() == 0)
96 0 : return boost::uuids::nil_uuid();
97 :
98 0 : return (*(vmi_list_.begin()))->logical_router_uuid();
99 : }
100 :
101 3 : VxlanRoutingRouteWalker::VxlanRoutingRouteWalker(const std::string &name,
102 3 : VxlanRoutingManager *mgr, Agent *agent) :
103 3 : AgentRouteWalker(name, agent), mgr_(mgr) {
104 3 : }
105 :
106 6 : VxlanRoutingRouteWalker::~VxlanRoutingRouteWalker() {
107 6 : }
108 :
109 : // Only take notification of bridge inet routes.
110 : // Change in them will trigger change in rest.
111 0 : bool VxlanRoutingRouteWalker::RouteWalkNotify(DBTablePartBase *partition,
112 : DBEntryBase *e) {
113 : // Now route leaking is triggered by changes in the Inet table of
114 : // a bridge VRF instance
115 : const InetUnicastRouteEntry *inet_rt =
116 0 : dynamic_cast<const InetUnicastRouteEntry*>(e);
117 0 : if (inet_rt) {
118 0 : const VrfEntry *vrf = inet_rt->vrf();
119 0 : if (vrf && vrf->vn() && !mgr_->IsRoutingVrf(vrf)) {
120 0 : mgr_->InetRouteNotify(partition, e);
121 : }
122 : }
123 0 : return true;
124 : }
125 :
126 3 : VxlanRoutingVrfMapper::VxlanRoutingVrfMapper(VxlanRoutingManager *mgr) :
127 3 : mgr_(mgr), lr_vrf_info_map_(), vn_lr_set_(),
128 6 : inet4_table_walker_(), inet6_table_walker_() {
129 3 : }
130 :
131 3 : VxlanRoutingVrfMapper::~VxlanRoutingVrfMapper() {
132 3 : }
133 :
134 3 : void VxlanRoutingVrfMapper::WalkBridgeInetTables(
135 : InetUnicastAgentRouteTable *inet4_table,
136 : InetUnicastAgentRouteTable *inet6_table) {
137 : // Inet 4
138 : {
139 3 : DBTable::DBTableWalkRef walk_ref;
140 3 : InetTableWalker::iterator it = inet4_table_walker_.find(inet4_table);
141 3 : if (it == inet4_table_walker_.end()) {
142 : walk_ref = inet4_table->
143 6 : AllocWalker(boost::bind(&VxlanRoutingManager::RouteNotify,
144 : mgr_, _1, _2),
145 : boost::bind(&VxlanRoutingVrfMapper::BridgeInet4RouteWalkDone,
146 3 : this, _1, _2));
147 3 : inet4_table_walker_[inet4_table] = walk_ref;
148 : } else {
149 0 : walk_ref = it->second;
150 : }
151 3 : inet4_table->WalkAgain(walk_ref);
152 : //Every time walk is issued for bridge table revisit subnet routes
153 3 : mgr_->HandleSubnetRoute(inet4_table->vrf_entry());
154 3 : }
155 : // Inet 6
156 : {
157 3 : DBTable::DBTableWalkRef walk_ref;
158 3 : InetTableWalker::iterator it = inet6_table_walker_.find(inet6_table);
159 3 : if (it == inet6_table_walker_.end()) {
160 : walk_ref = inet6_table->
161 6 : AllocWalker(boost::bind(&VxlanRoutingManager::RouteNotify,
162 : mgr_, _1, _2),
163 : boost::bind(&VxlanRoutingVrfMapper::BridgeInet6RouteWalkDone,
164 3 : this, _1, _2));
165 3 : inet6_table_walker_[inet6_table] = walk_ref;
166 : } else {
167 0 : walk_ref = it->second;
168 : }
169 3 : inet6_table->WalkAgain(walk_ref);
170 : //Every time walk is issued for bridge table revisit subnet routes
171 3 : mgr_->HandleSubnetRoute(inet6_table->vrf_entry());
172 3 : }
173 3 : }
174 :
175 0 : void VxlanRoutingVrfMapper::WalkRoutingVrf(const boost::uuids::uuid &lr_uuid,
176 : const VnEntry *vn, bool update, bool withdraw) {
177 0 : if (lr_uuid == boost::uuids::nil_uuid())
178 0 : return;
179 : VxlanRoutingVrfMapper::RoutedVrfInfo &routing_vrf_info =
180 0 : lr_vrf_info_map_[lr_uuid];
181 0 : const VrfEntry *routing_vrf = routing_vrf_info.routing_vrf_;
182 0 : DBTable::DBTableWalkRef walk_ref;
183 :
184 0 : if (withdraw) {
185 0 : InetUnicastAgentRouteTable *inet4_table = nullptr;
186 0 : InetUnicastAgentRouteTable *inet6_table = nullptr;
187 0 : const VrfEntry *bridge_vrf = VxlanRoutingManager::VnVrf(vn,
188 0 : routing_vrf_info.bridge_vrf_names_list_[vn]);
189 0 : if (bridge_vrf && routing_vrf) {
190 0 : inet4_table = bridge_vrf->GetInet4UnicastRouteTable();
191 0 : inet6_table = bridge_vrf->GetInet6UnicastRouteTable();
192 : }
193 0 : if (inet4_table) {
194 : walk_ref = inet4_table->
195 0 : AllocWalker(boost::bind(
196 : &VxlanRoutingManager::WithdrawEvpnRouteFromRoutingVrf,
197 : mgr_, routing_vrf, _1, _2),
198 : boost::bind(&VxlanRoutingVrfMapper::RoutingVrfRouteWalkDone,
199 0 : this, _1, _2));
200 0 : inet4_table->WalkAgain(walk_ref);
201 : }
202 0 : if (inet6_table) {
203 : walk_ref = inet6_table->
204 0 : AllocWalker(boost::bind(
205 : &VxlanRoutingManager::WithdrawEvpnRouteFromRoutingVrf,
206 : mgr_, routing_vrf, _1, _2),
207 : boost::bind(&VxlanRoutingVrfMapper::RoutingVrfRouteWalkDone,
208 0 : this, _1, _2));
209 0 : inet6_table->WalkAgain(walk_ref);
210 : }
211 : } else {
212 0 : EvpnAgentRouteTable *evpn_table = NULL;
213 0 : if (routing_vrf) {
214 : evpn_table =
215 : static_cast<EvpnAgentRouteTable *>(
216 0 : routing_vrf->GetEvpnRouteTable());
217 : }
218 0 : if (!evpn_table) {
219 0 : return;
220 : }
221 :
222 : walk_ref = evpn_table->
223 0 : AllocWalker(boost::bind(&VxlanRoutingManager::LeakRoutesIntoBridgeTables,
224 : mgr_, _1, _2, lr_uuid, vn, update),
225 : boost::bind(&VxlanRoutingVrfMapper::RoutingVrfRouteWalkDone,
226 0 : this, _1, _2));
227 0 : evpn_table->WalkAgain(walk_ref);
228 : }
229 0 : }
230 :
231 0 : void VxlanRoutingVrfMapper::RoutingVrfRouteWalkDone(DBTable::DBTableWalkRef walk_ref,
232 : DBTableBase *partition) {
233 0 : if (walk_ref.get() != NULL)
234 0 : (static_cast<DBTable *>(partition))->ReleaseWalker(walk_ref);
235 0 : }
236 :
237 3 : void VxlanRoutingVrfMapper::BridgeInet4RouteWalkDone(DBTable::DBTableWalkRef walk_ref,
238 : DBTableBase *partition) {
239 : const InetUnicastAgentRouteTable *table = static_cast<const InetUnicastAgentRouteTable *>
240 3 : (walk_ref->table());
241 3 : InetTableWalker::iterator it = inet4_table_walker_.find(table);
242 3 : if(it == inet4_table_walker_.end()) {
243 0 : LOG(ERROR, "Error in VxlanRoutingManager::BridgeInet4RouteWalkDone"
244 : << ", it == inet4_table_walker_.end()");
245 0 : assert(it != inet4_table_walker_.end());
246 : }
247 3 : inet4_table_walker_.erase(it);
248 3 : }
249 :
250 3 : void VxlanRoutingVrfMapper::BridgeInet6RouteWalkDone(DBTable::DBTableWalkRef walk_ref,
251 : DBTableBase *partition) {
252 : const InetUnicastAgentRouteTable *table = static_cast<const InetUnicastAgentRouteTable *>
253 3 : (walk_ref->table());
254 3 : InetTableWalker::iterator it = inet6_table_walker_.find(table);
255 3 : if(it == inet6_table_walker_.end()){
256 0 : LOG(ERROR, "Error in VxlanRoutingManager::BridgeInet6RouteWalkDone"
257 : << ", it == inet6_table_walker_.end()");
258 0 : assert(it != inet6_table_walker_.end());
259 : }
260 :
261 3 : inet6_table_walker_.erase(it);
262 3 : }
263 :
264 0 : void VxlanRoutingVrfMapper::WalkRoutingVrfRemoveExternalRoutes(
265 : const boost::uuids::uuid &lr_uuid, const VnEntry *vn,
266 : std::string bridge_vrf_name) {
267 0 : if (lr_uuid == boost::uuids::nil_uuid())
268 0 : return;
269 : VxlanRoutingVrfMapper::RoutedVrfInfo &routing_vrf_info =
270 0 : lr_vrf_info_map_[lr_uuid];
271 0 : const VrfEntry *routing_vrf = routing_vrf_info.routing_vrf_;
272 0 : DBTable::DBTableWalkRef walk_ref;
273 :
274 0 : EvpnAgentRouteTable *evpn_table = nullptr;
275 0 : if (routing_vrf != nullptr) {
276 : evpn_table =
277 : static_cast<EvpnAgentRouteTable *>(
278 0 : routing_vrf->GetEvpnRouteTable());
279 : }
280 0 : if (evpn_table == nullptr) {
281 0 : return;
282 : }
283 :
284 : walk_ref = evpn_table->
285 0 : AllocWalker(boost::bind(
286 : &VxlanRoutingManager::RemoveRoutesFromRoutingToBridgeVrf,
287 : mgr_, _1, _2, vn, bridge_vrf_name),
288 : boost::bind(&VxlanRoutingVrfMapper::RoutingVrfRouteWalkDone,
289 0 : this, _1, _2));
290 0 : evpn_table->WalkAgain(walk_ref);
291 0 : }
292 :
293 0 : void VxlanRoutingVrfMapper::WalkBridgeVrfs
294 : (const VxlanRoutingVrfMapper::RoutedVrfInfo &routed_vrf_info)
295 : {
296 : // Start walk on all l3 tables
297 : VxlanRoutingVrfMapper::RoutedVrfInfo::BridgeVnListIter it =
298 0 : routed_vrf_info.bridge_vn_list_.begin();
299 0 : while (it != routed_vrf_info.bridge_vn_list_.end()) {
300 0 : const VnEntry *vn = static_cast<const VnEntry *>(*it);
301 0 : const VrfEntry *vrf = VxlanRoutingManager::VnVrf(vn,
302 0 : routed_vrf_info.bridge_vrf_names_list_.at(vn));
303 0 : if (vrf) {
304 : InetUnicastAgentRouteTable *inet4_table =
305 : static_cast<InetUnicastAgentRouteTable *>
306 0 : (vrf->GetInet4UnicastRouteTable());
307 : InetUnicastAgentRouteTable *inet6_table =
308 : static_cast<InetUnicastAgentRouteTable *>
309 0 : (vrf->GetInet6UnicastRouteTable());
310 0 : if (!inet4_table || !inet6_table)
311 0 : continue;
312 0 : WalkBridgeInetTables(inet4_table, inet6_table);
313 : }
314 0 : it++;
315 : }
316 0 : }
317 :
318 6 : const VrfEntry *VxlanRoutingVrfMapper::GetRoutingVrfUsingVn
319 : (const VnEntry *vn) {
320 6 : VnLrSetIter it = vn_lr_set_.find(vn);
321 6 : if (it != vn_lr_set_.end()) {
322 0 : return GetRoutingVrfUsingUuid(it->second);
323 : }
324 6 : return NULL;
325 : }
326 :
327 60 : const VrfEntry *VxlanRoutingVrfMapper::GetRoutingVrfUsingAgentRoute
328 : (const AgentRoute *rt) {
329 60 : return GetRoutingVrfUsingUuid(GetLogicalRouterUuidUsingRoute(rt));
330 : }
331 :
332 60 : const VrfEntry *VxlanRoutingVrfMapper::GetRoutingVrfUsingUuid
333 : (const boost::uuids::uuid &lr_uuid) {
334 60 : LrVrfInfoMapIter it = lr_vrf_info_map_.find(lr_uuid);
335 60 : if (it != lr_vrf_info_map_.end()) {
336 0 : return it->second.routing_vrf_;
337 : }
338 60 : return NULL;
339 : }
340 :
341 60 : const boost::uuids::uuid VxlanRoutingVrfMapper::GetLogicalRouterUuidUsingRoute
342 : (const AgentRoute *rt) {
343 : using boost::uuids::nil_uuid;
344 :
345 60 : if (VxlanRoutingManager::IsRoutingVrf(rt->vrf())) {
346 0 : return rt->vrf()->vn()->logical_router_uuid();
347 : }
348 :
349 60 : const VnEntry* rt_vn = rt->vrf()->vn();
350 60 : if (!rt_vn) {
351 0 : return nil_uuid();
352 : }
353 :
354 : const VxlanRoutingVnState *vn_state =
355 60 : dynamic_cast<const VxlanRoutingVnState *>(rt_vn->
356 60 : GetAgentDBEntryState(mgr_->vn_listener_id()));
357 60 : if ((vn_state == NULL) || (vn_state->vmi_list_.size() == 0)) {
358 60 : return nil_uuid();
359 : }
360 :
361 0 : return vn_state->logical_router_uuid_;
362 : }
363 :
364 : // Invoked everytime when a vrf is pulled out of use.
365 : // Holds on object till all bridge and routing vrf are gone.
366 0 : void VxlanRoutingVrfMapper::TryDeleteLogicalRouter(LrVrfInfoMapIter &it) {
367 0 : if ((it->second.routing_vrf_ == NULL) &&
368 0 : (it->second.bridge_vn_list_.size() == 0)) {
369 0 : lr_vrf_info_map_.erase(it);
370 : }
371 0 : }
372 :
373 : const Peer *VxlanRoutingManager::routing_vrf_interface_peer_ = NULL;
374 : const Peer *VxlanRoutingManager::routing_vrf_vxlan_bgp_peer_ = NULL;
375 :
376 : /**
377 : * VxlanRoutingManager
378 : */
379 3 : VxlanRoutingManager::VxlanRoutingManager(Agent *agent) :
380 6 : agent_(agent), walker_(), vn_listener_id_(),
381 3 : vrf_listener_id_(), vmi_listener_id_(), vrf_mapper_(this) {
382 : //routing_vrf_interface_peer_ = agent_->evpn_routing_peer();
383 3 : routing_vrf_interface_peer_ = agent_->local_vm_export_peer();
384 3 : routing_vrf_vxlan_bgp_peer_ = agent_->vxlan_bgp_peer();
385 3 : }
386 :
387 6 : VxlanRoutingManager::~VxlanRoutingManager() {
388 6 : }
389 :
390 3 : void VxlanRoutingManager::Register() {
391 : // Walker to go through routes in bridge evpn tables.
392 6 : walker_.reset(new VxlanRoutingRouteWalker("VxlanRoutingManager", this,
393 3 : agent_));
394 3 : agent_->oper_db()->agent_route_walk_manager()->
395 3 : RegisterWalker(static_cast<AgentRouteWalker *>(walker_.get()));
396 :
397 : // Register all listener ids.
398 3 : vn_listener_id_ = agent_->vn_table()->
399 3 : Register(boost::bind(&VxlanRoutingManager::VnNotify,
400 : this, _1, _2));
401 3 : vrf_listener_id_ = agent_->vrf_table()->Register(
402 : boost::bind(&VxlanRoutingManager::VrfNotify, this, _1, _2));
403 3 : vmi_listener_id_ = agent_->interface_table()->Register(
404 : boost::bind(&VxlanRoutingManager::VmiNotify, this, _1, _2));
405 3 : }
406 :
407 3 : void VxlanRoutingManager::Shutdown() {
408 3 : agent_->vn_table()->Unregister(vn_listener_id_);
409 3 : agent_->vrf_table()->Unregister(vrf_listener_id_);
410 3 : agent_->interface_table()->Unregister(vmi_listener_id_);
411 3 : agent_->oper_db()->agent_route_walk_manager()->
412 3 : ReleaseWalker(walker_.get());
413 3 : walker_.reset(NULL);
414 3 : }
415 :
416 : /**
417 : * VNNotify
418 : * Handles routing vrf i.e. VRF meant for doing evpn routing.
419 : * Addition or deletion of same add/withdraws route imported from bridge vrf in
420 : * routing vrf.
421 : * Walk is issued for the routes of bridge vrf's evpn table.
422 : *
423 : * For bridge VRF, only delete of VN is handled here. Add has no operation as
424 : * add of VN does not give any info on LR/Routing VRF to use.
425 : * When delete is seen withdraw from the list of bridge list.
426 : */
427 19 : void VxlanRoutingManager::VnNotify(DBTablePartBase *partition, DBEntryBase *e) {
428 19 : VnEntry *vn = dynamic_cast<VnEntry *>(e);
429 19 : VxlanRoutingVnState *vn_state = dynamic_cast<VxlanRoutingVnState *>
430 19 : (vn->GetAgentDBEntryState(vn_listener_id_));
431 :
432 19 : if (vn->IsDeleted() && vn_state != NULL) {
433 6 : if (vn_state->is_routing_vn_) {
434 0 : RoutingVnNotify(vn, vn_state);
435 : } else {
436 6 : BridgeVnNotify(vn, vn_state);
437 : }
438 :
439 : //Delete State
440 6 : vn->ClearState(partition->parent(), vn_listener_id_);
441 6 : delete vn_state;
442 6 : return;
443 : }
444 :
445 : // if the VN had been deleted previously
446 13 : if (!vn_state && vn->IsDeleted()) {
447 0 : return;
448 : }
449 :
450 13 : if (!vn_state) {
451 6 : vn_state = new VxlanRoutingVnState(this);
452 6 : vn->SetState(partition->parent(), vn_listener_id_, vn_state);
453 : }
454 :
455 13 : if (vn->vxlan_routing_vn()) {
456 0 : vn_state->is_routing_vn_ = vn->vxlan_routing_vn();
457 : }
458 :
459 13 : vn_state->vrf_ref_ = vn->GetVrf();
460 13 : if (vn_state->is_routing_vn_) {
461 0 : vn_state->logical_router_uuid_ = vn->logical_router_uuid();
462 0 : RoutingVnNotify(vn, vn_state);
463 : } else {
464 13 : BridgeVnNotify(vn, vn_state);
465 : }
466 :
467 13 : return;
468 : }
469 :
470 19 : void UpdateLogicalRouterUuid(const VnEntry *vn,
471 : VxlanRoutingVnState *vn_state) {
472 : using boost::uuids::nil_uuid;
473 :
474 19 : if (vn_state->vmi_list_.size() == 0) {
475 19 : vn_state->logical_router_uuid_ = nil_uuid();
476 : }
477 :
478 19 : VxlanRoutingVnState::VmiListIter it = vn_state->vmi_list_.begin();
479 19 : while (it != vn_state->vmi_list_.end()) {
480 0 : vn_state->logical_router_uuid_ = (*it)->logical_router_uuid();
481 0 : if ((*it)->logical_router_uuid() != nil_uuid()) {
482 0 : return;
483 : }
484 : //Delete VMI with no lr uuid, vmi update will handle rest.
485 0 : vn_state->vmi_list_.erase(it);
486 0 : if (vn_state->vmi_list_.size() == 0) {
487 0 : vn_state->logical_router_uuid_ = nil_uuid();
488 0 : return;
489 : }
490 0 : it = vn_state->vmi_list_.begin();
491 : }
492 19 : return;
493 : }
494 :
495 19 : void VxlanRoutingManager::BridgeVnNotify(const VnEntry *vn,
496 : VxlanRoutingVnState *vn_state) {
497 : using boost::uuids::nil_uuid;
498 :
499 19 : if (vn->logical_router_uuid() != nil_uuid()) {
500 0 : return;
501 : }
502 :
503 19 : VxlanRoutingVrfMapper::VnLrSetIter it = vrf_mapper_.vn_lr_set_.find(vn);
504 : VxlanRoutingVrfMapper::LrVrfInfoMapIter routing_info_it =
505 19 : vrf_mapper_.lr_vrf_info_map_.end();
506 19 : VrfEntry *vn_vrf = vn->GetVrf();
507 19 : bool withdraw = false;
508 19 : bool update = true;
509 :
510 : // Update lr uuid in case some vmi is deleted or added.
511 19 : UpdateLogicalRouterUuid(vn, vn_state);
512 19 : if (vn->IsDeleted() || (vn_vrf == nullptr)) {
513 16 : withdraw = true;
514 16 : update = false;
515 : }
516 :
517 19 : if (it != vrf_mapper_.vn_lr_set_.end() &&
518 19 : (it->second != vn_state->logical_router_uuid_) &&
519 19 : (vn_state->logical_router_uuid_ != nil_uuid())) {
520 0 : withdraw = true;
521 : }
522 :
523 19 : if (vn_state->logical_router_uuid_ == nil_uuid()) {
524 19 : withdraw = true;
525 19 : update = false;
526 : }
527 :
528 19 : if (it != vrf_mapper_.vn_lr_set_.end()) {
529 0 : routing_info_it = vrf_mapper_.lr_vrf_info_map_.find(it->second);
530 : }
531 :
532 : // Handles deletion case
533 19 : if (withdraw) {
534 19 : if (routing_info_it != vrf_mapper_.lr_vrf_info_map_.end()) {
535 : VxlanRoutingVrfMapper::RoutedVrfInfo::BridgeVnListIter br_it =
536 0 : routing_info_it->second.bridge_vn_list_.find(vn);
537 0 : std::string vrf_name = "";
538 0 : if (routing_info_it->second.bridge_vrf_names_list_.count(vn) == 1) {
539 0 : vrf_name = routing_info_it->second.bridge_vrf_names_list_.at(vn);
540 0 : DeleteSubnetRoute(vn, vrf_name);
541 : }
542 0 : if (br_it != routing_info_it->second.bridge_vn_list_.end()) {
543 0 : vrf_mapper_.WalkRoutingVrf(it->second, vn, false, true);
544 0 : routing_info_it->second.bridge_vn_list_.erase(br_it);
545 0 : routing_info_it->second.bridge_vrf_names_list_.erase(vn);
546 0 : vrf_mapper_.WalkRoutingVrfRemoveExternalRoutes(it->second, vn,
547 : vrf_name);
548 : }
549 : // Trigger delete of logical router
550 0 : vrf_mapper_.TryDeleteLogicalRouter(routing_info_it);
551 0 : }
552 19 : vrf_mapper_.vn_lr_set_.erase(vn);
553 : }
554 :
555 19 : if (update) {
556 0 : vrf_mapper_.vn_lr_set_[vn] = vn_state->logical_router_uuid_;
557 0 : if (vrf_mapper_.vn_lr_set_[vn] == nil_uuid()) {
558 0 : return;
559 : }
560 :
561 : VxlanRoutingVrfMapper::RoutedVrfInfo &lr_vrf_info =
562 0 : vrf_mapper_.lr_vrf_info_map_[vn_state->logical_router_uuid_];
563 0 : lr_vrf_info.bridge_vn_list_.insert(vn);
564 0 : if (vn->GetVrf())
565 0 : lr_vrf_info.bridge_vrf_names_list_[vn] = vn->GetVrf()->GetName();
566 : else {
567 0 : lr_vrf_info.bridge_vrf_names_list_[vn] = std::string{""};
568 : }
569 0 : vrf_mapper_.WalkRoutingVrf(vrf_mapper_.vn_lr_set_[vn], vn, true, false);
570 : }
571 :
572 : // Without vrf walks cant be scheduled
573 19 : if (!vn_state->vrf_ref_.get()) {
574 16 : return;
575 : }
576 :
577 : // Walk Evpn table if withdraw or update was done
578 3 : if (update || withdraw) {
579 : InetUnicastAgentRouteTable *inet4_table =
580 : static_cast<InetUnicastAgentRouteTable *>(vn_state->vrf_ref_.get()->
581 3 : GetInet4UnicastRouteTable());
582 : InetUnicastAgentRouteTable *inet6_table =
583 : static_cast<InetUnicastAgentRouteTable *>(vn_state->vrf_ref_.get()->
584 3 : GetInet6UnicastRouteTable());
585 3 : if (inet4_table && inet6_table) {
586 3 : vrf_mapper_.WalkBridgeInetTables(inet4_table, inet6_table);
587 : }
588 : }
589 3 : return;
590 : }
591 :
592 0 : void VxlanRoutingManager::RoutingVrfDeleteAllRoutes(VrfEntry* rt_vrf) {
593 0 : if (rt_vrf == nullptr) {
594 0 : return;
595 : }
596 : // Loop over all EVPN routes and delete them
597 :
598 0 : EvpnAgentRouteTable *evpn_table = dynamic_cast<EvpnAgentRouteTable *>
599 0 : (rt_vrf->GetEvpnRouteTable());
600 0 : if (evpn_table == nullptr) {
601 0 : return;
602 : }
603 0 : EvpnRouteEntry *c_entry = dynamic_cast<EvpnRouteEntry *>
604 0 : (evpn_table->GetTablePartition(0)->GetFirst());
605 :
606 0 : const std::string vrf_name = rt_vrf->GetName();
607 0 : const uint32_t ethernet_tag = 0;
608 0 : const MacAddress mac_addr;
609 0 : while (c_entry != nullptr) {
610 0 : const IpAddress &prefix_ip = c_entry->prefix_address();
611 0 : const uint8_t plen = c_entry->prefix_length();
612 0 : const AgentPath *rt_active_path = c_entry->GetActivePath();
613 0 : const Peer *rt_active_peer = nullptr;
614 0 : const auto &path_list = c_entry->GetPathList();
615 0 : if (rt_active_path != nullptr)
616 0 : rt_active_peer = rt_active_path->peer();
617 :
618 : // Compute next entry in advance
619 0 : if (c_entry != nullptr && c_entry->get_table_partition()) {
620 0 : c_entry = dynamic_cast<EvpnRouteEntry *>
621 0 : (c_entry->get_table_partition()->GetNext(c_entry));
622 : } else {
623 0 : break;
624 : }
625 :
626 0 : InetUnicastAgentRouteTable::DeleteReq(routing_vrf_interface_peer_,
627 : vrf_name, prefix_ip, plen,
628 : nullptr);
629 0 : InetUnicastAgentRouteTable::DeleteReq(routing_vrf_vxlan_bgp_peer_,
630 : vrf_name, prefix_ip, plen,
631 : nullptr);
632 :
633 0 : if ((rt_active_peer != nullptr) &&
634 0 : (rt_active_peer->GetType() != Peer::BGP_PEER)) {
635 : // Delete routes originated from bridge networks
636 0 : EvpnAgentRouteTable::DeleteReq(rt_active_peer,
637 : vrf_name,
638 : mac_addr,
639 : prefix_ip,
640 : plen,
641 : ethernet_tag, // ethernet_tag = 0 for Type5
642 : nullptr);
643 : } else {
644 0 : for (auto &path_ref : path_list) {
645 0 : EvpnAgentRouteTable::DeleteReq(
646 : static_cast<const AgentPath*>
647 : (&path_ref)->peer(),
648 : vrf_name,
649 : mac_addr,
650 : prefix_ip,
651 : plen,
652 : ethernet_tag, // ethernet_tag = 0 for Type5
653 : nullptr);
654 : }
655 : }
656 : }
657 0 : }
658 :
659 0 : void VxlanRoutingManager::RoutingVnNotify(const VnEntry *vn,
660 : VxlanRoutingVnState *vn_state) {
661 :
662 0 : bool withdraw = false;
663 0 : bool update = false;
664 0 : VxlanRoutingVrfMapper::VnLrSetIter it = vrf_mapper_.vn_lr_set_.find(vn);
665 :
666 0 : if (vn->IsDeleted() ||
667 0 : (vn->GetVrf() == NULL) ||
668 0 : (vn_state->is_routing_vn_ == false)) {
669 0 : update = false;
670 0 : withdraw = true;
671 : } else {
672 0 : update = true;
673 0 : if (it != vrf_mapper_.vn_lr_set_.end()) {
674 : // LR uuid changed, so withdraw from old and add new.
675 0 : if (it->second != vn_state->logical_router_uuid_) {
676 0 : withdraw = true;
677 : }
678 : }
679 : }
680 :
681 0 : if (withdraw && (it != vrf_mapper_.vn_lr_set_.end())) {
682 : VxlanRoutingVrfMapper::LrVrfInfoMapIter routing_info_it =
683 0 : vrf_mapper_.lr_vrf_info_map_.find(it->second);
684 : // Delete only if parent VN is same as notified VN coz it may so happen
685 : // that some other VN has taken the ownership of this LR and
686 : // notification of same came before this VN.
687 0 : if (routing_info_it != vrf_mapper_.lr_vrf_info_map_.end()) {
688 0 : if (routing_info_it->second.routing_vn_ == vn) {
689 0 : RoutingVrfDeleteAllRoutes(
690 0 : routing_info_it->second.routing_vrf_);
691 : // Routing VN/VRF
692 : // Reset parent vn and routing vrf
693 0 : routing_info_it->second.routing_vn_ = nullptr;
694 0 : routing_info_it->second.routing_vrf_ = nullptr;
695 : }
696 : // Trigger delete of logical router
697 0 : vrf_mapper_.TryDeleteLogicalRouter(routing_info_it);
698 : }
699 0 : vrf_mapper_.vn_lr_set_.erase(it);
700 : }
701 :
702 0 : if (update) {
703 0 : if (vn_state->logical_router_uuid_ == boost::uuids::nil_uuid()) {
704 0 : return;
705 : }
706 :
707 0 : if (it == vrf_mapper_.vn_lr_set_.end()) {
708 0 : vrf_mapper_.vn_lr_set_[vn] = vn_state->logical_router_uuid_;
709 : }
710 :
711 : VxlanRoutingVrfMapper::RoutedVrfInfo &routed_vrf_info =
712 0 : vrf_mapper_.lr_vrf_info_map_[vn_state->logical_router_uuid_];
713 : // Take the ownership of LR
714 0 : routed_vrf_info.routing_vn_ = vn;
715 0 : if (routed_vrf_info.routing_vrf_ != vn->GetVrf()) {
716 0 : routed_vrf_info.routing_vrf_ = vn->GetVrf();
717 0 : vrf_mapper_.WalkBridgeVrfs(routed_vrf_info);
718 : }
719 : }
720 : }
721 :
722 : /**
723 : * Updates (sets or deletes) VxlanRoutingState for the given
724 : * modified VrfEntry
725 : */
726 106 : void VxlanRoutingManager::VrfNotify(DBTablePartBase *partition,
727 : DBEntryBase *e) {
728 106 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
729 106 : if (vrf->GetName().compare(agent_->fabric_vrf_name()) == 0)
730 19 : return;
731 87 : if (vrf->GetName().compare(agent_->fabric_policy_vrf_name()) == 0)
732 27 : return;
733 :
734 60 : VxlanRoutingState *state = dynamic_cast<VxlanRoutingState *>(vrf->
735 60 : GetState(partition->parent(), vrf_listener_id_));
736 60 : if (vrf->IsDeleted()) {
737 48 : if (state) {
738 6 : vrf->ClearState(partition->parent(), vrf_listener_id_);
739 6 : delete state;
740 : }
741 : } else {
742 : // Vrf was added/changed.
743 12 : if (!state) {
744 6 : state = new VxlanRoutingState(this, vrf);
745 6 : vrf->SetState(partition->parent(), vrf_listener_id_, state);
746 : }
747 12 : if (vrf->vn() && vrf->vn()->vxlan_routing_vn()) {
748 0 : vrf->set_routing_vrf(true);
749 : }
750 : }
751 : }
752 :
753 98 : void VxlanRoutingManager::VmiNotify(DBTablePartBase *partition,
754 : DBEntryBase *e) {
755 98 : VmInterface *vmi = dynamic_cast<VmInterface *>(e);
756 98 : if (!vmi) {
757 27 : return;
758 : }
759 :
760 71 : VnEntry *vn = vmi->GetNonConstVn();
761 71 : VxlanRoutingVnState *vn_state = NULL;
762 71 : VxlanRoutingVmiState *vmi_state = dynamic_cast<VxlanRoutingVmiState *>(vmi->
763 71 : GetAgentDBEntryState(vmi_listener_id_));
764 108 : if (vmi->IsDeleted() || (vn == NULL) ||
765 108 : (vmi->logical_router_uuid() == boost::uuids::nil_uuid())) {
766 71 : if (!vmi_state) {
767 71 : return;
768 : }
769 0 : vn = vmi_state->vn_entry_.get();
770 0 : vn_state = dynamic_cast<VxlanRoutingVnState *>
771 0 : (vn->GetAgentDBEntryState(vn_listener_id_));
772 0 : if (vn_state)
773 0 : vn_state->DeleteVmi(vn, vmi);
774 0 : vmi->ClearState(partition->parent(), vmi_listener_id_);
775 0 : delete vmi_state;
776 0 : return;
777 : }
778 :
779 0 : if ((vmi->device_type() != VmInterface::VMI_ON_LR) ||
780 0 : (vmi->vmi_type() != VmInterface::ROUTER)) {
781 0 : return;
782 : }
783 :
784 0 : if (vmi->logical_router_uuid() == boost::uuids::nil_uuid()) {
785 0 : return;
786 : }
787 :
788 : // Without VN no point of update
789 0 : if (!vn) {
790 0 : return;
791 : }
792 :
793 0 : if (!vmi_state) {
794 0 : vmi_state = new VxlanRoutingVmiState();
795 0 : vmi->SetState(partition->parent(), vmi_listener_id_, vmi_state);
796 0 : vmi_state->vn_entry_ = vn;
797 : }
798 : // Update logical_router_uuid
799 0 : vmi_state->logical_router_uuid_ = vmi->logical_router_uuid();
800 :
801 : // Its necessary to add state on VN so as to push VMI. VN notify can come
802 : // after VMI notify.
803 0 : VnNotify(vn->get_table_partition(), vn);
804 : // Now get VN state and add/delete VMI there
805 0 : vn_state = dynamic_cast<VxlanRoutingVnState *>
806 0 : (vn->GetAgentDBEntryState(vn_listener_id_));
807 0 : if (vn_state) {
808 0 : vn_state->AddVmi(vn, vmi);
809 : }
810 : }
811 :
812 6 : void VxlanRoutingManager::HandleSubnetRoute(const VrfEntry *vrf, bool bridge_vrf) {
813 : //
814 : // New version
815 : //
816 6 : if (vrf->vn() && vrf->vn()->vxlan_routing_vn() == false) {
817 : const VrfEntry *routing_vrf =
818 6 : vrf_mapper_.GetRoutingVrfUsingVn(vrf->vn());
819 6 : if (!routing_vrf || vrf->IsDeleted()) {
820 6 : DeleteSubnetRoute(vrf);
821 6 : vrf->vn()->set_lr_vrf(NULL);
822 : } else {
823 0 : UpdateSubnetRoute(vrf, routing_vrf);
824 0 : vrf->vn()->set_lr_vrf(routing_vrf);
825 : }
826 : }
827 6 : }
828 :
829 0 : void VxlanRoutingManager::DeleteIpamRoutes(const VnEntry *vn,
830 : const std::string& vrf_name,
831 : const IpAddress& ipam_prefix,
832 : const uint32_t plen) {
833 0 : if (vn == NULL || vrf_name == std::string(""))
834 0 : return;
835 :
836 0 : VxlanRoutingVrfMapper::VnLrSetIter lr_it = vrf_mapper_.vn_lr_set_.find(vn);
837 :
838 0 : if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
839 0 : lr_it->second == boost::uuids::nil_uuid())
840 0 : return;
841 :
842 : VxlanRoutingVrfMapper::RoutedVrfInfo &lr_vrf_info =
843 0 : vrf_mapper_.lr_vrf_info_map_[lr_it->second];
844 :
845 0 : if (lr_vrf_info.bridge_vn_list_.size() == 0)
846 0 : return;
847 :
848 0 : for (auto bridge_vn_entry : lr_vrf_info.bridge_vn_list_) {
849 0 : if (vn == bridge_vn_entry) {
850 0 : continue;
851 : }
852 :
853 0 : VrfEntry* it_vrf = VnVrf(bridge_vn_entry, lr_vrf_info.bridge_vrf_names_list_[bridge_vn_entry]);
854 0 : if (it_vrf == nullptr) {
855 0 : continue;
856 : }
857 :
858 : it_vrf->GetInetUnicastRouteTable(ipam_prefix)->
859 0 : Delete(agent_->evpn_routing_peer(), it_vrf->GetName(),
860 : ipam_prefix, plen, NULL);
861 : }
862 : }
863 :
864 6 : void VxlanRoutingManager::DeleteSubnetRoute(const VnEntry *vn, const std::string& vrf_name) {
865 6 : if (vn == NULL || vrf_name == std::string(""))
866 6 : return;
867 6 : std::vector<VnIpam> bridge_vn_ipam = vn->GetVnIpam();
868 :
869 6 : if (bridge_vn_ipam.size() == 0)
870 0 : return;
871 :
872 6 : VxlanRoutingVrfMapper::VnLrSetIter lr_it = vrf_mapper_.vn_lr_set_.find(vn);
873 :
874 6 : if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
875 6 : lr_it->second == boost::uuids::nil_uuid())
876 6 : return;
877 :
878 : VxlanRoutingVrfMapper::RoutedVrfInfo &lr_vrf_info =
879 0 : vrf_mapper_.lr_vrf_info_map_[lr_it->second];
880 :
881 0 : if (lr_vrf_info.bridge_vn_list_.size() == 0)
882 0 : return;
883 :
884 0 : for (auto bridge_vn_entry : lr_vrf_info.bridge_vn_list_) {
885 0 : if (vn == bridge_vn_entry) {
886 0 : continue;
887 : }
888 :
889 0 : for (auto br_ipam : bridge_vn_ipam) {
890 0 : VrfEntry* it_vrf = VnVrf(bridge_vn_entry, lr_vrf_info.bridge_vrf_names_list_[bridge_vn_entry]);
891 0 : if (it_vrf == nullptr) {
892 0 : continue;
893 : }
894 :
895 0 : it_vrf->GetInetUnicastRouteTable(br_ipam.ip_prefix)->
896 0 : DeleteReq(agent_->evpn_routing_peer(), it_vrf->GetName(),
897 0 : br_ipam.GetSubnetAddress(), br_ipam.plen, NULL);
898 0 : }
899 :
900 0 : std::vector<VnIpam> vn_ipam = bridge_vn_entry->GetVnIpam();
901 :
902 0 : if (vn_ipam.size() == 0) {
903 0 : continue;
904 : }
905 0 : for (auto br_vn_ipam : vn_ipam) {
906 0 : InetUnicastAgentRouteTable::DeleteReq(agent_->evpn_routing_peer(),
907 0 : vrf_name, br_vn_ipam.GetSubnetAddress(),
908 0 : br_vn_ipam.plen, NULL);
909 0 : }
910 0 : }
911 6 : }
912 :
913 : //void VxlanRoutingManager::DeleteSubnetRoute(const VrfEntry *vrf, VnIpam *ipam) {
914 6 : void VxlanRoutingManager::DeleteSubnetRoute(const VrfEntry *vrf) {
915 6 : if (vrf == NULL)
916 0 : return;
917 6 : DeleteSubnetRoute(vrf->vn(), vrf->GetName());
918 : }
919 :
920 0 : void VxlanRoutingManager::UpdateSubnetRoute(const VrfEntry *bridge_vrf,
921 : const VrfEntry *routing_vrf) {
922 0 : if (!bridge_vrf->vn())
923 0 : return;
924 :
925 0 : std::vector<VnIpam> bridge_vn_ipam = bridge_vrf->vn()->GetVnIpam();
926 :
927 0 : if (bridge_vn_ipam.size() == 0)
928 0 : return;
929 :
930 : VxlanRoutingVrfMapper::VnLrSetIter lr_it =
931 0 : vrf_mapper_.vn_lr_set_.find(bridge_vrf->vn());
932 :
933 0 : if (lr_it == vrf_mapper_.vn_lr_set_.end() ||
934 0 : lr_it->second == boost::uuids::nil_uuid())
935 0 : return;
936 :
937 : VxlanRoutingVrfMapper::RoutedVrfInfo &lr_vrf_info =
938 0 : vrf_mapper_.lr_vrf_info_map_[lr_it->second];
939 :
940 0 : if (lr_vrf_info.bridge_vn_list_.size() == 0)
941 0 : return;
942 :
943 : VxlanRoutingVrfMapper::RoutedVrfInfo::BridgeVnListIter it =
944 0 : lr_vrf_info.bridge_vn_list_.begin();
945 0 : while (it != lr_vrf_info.bridge_vn_list_.end()) {
946 0 : if (bridge_vrf->vn() == *it) {
947 0 : it++;
948 0 : continue;
949 : }
950 :
951 0 : for (std::vector<VnIpam>::iterator ipam_itr = bridge_vn_ipam.begin();
952 0 : ipam_itr < bridge_vn_ipam.end(); ipam_itr++) {
953 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
954 0 : nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
955 0 : nh_req.data.reset(new VrfNHData(false, false, false));
956 0 : VrfEntry* it_vrf = VnVrf((*it), lr_vrf_info.bridge_vrf_names_list_[(*it)]);
957 0 : if (it_vrf == nullptr) {
958 0 : continue;
959 : }
960 0 : it_vrf->GetInetUnicastRouteTable(ipam_itr->ip_prefix)->
961 0 : AddEvpnRoutingRouteReq(ipam_itr->ip_prefix, ipam_itr->plen, routing_vrf,
962 0 : agent_->evpn_routing_peer(),
963 0 : SecurityGroupList(),
964 0 : CommunityList(),
965 0 : PathPreference(),
966 0 : EcmpLoadBalance(),
967 0 : TagList(),
968 : nh_req,
969 : routing_vrf->vxlan_id(),
970 0 : VnListType());
971 0 : }
972 :
973 0 : std::vector<VnIpam> vn_ipam = (*it)->GetVnIpam();
974 0 : for (std::vector<VnIpam>::iterator vn_ipam_itr = vn_ipam.begin();
975 0 : vn_ipam_itr != vn_ipam.end(); vn_ipam_itr++) {
976 :
977 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
978 0 : nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
979 0 : nh_req.data.reset(new VrfNHData(false, false, false));
980 0 : bridge_vrf->GetInetUnicastRouteTable(vn_ipam_itr->ip_prefix)->
981 0 : AddEvpnRoutingRouteReq(vn_ipam_itr->ip_prefix, vn_ipam_itr->plen, routing_vrf,
982 0 : agent_->evpn_routing_peer(),
983 0 : SecurityGroupList(),
984 0 : CommunityList(),
985 0 : PathPreference(),
986 0 : EcmpLoadBalance(),
987 0 : TagList(),
988 : nh_req,
989 : routing_vrf->vxlan_id(),
990 0 : VnListType());
991 0 : }
992 0 : it++;
993 0 : }
994 0 : }
995 :
996 : /**
997 : * sandesh request
998 : */
999 0 : void VxlanRoutingManager::FillSandeshInfo(VxlanRoutingResp *resp) {
1000 : VxlanRoutingVrfMapper::LrVrfInfoMapIter it1 =
1001 0 : vrf_mapper_.lr_vrf_info_map_.begin();
1002 0 : std::vector<VxlanRoutingMap> vr_map;
1003 0 : while (it1 != vrf_mapper_.lr_vrf_info_map_.end()) {
1004 0 : VxlanRoutingMap vxlan_routing_map;
1005 0 : vxlan_routing_map.set_logical_router_uuid(UuidToString(it1->first));
1006 0 : vxlan_routing_map.set_routing_vrf(it1->second.routing_vrf_->
1007 : GetName());
1008 0 : vxlan_routing_map.set_parent_routing_vn(it1->second.routing_vn_->
1009 : GetName());
1010 : VxlanRoutingVrfMapper::RoutedVrfInfo::BridgeVnListIter it2 =
1011 0 : it1->second.bridge_vn_list_.begin();
1012 0 : while (it2 != it1->second.bridge_vn_list_.end()) {
1013 0 : VxlanRoutingBridgeVrf bridge_vrf;
1014 0 : if ((*it2)->GetVrf()) {
1015 0 : bridge_vrf.set_bridge_vrf((*it2)->GetVrf()->GetName());
1016 : }
1017 0 : bridge_vrf.set_bridge_vn((*it2)->GetName());
1018 0 : vxlan_routing_map.bridge_vrfs.push_back(bridge_vrf);
1019 0 : it2++;
1020 0 : }
1021 0 : vr_map.push_back(vxlan_routing_map);
1022 0 : it1++;
1023 0 : }
1024 0 : resp->set_vr_map(vr_map);
1025 0 : }
1026 :
1027 0 : void VxlanRoutingReq::HandleRequest() const {
1028 0 : VxlanRoutingResp *resp = new VxlanRoutingResp();
1029 0 : Agent *agent = Agent::GetInstance();
1030 : VxlanRoutingManager *vxlan_routing_mgr =
1031 0 : agent->oper_db()->vxlan_routing_manager();
1032 0 : if (vxlan_routing_mgr) {
1033 0 : resp->set_context(context());
1034 0 : vxlan_routing_mgr->FillSandeshInfo(resp);
1035 : }
1036 0 : resp->set_more(false);
1037 0 : resp->Response();
1038 0 : return;
1039 : }
|