Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <cmn/agent_cmn.h>
6 :
7 : #include <base/lifetime.h>
8 : #include <base/parse_object.h>
9 : #include <ifmap/ifmap_link.h>
10 : #include <ifmap/ifmap_table.h>
11 :
12 : #include <bgp_schema_types.h>
13 : #include <vnc_cfg_types.h>
14 :
15 : #include <init/agent_init.h>
16 : #include <cfg/cfg_init.h>
17 : #include <route/route.h>
18 : #include <oper/route_common.h>
19 : #include <oper/vn.h>
20 : #include <oper/vrf.h>
21 : #include <oper/peer.h>
22 : #include <oper/mirror_table.h>
23 : #include <oper/agent_route_walker.h>
24 : #include <controller/controller_init.h>
25 : #include <controller/controller_vrf_export.h>
26 : #include <oper/agent_sandesh.h>
27 : #include <oper/nexthop.h>
28 : #include <oper/config_manager.h>
29 : #include <oper/agent_route_resync.h>
30 : #include <resource_manager/resource_manager.h>
31 : #include <resource_manager/mpls_index.h>
32 : #include <resource_manager/vrf_index.h>
33 :
34 : #define MAX_VRF_DELETE_TIMEOUT_RETRY_COUNT 10
35 :
36 : using namespace std;
37 : using namespace autogen;
38 :
39 : VrfTable *VrfTable::vrf_table_;
40 :
41 : class VrfEntry::DeleteActor : public LifetimeActor {
42 : public:
43 8 : DeleteActor(VrfEntry *vrf) :
44 16 : LifetimeActor((static_cast<VrfTable *>(vrf->get_table()))->
45 8 : agent()->lifetime_manager()), table_(vrf, this) {
46 8 : }
47 16 : virtual ~DeleteActor() {
48 16 : }
49 8 : virtual bool MayDelete() const {
50 : //No table present, then this VRF can be deleted
51 8 : return table_->AllRouteTableDeleted();
52 : }
53 8 : virtual void Shutdown() {
54 8 : }
55 8 : virtual void Destroy() {
56 8 : table_->SendObjectLog(AgentLogEvent::DEL);
57 8 : table_ = NULL;
58 8 : }
59 :
60 : private:
61 : VrfEntryRef table_;
62 : };
63 :
64 1296 : VrfEntry::VrfEntry(const string &name, uint32_t flags, Agent *agent) :
65 2592 : name_(name), id_(kInvalidIndex), flags_(flags),
66 1296 : walkid_(DBTableWalker::kInvalidWalkerId), deleter_(NULL),
67 10368 : rt_table_db_(), delete_timeout_timer_(NULL),
68 1296 : table_label_(MplsTable::kInvalidLabel),
69 1296 : vxlan_id_(VxLanTable::kInvalidvxlan_id),
70 1296 : rt_table_delete_bmap_(0),
71 1296 : route_resync_walker_(NULL), allow_route_add_on_deleted_vrf_(false),
72 1296 : layer2_control_word_(false),
73 1296 : rd_(0), routing_vrf_(false), retries_(0),
74 1296 : hbf_rintf_(Interface::kInvalidIndex),
75 3888 : hbf_lintf_(Interface::kInvalidIndex), deleted_(false) {
76 1296 : nh_.reset();
77 1296 : }
78 :
79 2592 : VrfEntry::~VrfEntry() {
80 1296 : if (id_ != kInvalidIndex) {
81 8 : VrfTable *table = static_cast<VrfTable *>(get_table());
82 8 : SetNotify();
83 :
84 : //In case of PBB VRF is implictly created, hence upon
85 : //delete get the bmac VRF and trigger a notify,
86 : //so that if bridge domain is reused it can be recreated
87 8 : if (are_flags_set(VrfData::PbbVrf)) {
88 0 : table->VrfReuse(bmac_vrf_name_);
89 : }
90 8 : table->FreeVrfId(id_);
91 8 : table->VrfReuse(GetName());
92 8 : vrf_node_ptr_ = NULL;
93 : }
94 : //Delete timer
95 1296 : if (delete_timeout_timer_)
96 8 : TimerManager::DeleteTimer(delete_timeout_timer_);
97 2592 : }
98 :
99 3829 : bool VrfEntry::IsLess(const DBEntry &rhs) const {
100 3829 : const VrfEntry &a = static_cast<const VrfEntry &>(rhs);
101 3829 : return (name_ < a.name_);
102 : }
103 :
104 0 : string VrfEntry::ToString() const {
105 0 : return "VRF";
106 : }
107 :
108 57 : bool VrfEntry::UpdateVxlanId(Agent *agent, uint32_t new_vxlan_id) {
109 57 : bool ret = false;
110 57 : if (new_vxlan_id == vxlan_id_) {
111 51 : return ret;
112 : }
113 :
114 6 : vxlan_id_ = new_vxlan_id;
115 6 : return ret;
116 : }
117 :
118 0 : void VrfEntry::CreateTableLabel(bool learning_enabled, bool l2,
119 : bool flood_unknown_unicast,
120 : bool layer2_control_word) {
121 0 : l2_ = l2;
122 0 : VrfTable *table = static_cast<VrfTable *>(get_table());
123 0 : Agent *agent = table->agent();
124 :
125 : // Create VrfNH and assign label from it
126 0 : DBRequest nh_req;
127 0 : nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
128 0 : VrfNHKey *vrf_nh_key = new VrfNHKey(name_, false, l2);
129 0 : nh_req.key.reset(vrf_nh_key);
130 0 : nh_req.data.reset(new VrfNHData(flood_unknown_unicast, learning_enabled,
131 0 : layer2_control_word));
132 0 : agent->nexthop_table()->Process(nh_req);
133 :
134 : // Get label from nh
135 0 : NextHop *nh = static_cast<NextHop *>(
136 0 : agent->nexthop_table()->FindActiveEntry(vrf_nh_key));
137 0 : nh_ = nh;
138 0 : set_table_label(nh->mpls_label()->label());
139 0 : }
140 :
141 8 : void VrfEntry::CreateRouteTables() {
142 8 : DB *db = get_table()->database();
143 8 : VrfTable *table = static_cast<VrfTable *>(get_table());
144 :
145 56 : for (uint8_t type = (Agent::INVALID + 1); type < Agent::ROUTE_TABLE_MAX; type++) {
146 96 : rt_table_db_[type] = static_cast<AgentRouteTable *>
147 48 : (db->CreateTable(name_ +
148 48 : AgentRouteTable::GetSuffix(Agent::RouteTableType(type))));
149 48 : rt_table_db_[type]->SetVrf(this);
150 48 : table->dbtree_[type].insert(VrfTable::VrfDbPair(name_, rt_table_db_[type]));
151 : }
152 8 : }
153 :
154 8 : void VrfEntry::DeleteRouteTables() {
155 56 : for (int table_type = (Agent::INVALID + 1);
156 56 : table_type < Agent::ROUTE_TABLE_MAX; table_type++) {
157 48 : VrfTable *vrf_table = ((VrfTable *) get_table());
158 : AgentRouteTable *route_table =
159 48 : vrf_table->GetRouteTable(name_, table_type);
160 48 : if (route_table) {
161 48 : vrf_table->DeleteFromDbTree(table_type, name_);
162 48 : vrf_table->database()->RemoveTable(route_table);
163 48 : delete route_table;
164 : }
165 : }
166 8 : }
167 :
168 8 : void VrfEntry::PostAdd() {
169 8 : VrfTable *table = static_cast<VrfTable *>(get_table());
170 8 : Agent *agent = table->agent();
171 : // get_table() would return NULL in Add(), so move dependent functions and
172 : // initialization to PostAdd
173 8 : deleter_.reset(new DeleteActor(this));
174 8 : if (route_resync_walker_.get() == NULL) {
175 : route_resync_walker_ = new AgentRouteResync("VrfRouteResyncWalker",
176 8 : agent);
177 : agent->oper_db()->agent_route_walk_manager()->
178 8 : RegisterWalker(static_cast<AgentRouteWalker *>
179 : (route_resync_walker_.get()));
180 : }
181 : // Create the route-tables and insert them into dbtree_
182 8 : CreateRouteTables();
183 :
184 8 : uint32_t vxlan_id = VxLanTable::kInvalidvxlan_id;
185 8 : if (vn_) {
186 0 : vxlan_id = vn_->GetVxLanId();
187 : }
188 8 : UpdateVxlanId(agent, vxlan_id);
189 :
190 : // Add the L2 Receive routes for VRRP mac
191 8 : BridgeAgentRouteTable *l2_table = static_cast<BridgeAgentRouteTable *>
192 : (rt_table_db_[Agent::BRIDGE]);
193 8 : l2_table->AddBridgeReceiveRoute(agent->local_vm_peer(), name_, 0,
194 : agent->vrrp_mac(), "");
195 8 : l2_table->AddBridgeReceiveRoute(agent->local_peer(), name_,
196 : agent->left_si_mac(), "", "pkt0", true);
197 8 : l2_table->AddBridgeReceiveRoute(agent->local_peer(), name_,
198 : agent->right_si_mac(), "", "pkt0", true);
199 :
200 : // Add the L2 Receive routes for xconnect interface to vhost
201 : // Note, vhost is not created when fabric VRF is created. We only need
202 : // VRRP MAC on fabric vrf. So, we are good for now
203 8 : const VmInterface *vhost = dynamic_cast<const VmInterface *>
204 8 : (agent->vhost_interface());
205 8 : if (vhost && vhost->parent_list().empty() == false) {
206 12 : for (size_t i = 0; i < vhost->parent_list().size(); i++) {
207 18 : l2_table->AddBridgeReceiveRoute(agent->local_vm_peer(), name_, 0,
208 12 : vhost->parent_list()[i]->mac(), "");
209 : }
210 : }
211 :
212 : //Add receive route for vmware physical interface mac, so
213 : //that packets hitting this mac gets routed(inter-vn traffic)
214 8 : if (agent->isVmwareMode()) {
215 0 : PhysicalInterfaceKey key(agent->params()->vmware_physical_port());
216 0 : Interface *intf = static_cast<Interface *>
217 0 : (agent->interface_table()->FindActiveEntry(&key));
218 0 : if (intf) {
219 0 : l2_table->AddBridgeReceiveRoute(agent->local_vm_peer(), name_, 0,
220 : intf->mac(), "");
221 : }
222 0 : }
223 :
224 8 : SendObjectLog(AgentLogEvent::ADD);
225 8 : }
226 :
227 226 : DBEntryBase::KeyPtr VrfEntry::GetDBRequestKey() const {
228 226 : VrfKey *key = new VrfKey(name_);
229 226 : return DBEntryBase::KeyPtr(key);
230 : }
231 :
232 0 : void VrfEntry::SetKey(const DBRequestKey *key) {
233 0 : const VrfKey *k = static_cast<const VrfKey *>(key);
234 0 : name_ = k->name_;
235 0 : }
236 :
237 6 : InetUnicastRouteEntry *VrfEntry::GetUcRoute(const IpAddress &addr) const {
238 6 : InetUnicastAgentRouteTable *table = NULL;
239 6 : if (addr.is_v4()) {
240 6 : table = GetInet4UnicastRouteTable();
241 0 : } else if (addr.is_v6()) {
242 0 : table = GetInet6UnicastRouteTable();
243 : }
244 6 : if (table == NULL)
245 0 : return NULL;
246 :
247 6 : return table->FindLPM(addr);
248 : }
249 :
250 154 : InetUnicastRouteEntry *VrfEntry::GetUcRoute(const InetUnicastRouteEntry &rt_key) const {
251 154 : InetUnicastAgentRouteTable *table = NULL;
252 :
253 154 : if (rt_key.prefix_address().is_v4()) {
254 154 : table = GetInet4UnicastRouteTable();
255 0 : } else if (rt_key.prefix_address().is_v6()) {
256 0 : table = GetInet6UnicastRouteTable();
257 : }
258 154 : if (table == NULL)
259 0 : return NULL;
260 :
261 154 : return table->FindLPM(rt_key);
262 : }
263 :
264 48 : LifetimeActor *VrfEntry::deleter() {
265 48 : return deleter_.get();
266 : }
267 :
268 10 : bool VrfEntry::AllRouteTableDeleted() const {
269 58 : for (int i = Agent::INET4_UNICAST; i < Agent::ROUTE_TABLE_MAX; i++) {
270 50 : if ((rt_table_delete_bmap_ & (1 << i)) == 0)
271 2 : return false;
272 : }
273 :
274 8 : return true;
275 : }
276 :
277 2661 : bool VrfEntry::RouteTableDeleted(uint8_t table_type) const {
278 2661 : return (rt_table_delete_bmap_ & (1 << table_type));
279 : }
280 :
281 48 : void VrfEntry::SetRouteTableDeleted(uint8_t table_type) {
282 48 : rt_table_delete_bmap_ |= (1 << table_type);
283 48 : }
284 :
285 2661 : AgentRouteTable *VrfEntry::GetRouteTable(uint8_t table_type) const {
286 2661 : return (RouteTableDeleted(table_type) ? NULL : rt_table_db_[table_type]);
287 : }
288 :
289 0 : const std::string VrfEntry::GetTableTypeString(uint8_t table_type) const {
290 0 : switch (table_type) {
291 0 : case Agent::INET4_UNICAST: {
292 0 : return "inet4_unicast";
293 : break;
294 : }
295 0 : case Agent::INET4_MPLS: {
296 0 : return "inet4_mpls";
297 : break;
298 : }
299 0 : case Agent::INET6_UNICAST: {
300 0 : return "inet6_unicast";
301 : break;
302 : }
303 0 : case Agent::INET4_MULTICAST: {
304 0 : return "inet4_multicast";
305 : break;
306 : }
307 0 : case Agent::BRIDGE: {
308 0 : return "bridge";
309 : break;
310 : }
311 0 : case Agent::EVPN: {
312 0 : return "evpn";
313 : break;
314 : }
315 : }
316 0 : return "None";
317 : }
318 :
319 538 : InetUnicastAgentRouteTable *VrfEntry::GetInet4UnicastRouteTable() const {
320 538 : return static_cast<InetUnicastAgentRouteTable *>(GetRouteTable(Agent::INET4_UNICAST));
321 : }
322 :
323 10 : InetUnicastAgentRouteTable *VrfEntry::GetInet4MplsUnicastRouteTable() const {
324 10 : return static_cast<InetUnicastAgentRouteTable *>(GetRouteTable(Agent::INET4_MPLS));
325 : }
326 9 : AgentRouteTable *VrfEntry::GetInet4MulticastRouteTable() const {
327 9 : return GetRouteTable(Agent::INET4_MULTICAST);
328 : }
329 :
330 190 : AgentRouteTable *VrfEntry::GetEvpnRouteTable() const {
331 190 : return GetRouteTable(Agent::EVPN);
332 : }
333 :
334 336 : AgentRouteTable *VrfEntry::GetBridgeRouteTable() const {
335 336 : return GetRouteTable(Agent::BRIDGE);
336 : }
337 :
338 91 : InetUnicastAgentRouteTable *VrfEntry::GetInet6UnicastRouteTable() const {
339 91 : return static_cast<InetUnicastAgentRouteTable *>(GetRouteTable(Agent::INET6_UNICAST));
340 : }
341 :
342 0 : bool VrfEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
343 0 : VrfListResp *resp = static_cast<VrfListResp *>(sresp);
344 :
345 0 : if (name.empty() || GetName().find(name) != string::npos) {
346 0 : VrfSandeshData data;
347 0 : data.set_name(GetName());
348 0 : data.set_ucindex(vrf_id());
349 0 : data.set_mcindex(vrf_id());
350 0 : data.set_evpnindex(vrf_id());
351 0 : data.set_l2index(vrf_id());
352 0 : data.set_brindex(vrf_id());
353 0 : data.set_uc6index(vrf_id());
354 0 : std::string vrf_flags;
355 0 : if (flags() & VrfData::ConfigVrf)
356 0 : vrf_flags += "Config; ";
357 0 : if (flags() & VrfData::GwVrf)
358 0 : vrf_flags += "Gateway; ";
359 0 : if (flags() & VrfData::PbbVrf)
360 0 : vrf_flags += "PBB C-Vrf";
361 0 : data.set_source(vrf_flags);
362 0 : if (vn_.get()) {
363 0 : data.set_vn(vn_->GetName());
364 : } else {
365 0 : data.set_vn("N/A");
366 : }
367 0 : data.set_table_label(table_label());
368 0 : VrfTable *table = static_cast<VrfTable *>(get_table());
369 0 : stringstream rd;
370 0 : rd << table->agent()->compute_node_ip().to_string() << ":" <<
371 0 : RDInstanceId(table->agent()->tor_agent_enabled());
372 0 : data.set_RD(rd.str());
373 :
374 : std::vector<VrfSandeshData> &list =
375 0 : const_cast<std::vector<VrfSandeshData>&>(resp->get_vrf_list());
376 0 : data.set_vxlan_id(vxlan_id_);
377 0 : data.set_mac_aging_time(mac_aging_time_);
378 0 : data.set_layer2_control_word(layer2_control_word_);
379 0 : if (forwarding_vrf_.get()) {
380 0 : data.set_forwarding_vrf(forwarding_vrf_->name_);
381 : }
382 0 : data.set_hbf_rintf(hbf_rintf());
383 0 : data.set_hbf_lintf(hbf_lintf());
384 0 : list.push_back(data);
385 0 : return true;
386 0 : }
387 :
388 0 : return false;
389 : }
390 :
391 24 : void VrfEntry::SendObjectLog(AgentLogEvent::type event) const {
392 48 : VrfObjectLogInfo vrf;
393 24 : string str;
394 24 : switch (event) {
395 8 : case AgentLogEvent::ADD:
396 8 : str.assign("Addition ");
397 8 : break;
398 8 : case AgentLogEvent::DEL:
399 8 : str.assign("Deletion ");
400 8 : break;
401 0 : case AgentLogEvent::CHANGE:
402 0 : str.assign("Modification ");
403 0 : break;
404 8 : case AgentLogEvent::DELETE_TRIGGER:
405 8 : str.assign("Deletion Triggered ");
406 8 : break;
407 0 : default:
408 0 : str.assign("");
409 0 : break;
410 : }
411 24 : vrf.set_event(str);
412 24 : vrf.set_name(name_);
413 24 : vrf.set_index(id_);
414 24 : VRF_OBJECT_LOG_LOG("AgentVrf", SandeshLevel::SYS_INFO, vrf);
415 24 : }
416 :
417 0 : bool VrfEntry::DeleteTimeout() {
418 0 : uint32_t num_routes = 0;
419 0 : for (uint8_t type = (Agent::INVALID + 1);
420 0 : type < Agent::ROUTE_TABLE_MAX;
421 : type++) {
422 0 : num_routes += rt_table_db_[type]->Size();
423 : }
424 0 : if (num_routes) {
425 0 : std::ostringstream str;
426 0 : str << "Unicast routes: " << rt_table_db_[Agent::INET4_UNICAST]->Size();
427 0 : str << "Unicast MPLS routes: " << rt_table_db_[Agent::INET4_MPLS]->Size();
428 0 : str << " Mutlicast routes: " << rt_table_db_[Agent::INET4_MULTICAST]->Size();
429 0 : str << " EVPN routes: " << rt_table_db_[Agent::EVPN]->Size();
430 0 : str << " Bridge routes: " << rt_table_db_[Agent::BRIDGE]->Size();
431 0 : str << "Unicast v6 routes: " << rt_table_db_[Agent::INET6_UNICAST]->Size();
432 0 : str << " Reference: " << GetRefCount();
433 0 : OPER_TRACE_ENTRY(Vrf, static_cast<const AgentDBTable *>(get_table()),
434 : "VRF delete failed, " + str.str(), name_);
435 0 : assert(0);
436 : return false;
437 0 : }
438 :
439 : // if number of routes is 0, and VRF ref count is non zero
440 : // then only reschedule delete timout
441 0 : if (retries_ >= MAX_VRF_DELETE_TIMEOUT_RETRY_COUNT) {
442 0 : OPER_TRACE_ENTRY(Vrf, static_cast<const AgentDBTable *>(get_table()),
443 : "VRF delete failed with max retries", name_);
444 0 : assert(0);
445 : return false;
446 : }
447 0 : retries_ = retries_+1;
448 0 : return true;
449 : }
450 :
451 8 : void VrfEntry::StartDeleteTimer() {
452 8 : Agent *agent = (static_cast<VrfTable *>(get_table()))->agent();
453 16 : delete_timeout_timer_ = TimerManager::CreateTimer(
454 8 : *(agent->event_manager())->io_service(),
455 : "VrfDeleteTimer");
456 8 : delete_timeout_timer_->Start(kDeleteTimeout,
457 : boost::bind(&VrfEntry::DeleteTimeout,
458 : this));
459 8 : }
460 :
461 8 : void VrfEntry::CancelDeleteTimer() {
462 8 : delete_timeout_timer_->Cancel();
463 8 : }
464 :
465 0 : bool VrfEntry::ResetVrfDelete() {
466 0 : delete_reuse_mutex_.lock();
467 0 : if (deleted_ == true) {
468 0 : delete_reuse_mutex_.unlock();
469 0 : return false;
470 : }
471 0 : if (AllRouteTablesEmpty()) {
472 0 : if (!AllRouteTableDeleted() ||
473 0 : deleter_->HasRefcount() ||
474 0 : deleter_->HasDependents()) {
475 0 : delete_reuse_mutex_.unlock();
476 0 : return false;
477 : }
478 0 : if (route_resync_walker_.get() != NULL) {
479 0 : if (route_resync_walker_.get()->refcount() > 1 ||
480 0 : route_resync_walker_.get()->IsValidDeleteWalkRef() ||
481 0 : route_resync_walker_.get()->IsValidVrfWalkRef() ||
482 0 : route_resync_walker_.get()->IsDeregisterDone() == false) {
483 0 : delete_reuse_mutex_.unlock();
484 0 : return false;
485 : }
486 : }
487 0 : ClearDelete();
488 0 : delete_reuse_mutex_.unlock();
489 0 : CancelDeleteTimer();
490 0 : rt_table_delete_bmap_ = 0;
491 0 : DeleteRouteTables();
492 0 : deleter_.reset(new DeleteActor(this));
493 0 : CreateRouteTables();
494 0 : VrfTable *table = static_cast<VrfTable *>(get_table());
495 0 : Agent *agent = table->agent();
496 0 : route_resync_walker_.reset(new AgentRouteResync("VrfRouteResyncWalker",
497 0 : agent));
498 : agent->oper_db()->agent_route_walk_manager()->
499 0 : RegisterWalker(static_cast<AgentRouteWalker *>
500 : (route_resync_walker_.get()));
501 0 : SetNotify();
502 0 : table->VrfReuse(GetName());
503 0 : vrf_node_ptr_ = NULL;
504 0 : retries_ = 0;
505 0 : if (delete_timeout_timer_)
506 0 : TimerManager::DeleteTimer(delete_timeout_timer_);
507 :
508 0 : OPER_TRACE_ENTRY(Vrf, static_cast<const AgentDBTable *>(get_table()),
509 : "Reset Vrf Deletion", GetName());
510 0 : return true;
511 : }
512 0 : delete_reuse_mutex_.unlock();
513 0 : return false;
514 : }
515 :
516 6 : void VrfEntry::ResyncRoutes() {
517 6 : (static_cast<AgentRouteResync *>(route_resync_walker_.get()))->
518 6 : UpdateRoutesInVrf(this);
519 6 : }
520 :
521 : // Used to decide RD to be sent to CN for this VRF.
522 : // In non tor-agent case vrf-id generated is used.
523 : // However in tor-agent vn id(network-id) is used. This is because both active
524 : // and backup TA can publish same route which will be sent to BGP router peered
525 : // to CN. If both these TA end up generating different vrf-id for same Vrf, then
526 : // RD using vrf_id will be different. Hence BGP router will get same route with
527 : // two different RD causing undefined behavior.
528 : // To avoid this both TA should generate same RD. As VN id is generated by config
529 : // it is unique and common across both TA so same can be used.
530 49 : int VrfEntry::RDInstanceId(bool tor_agent_enabled) const {
531 49 : if (tor_agent_enabled == false) {
532 49 : return id_;
533 : }
534 :
535 0 : if (vn() == NULL)
536 0 : return kInvalidIndex;
537 :
538 0 : if (vn()->vnid() == 0)
539 0 : return kInvalidIndex;
540 :
541 0 : return vn()->vnid();
542 : }
543 :
544 203 : void VrfEntry::RetryDelete() {
545 203 : if (AllRouteTablesEmpty() == false)
546 9 : return;
547 :
548 : // Enqueue a DB Request to notify the entry, entry should always be
549 : // notified in db::DBTable task context
550 194 : DBRequest req(DBRequest::DB_ENTRY_NOTIFY);
551 194 : req.key = GetDBRequestKey();
552 194 : (static_cast<VrfTable *>(get_table()))->Enqueue(&req);
553 194 : }
554 :
555 404 : bool VrfEntry::AllRouteTablesEmpty() const {
556 1751 : for (uint8_t type = (Agent::INVALID + 1);
557 1751 : type < Agent::ROUTE_TABLE_MAX;
558 : type++) {
559 1551 : if (rt_table_db_[type]->empty() == false) {
560 204 : return false;
561 : }
562 : }
563 200 : return true;
564 : }
565 :
566 8 : void VrfEntry::ReleaseWalker() {
567 8 : if (route_resync_walker_.get() != NULL) {
568 8 : VrfTable *table = static_cast<VrfTable *>(get_table());
569 : table->agent()->oper_db()->agent_route_walk_manager()->
570 8 : ReleaseWalker(route_resync_walker_.get());
571 : }
572 8 : }
573 :
574 : InetUnicastAgentRouteTable *
575 105 : VrfEntry::GetInetUnicastRouteTable(const IpAddress &addr) const {
576 105 : if (addr.is_v4())
577 : return static_cast<InetUnicastAgentRouteTable *>
578 105 : (GetInet4UnicastRouteTable());
579 : return static_cast<InetUnicastAgentRouteTable *>
580 0 : (GetInet6UnicastRouteTable());
581 : }
582 :
583 8 : void VrfEntry::SetNotify() {
584 8 : VrfTable *table = static_cast<VrfTable *>(get_table());
585 8 : if (vrf_node_ptr_) {
586 : IFMapDependencyManager *dep = table->agent()->
587 6 : oper_db()->dependency_manager();
588 6 : IFMapNodeState *state = vrf_node_ptr_.get();
589 6 : dep->SetNotify(state->node(), true);
590 : }
591 8 : }
592 :
593 : class VrfDeleteWalker : public AgentRouteWalker {
594 : public:
595 0 : VrfDeleteWalker(const std::string &name, Agent *agent) :
596 0 : AgentRouteWalker(name, agent) {
597 0 : }
598 :
599 0 : ~VrfDeleteWalker() { }
600 :
601 : //Override vrf notification
602 0 : bool VrfWalkNotify(DBTablePartBase *partition, DBEntryBase *e) {
603 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
604 0 : req.key = e->GetDBRequestKey();
605 0 : (static_cast<VrfTable *>(e->get_table()))->Process(req);
606 0 : return true;
607 0 : }
608 :
609 : //Override route notification
610 0 : bool RouteWalkNotify(DBTablePartBase *partition, DBEntryBase *e) {
611 0 : assert(0);
612 : return false;
613 : }
614 :
615 0 : static void WalkDone(VrfDeleteWalker *walker) {
616 0 : walker->mgr()->ReleaseWalker(walker);
617 0 : walker->agent()->vrf_table()->reset_vrf_delete_walker();
618 0 : }
619 :
620 : private:
621 : };
622 :
623 8 : void VrfTable::FreeVrfId(size_t index) {
624 8 : agent()->resource_manager()->Release(Resource::VRF_INDEX, index);
625 8 : index_table_.Remove(index);
626 8 : };
627 0 : void VrfTable::Clear() {
628 0 : if (route_delete_walker_.get())
629 : agent()->oper_db()->agent_route_walk_manager()->
630 0 : ReleaseWalker(route_delete_walker_.get());
631 0 : if (vrf_delete_walker_.get() != NULL)
632 : agent()->oper_db()->agent_route_walk_manager()->
633 0 : ReleaseWalker(vrf_delete_walker_.get());
634 0 : }
635 :
636 1288 : std::unique_ptr<DBEntry> VrfTable::AllocEntry(const DBRequestKey *k) const {
637 1288 : const VrfKey *key = static_cast<const VrfKey *>(k);
638 1288 : VrfEntry *vrf = new VrfEntry(key->name_, 0, agent());
639 1288 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vrf));
640 : }
641 :
642 9 : VrfTable::~VrfTable() {
643 11 : }
644 :
645 8 : DBEntry *VrfTable::OperDBAdd(const DBRequest *req) {
646 8 : VrfKey *key = static_cast<VrfKey *>(req->key.get());
647 8 : VrfData *data = static_cast<VrfData *>(req->data.get());
648 8 : VrfEntry *vrf = new VrfEntry(key->name_, data->flags_, agent());
649 :
650 : // Add VRF into name based tree
651 8 : if (FindVrfFromName(key->name_)) {
652 0 : delete vrf;
653 0 : assert(0);
654 : return NULL;
655 : }
656 8 : if (vrf) {
657 : ResourceManager::KeyPtr rkey(new VrfIndexResourceKey(
658 8 : agent()->resource_manager(), key->name_));
659 16 : vrf->id_ = static_cast<IndexResourceData *>(agent()->resource_manager()->
660 8 : Allocate(rkey).get())->index();
661 8 : index_table_.InsertAtIndex(vrf->id_, vrf);
662 8 : }
663 8 : name_tree_.insert( VrfNamePair(key->name_, vrf));
664 :
665 8 : vrf->vn_.reset(agent()->vn_table()->Find(data->vn_uuid_));
666 8 : if (vrf->vn_) {
667 0 : vrf->set_routing_vrf(vrf->vn_->vxlan_routing_vn());
668 : }
669 :
670 8 : vrf->si_vn_ref_.reset(agent()->vn_table()->Find(data->si_vn_ref_uuid_));
671 :
672 8 : vrf->isid_ = data->isid_;
673 8 : vrf->bmac_vrf_name_ = data->bmac_vrf_name_;
674 8 : vrf->learning_enabled_ = data->learning_enabled_;
675 8 : vrf->mac_aging_time_ = data->mac_aging_time_;
676 8 : vrf->set_hbf_rintf(data->hbf_rintf_);
677 8 : vrf->set_hbf_lintf(data->hbf_lintf_);
678 8 : if (vrf->vn_.get()) {
679 0 : vrf->layer2_control_word_ = vrf->vn_->layer2_control_word();
680 : }
681 8 : vrf->set_rd(vrf->RDInstanceId(agent()->tor_agent_enabled()));
682 8 : if (data->forwarding_vrf_name_ != Agent::NullString()) {
683 1 : vrf->forwarding_vrf_ = FindVrfFromName(data->forwarding_vrf_name_);
684 : }
685 8 : return vrf;
686 : }
687 :
688 41 : bool VrfTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
689 41 : bool ret = false;
690 41 : VrfEntry *vrf = static_cast<VrfEntry *>(entry);
691 41 : VrfData *data = static_cast<VrfData *>(req->data.get());
692 41 : vrf->set_flags(data->flags_);
693 :
694 41 : if (vrf->are_flags_set(VrfData::PbbVrf)) {
695 0 : if (FindVrfFromName(vrf->bmac_vrf_name_) == NULL) {
696 0 : assert(0);
697 : }
698 : }
699 :
700 41 : VnEntry *vn = agent()->vn_table()->Find(data->vn_uuid_);
701 41 : bool resync_routes = false;
702 :
703 41 : if (vn != vrf->vn_.get()) {
704 6 : resync_routes = true;
705 6 : vrf->vn_.reset(vn);
706 6 : ret = true;
707 : }
708 :
709 41 : VnEntry *si_vn_ref = agent()->vn_table()->Find(data->si_vn_ref_uuid_);
710 41 : if (si_vn_ref != vrf->si_vn_ref_.get()) {
711 0 : vrf->si_vn_ref_.reset(si_vn_ref);
712 : }
713 :
714 41 : if (data->ifmap_node() && vrf->ifmap_node() != data->ifmap_node()) {
715 0 : ret = true;
716 : }
717 :
718 41 : bool layer2_control_word = false;
719 41 : if (vn) {
720 18 : layer2_control_word = vn->layer2_control_word();
721 : }
722 :
723 41 : if (vrf->layer2_control_word_ != layer2_control_word) {
724 0 : vrf->layer2_control_word_ = layer2_control_word;
725 0 : vrf->ResyncRoutes();
726 0 : ret = true;
727 : }
728 :
729 41 : if (vrf->learning_enabled_ != data->learning_enabled_) {
730 0 : vrf->learning_enabled_ = data->learning_enabled_;
731 0 : ret = true;
732 : }
733 :
734 41 : if (vrf->isid_ != data->isid_) {
735 0 : vrf->isid_ = data->isid_;
736 0 : ret = true;
737 : }
738 :
739 41 : if (vrf->rd() != vrf->RDInstanceId(agent()->tor_agent_enabled())) {
740 0 : resync_routes = true;
741 0 : vrf->set_rd(vrf->RDInstanceId(agent()->tor_agent_enabled()));
742 0 : ret = true;
743 : }
744 :
745 41 : if (resync_routes) {
746 6 : vrf->ResyncRoutes();
747 : }
748 :
749 41 : uint32_t vxlan_id = VxLanTable::kInvalidvxlan_id;
750 41 : if (vn) {
751 18 : vxlan_id = vn->GetVxLanId();
752 : }
753 41 : vrf->UpdateVxlanId(agent(), vxlan_id);
754 :
755 41 : if (data && vrf->mac_aging_time_ != data->mac_aging_time_) {
756 0 : vrf->mac_aging_time_ = data->mac_aging_time_;
757 : }
758 :
759 41 : VrfEntry *forwarding_vrf = NULL;
760 41 : if (data->forwarding_vrf_name_ != Agent::NullString()) {
761 0 : forwarding_vrf = FindVrfFromName(data->forwarding_vrf_name_);
762 : }
763 :
764 41 : if (forwarding_vrf != vrf->forwarding_vrf_) {
765 0 : vrf->forwarding_vrf_ = forwarding_vrf;
766 0 : ret = true;
767 : }
768 :
769 41 : if (vrf->hbf_rintf() != data->hbf_rintf_) {
770 0 : vrf->set_hbf_rintf(data->hbf_rintf_);
771 0 : ret = true;
772 : }
773 41 : if (vrf->hbf_lintf() != data->hbf_lintf_) {
774 0 : vrf->set_hbf_lintf(data->hbf_lintf_);
775 0 : ret = true;
776 : }
777 :
778 41 : return ret;
779 : }
780 :
781 8 : bool VrfTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
782 8 : VrfEntry *vrf = static_cast<VrfEntry *>(entry);
783 8 : VrfData *data = static_cast<VrfData *>(req->data.get());
784 :
785 : // VRF can be created by both config and VGW. VRF cannot be deleted till
786 : // both config and VGW delete it.
787 : // We want to retain flags like PbbVrf, hence mask only flags which
788 : // are needed to delete the VRF
789 8 : vrf->flags_ &= ~(data->flags_ & data->ConfigFlags());
790 8 : if ((vrf->flags_ & data->ConfigFlags()) != 0)
791 0 : return false;
792 :
793 : // Delete the L2 Receive routes added by default
794 8 : BridgeAgentRouteTable *l2_table = static_cast<BridgeAgentRouteTable *>
795 : (vrf->rt_table_db_[Agent::BRIDGE]);
796 8 : l2_table->Delete(agent()->local_vm_peer(), vrf->GetName(),
797 8 : agent()->vrrp_mac(), 0);
798 8 : l2_table->Delete(agent()->local_peer(), vrf->GetName(),
799 8 : agent()->left_si_mac(), -1);
800 8 : l2_table->Delete(agent()->local_peer(), vrf->GetName(),
801 8 : agent()->right_si_mac(), -1);
802 8 : const VmInterface *vhost = dynamic_cast<const VmInterface *>
803 8 : (agent()->vhost_interface());
804 8 : if (vhost && vhost->parent_list().empty() == false) {
805 14 : for (size_t i = 0; i < vhost->parent_list().size(); i++) {
806 7 : l2_table->Delete(agent()->local_vm_peer(), vrf->GetName(),
807 14 : vhost->parent_list()[i]->mac(), 0);
808 : }
809 : }
810 :
811 8 : if (agent()->isVmwareMode()) {
812 0 : PhysicalInterfaceKey key(agent()->params()->vmware_physical_port());
813 0 : Interface *intf = static_cast<Interface *>
814 0 : (agent()->interface_table()->FindActiveEntry(&key));
815 0 : if (intf) {
816 0 : l2_table->Delete(agent()->local_vm_peer(), vrf->GetName(),
817 : intf->mac(), 0);
818 : }
819 0 : }
820 :
821 8 : vrf->UpdateVxlanId(agent(), VxLanTable::kInvalidvxlan_id);
822 8 : vrf->vn_.reset(NULL);
823 8 : if (vrf->table_label() != MplsTable::kInvalidLabel) {
824 0 : vrf->nh_.reset();
825 0 : vrf->set_table_label(MplsTable::kInvalidLabel);
826 : }
827 8 : vrf->deleter_->Delete();
828 8 : vrf->StartDeleteTimer();
829 8 : vrf->SendObjectLog(AgentLogEvent::DELETE_TRIGGER);
830 :
831 :
832 8 : if (vrf->ifmap_node()) {
833 6 : IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
834 6 : vrf->vrf_node_ptr_ = dep->SetState(vrf->ifmap_node());
835 6 : dep->SetNotify(vrf->ifmap_node(), false);
836 : }
837 8 : vrf->ReleaseWalker();
838 :
839 8 : return true;
840 : }
841 :
842 8 : void VrfTable::VrfReuse(const std::string name) {
843 8 : IFMapTable::RequestKey req_key;
844 8 : req_key.id_type = "routing-instance";
845 8 : req_key.id_name = name;
846 8 : IFMapNode *node = IFMapAgentTable::TableEntryLookup(database(), &req_key);
847 :
848 8 : if (!node || node->IsDeleted()) {
849 8 : return;
850 : }
851 :
852 0 : OPER_TRACE(Vrf, "Resyncing configuration for VRF: ", name);
853 0 : agent()->config_manager()->NodeResync(node);
854 8 : }
855 :
856 8 : void VrfTable::OnZeroRefcount(AgentDBEntry *e) {
857 8 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
858 8 : std::scoped_lock lock(vrf->delete_reuse_mutex_);
859 8 : if (e->IsDeleted()) {
860 8 : vrf->DeleteRouteTables();
861 8 : name_tree_.erase(vrf->GetName());
862 8 : vrf->CancelDeleteTimer();
863 8 : vrf->deleted_ = true;
864 : }
865 8 : }
866 :
867 1 : DBTableBase *VrfTable::CreateTable(DB *db, const std::string &name) {
868 1 : vrf_table_ = new VrfTable(db, name);
869 1 : vrf_table_->Init();
870 1 : return vrf_table_;
871 : };
872 :
873 1285 : VrfEntry *VrfTable::FindVrfFromName(const string &name) {
874 1285 : VrfNameTree::const_iterator it;
875 :
876 1285 : it = name_tree_.find(name);
877 1285 : if (it == name_tree_.end()) {
878 13 : return NULL;
879 : }
880 :
881 1272 : return static_cast<VrfEntry *>(it->second);
882 : }
883 :
884 2728 : VrfEntry *VrfTable::FindVrfFromId(size_t index) {
885 2728 : VrfEntry *vrf = index_table_.At(index);
886 2728 : if (vrf && vrf->IsDeleted() == false) {
887 2348 : return vrf;
888 : }
889 380 : return NULL;
890 : }
891 :
892 168 : VrfEntry *VrfTable::FindVrfFromIdIncludingDeletedVrf(size_t index) {
893 168 : VrfEntry *vrf = index_table_.At(index);
894 168 : return vrf;
895 : }
896 :
897 120 : InetUnicastAgentRouteTable *VrfTable::GetInet4UnicastRouteTable
898 : (const string &vrf_name) {
899 : return static_cast<InetUnicastAgentRouteTable *>
900 120 : (GetRouteTable(vrf_name, Agent::INET4_UNICAST));
901 : }
902 :
903 1 : InetUnicastAgentRouteTable *VrfTable::GetInet4MplsUnicastRouteTable
904 : (const string &vrf_name) {
905 : return static_cast<InetUnicastAgentRouteTable *>
906 1 : (GetRouteTable(vrf_name, Agent::INET4_MPLS));
907 : }
908 :
909 0 : AgentRouteTable *VrfTable::GetInet4MulticastRouteTable(const string &vrf_name) {
910 0 : return GetRouteTable(vrf_name, Agent::INET4_MULTICAST);
911 : }
912 :
913 89 : AgentRouteTable *VrfTable::GetEvpnRouteTable(const string &vrf_name) {
914 89 : return GetRouteTable(vrf_name, Agent::EVPN);
915 : }
916 :
917 175 : AgentRouteTable *VrfTable::GetBridgeRouteTable(const string &vrf_name) {
918 175 : return GetRouteTable(vrf_name, Agent::BRIDGE);
919 : }
920 :
921 39 : InetUnicastAgentRouteTable *VrfTable::GetInet6UnicastRouteTable
922 : (const string &vrf_name) {
923 : return static_cast<InetUnicastAgentRouteTable *>
924 39 : (GetRouteTable(vrf_name, Agent::INET6_UNICAST));
925 : }
926 :
927 472 : AgentRouteTable *VrfTable::GetRouteTable(const string &vrf_name,
928 : uint8_t table_type) {
929 472 : VrfDbTree::const_iterator it;
930 :
931 472 : it = dbtree_[table_type].find(vrf_name);
932 472 : if (it == dbtree_[table_type].end()) {
933 0 : return NULL;
934 : }
935 :
936 472 : return static_cast<AgentRouteTable *>(it->second);
937 : }
938 :
939 0 : void VrfTable::CreateVrfReq(const string &name, uint32_t flags) {
940 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
941 0 : req.key.reset(new VrfKey(name));
942 0 : req.data.reset(new VrfData(agent(), NULL, flags, boost::uuids::nil_uuid(),
943 0 : 0, "", 0, false));
944 0 : Enqueue(&req);
945 0 : }
946 :
947 0 : void VrfTable::CreateVrfReq(const string &name,
948 : const boost::uuids::uuid &vn_uuid,
949 : uint32_t flags) {
950 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
951 0 : req.key.reset(new VrfKey(name));
952 0 : req.data.reset(new VrfData(agent(), NULL, flags, vn_uuid,
953 0 : 0, "", 0, false));
954 0 : Enqueue(&req);
955 0 : }
956 :
957 0 : void VrfTable::CreateVrf(const string &name, const boost::uuids::uuid &vn_uuid,
958 : uint32_t flags, uint32_t isid,
959 : const std::string &bmac_vrf_name,
960 : uint32_t aging_timeout,
961 : bool learning_enabled) {
962 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
963 0 : req.key.reset(new VrfKey(name));
964 0 : req.data.reset(new VrfData(agent(), NULL, flags, vn_uuid, isid,
965 : bmac_vrf_name, aging_timeout,
966 0 : learning_enabled));
967 0 : Process(req);
968 0 : }
969 :
970 1 : void VrfTable::CreateVrf(const string &name,
971 : const boost::uuids::uuid &vn_uuid,
972 : uint32_t flags) {
973 1 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
974 1 : req.key.reset(new VrfKey(name));
975 2 : req.data.reset(new VrfData(agent(), NULL, flags, vn_uuid, 0,
976 1 : "", 0, false));
977 1 : Process(req);
978 1 : }
979 3 : void VrfTable::DeleteVrfReq(const string &name, uint32_t flags) {
980 3 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
981 3 : req.key.reset(new VrfKey(name));
982 6 : req.data.reset(new VrfData(agent(), NULL, flags, boost::uuids::nil_uuid(),
983 3 : 0, "", 0, false));
984 3 : Enqueue(&req);
985 3 : }
986 :
987 0 : void VrfTable::DeleteVrf(const string &name, uint32_t flags) {
988 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
989 0 : req.key.reset(new VrfKey(name));
990 0 : req.data.reset(new VrfData(agent(), NULL, flags, boost::uuids::nil_uuid(),
991 0 : 0, "", 0, false));
992 0 : Process(req);
993 0 : }
994 :
995 1 : void VrfTable::CreateStaticVrf(const string &name) {
996 1 : static_vrf_set_.insert(name);
997 1 : CreateVrf(name, boost::uuids::nil_uuid(), VrfData::ConfigVrf);
998 1 : }
999 :
1000 1 : void VrfTable::CreateFabricPolicyVrf(const string &name) {
1001 1 : static_vrf_set_.insert(name);
1002 1 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1003 1 : req.key.reset(new VrfKey(name));
1004 1 : VrfData *data = new VrfData(agent(), NULL, VrfData::ConfigVrf,
1005 1 : boost::uuids::nil_uuid(), 0, "", 0, false);
1006 1 : data->forwarding_vrf_name_ = agent()->fabric_vrf_name();
1007 1 : req.data.reset(data);
1008 1 : Process(req);
1009 1 : }
1010 :
1011 3 : void VrfTable::DeleteStaticVrf(const string &name) {
1012 3 : static_vrf_set_.erase(name);
1013 3 : DeleteVrfReq(name);
1014 3 : }
1015 :
1016 48 : void VrfTable::DeleteFromDbTree(int table_type, const std::string &vrf_name) {
1017 48 : dbtree_[table_type].erase(vrf_name);
1018 48 : }
1019 :
1020 256 : void VrfTable::Input(DBTablePartition *partition, DBClient *client,
1021 : DBRequest *req) {
1022 :
1023 256 : VrfKey *key = static_cast<VrfKey *>(req->key.get());
1024 256 : VrfEntry *entry = static_cast<VrfEntry *>(partition->Find(key));
1025 :
1026 256 : if (entry && entry->IsDeleted()) {
1027 199 : if (req->oper != DBRequest::DB_ENTRY_NOTIFY) {
1028 5 : OPER_TRACE(Vrf, "VRF pending delete, Ignoring DB operation for ",
1029 : entry->GetName());
1030 5 : return;
1031 : } else {
1032 : // Allow DB Operation for DB Entry Notify, along with
1033 : // validation for sub op as ADD_DEL_CHANGE
1034 194 : AgentKey *key = static_cast<AgentKey *>(req->key.get());
1035 194 : assert(key->sub_op_ == AgentKey::ADD_DEL_CHANGE);
1036 : }
1037 : }
1038 :
1039 251 : AgentDBTable::Input(partition, client, req);
1040 251 : return;
1041 : }
1042 :
1043 0 : static void FindHbfInterfacesFromHBS(Agent* agent, IFMapNode *node,
1044 : uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
1045 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1046 0 : DBGraph *graph = table->GetGraph();
1047 :
1048 0 : for (DBGraphVertex::edge_iterator iter = node->edge_list_begin(graph);
1049 0 : iter != node->edge_list_end(graph); ++iter) {
1050 0 : if (iter->IsDeleted()) {
1051 0 : continue;
1052 : }
1053 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.target());
1054 :
1055 0 : if (!strcmp(adj_node->table()->Typename(),
1056 : "host-based-service-virtual-network")) {
1057 : autogen::HostBasedServiceVirtualNetwork *hbsvn =
1058 : static_cast<HostBasedServiceVirtualNetwork *>
1059 0 : (adj_node->GetObject());
1060 0 : ServiceVirtualNetworkType type = hbsvn->data();
1061 :
1062 0 : for (DBGraphVertex::adjacency_iterator iter =
1063 0 : adj_node->begin(graph);
1064 0 : iter != node->end(graph); ++iter) {
1065 : IFMapNode *hbsvn_adj_node =
1066 0 : static_cast<IFMapNode *>(iter.operator->());
1067 0 : if (!strcmp(hbsvn_adj_node->table()->Typename(),
1068 : "virtual-network")) {
1069 0 : for (DBGraphVertex::adjacency_iterator iter =
1070 0 : hbsvn_adj_node->begin(graph);
1071 0 : iter != node->end(graph); ++iter) {
1072 0 : if (iter->IsDeleted()) {
1073 0 : continue;
1074 : }
1075 : IFMapNode *vmi_node =
1076 0 : static_cast<IFMapNode *>(iter.operator->());
1077 0 : if (!strcmp(vmi_node->table()->Typename(),
1078 : "virtual-machine-interface")) {
1079 : VirtualMachineInterface *cfg =
1080 : static_cast <VirtualMachineInterface *>
1081 0 : (vmi_node->GetObject());
1082 0 : autogen::IdPermsType id_perms = cfg->id_perms();
1083 : boost::uuids::uuid u;
1084 0 : CfgUuidSet(id_perms.uuid.uuid_mslong,
1085 : id_perms.uuid.uuid_lslong, u);
1086 : InterfaceConstRef intf =
1087 0 : agent->interface_table()->FindVmi(u);
1088 0 : if (!intf) {
1089 0 : continue;
1090 : }
1091 0 : if (!strcmp(type.virtual_network_type.c_str(),
1092 : "right")) {
1093 0 : hbf_rintf = intf->id();
1094 0 : } else if (!strcmp(
1095 : type.virtual_network_type.c_str(), "left")) {
1096 0 : hbf_lintf = intf->id();
1097 : }
1098 0 : }
1099 : }
1100 : }
1101 : }
1102 0 : }
1103 : }
1104 0 : }
1105 :
1106 0 : static void FindHbfInterfacesFromProject(Agent* agent, IFMapNode *node,
1107 : uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
1108 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1109 0 : DBGraph *graph = table->GetGraph();
1110 :
1111 0 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
1112 0 : iter != node->end(graph); ++iter) {
1113 0 : if (iter->IsDeleted()) {
1114 0 : continue;
1115 : }
1116 : IFMapNode *adj_node =
1117 0 : static_cast<IFMapNode *>(iter.operator->());
1118 :
1119 0 : if (strcmp(adj_node->table()->Typename(), "host-based-service") == 0) {
1120 0 : FindHbfInterfacesFromHBS(agent, adj_node, hbf_rintf, hbf_lintf);
1121 0 : break;
1122 : }
1123 : }
1124 0 : }
1125 :
1126 12 : static void FindHbfInterfacesFromVmi(Agent* agent, IFMapNode *node,
1127 : uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
1128 12 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1129 12 : DBGraph *graph = table->GetGraph();
1130 :
1131 12 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
1132 48 : iter != node->end(graph); ++iter) {
1133 36 : if (iter->IsDeleted()) {
1134 0 : continue;
1135 : }
1136 : IFMapNode *adj_node =
1137 36 : static_cast<IFMapNode *>(iter.operator->());
1138 :
1139 36 : if (strcmp(adj_node->table()->Typename(), "project") == 0) {
1140 0 : FindHbfInterfacesFromProject(agent, adj_node, hbf_rintf, hbf_lintf);
1141 0 : break;
1142 : }
1143 : }
1144 12 : }
1145 :
1146 18 : static void FindHbfInterfaces(Agent *agent, IFMapNode *vn_node,
1147 : uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
1148 18 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
1149 18 : DBGraph *graph = table->GetGraph();
1150 :
1151 18 : for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
1152 30 : iter != vn_node->end(graph); ++iter) {
1153 24 : if (iter->IsDeleted()) {
1154 0 : continue;
1155 : }
1156 : IFMapNode *adj_node =
1157 24 : static_cast<IFMapNode *>(iter.operator->());
1158 :
1159 24 : if (strcmp(adj_node->table()->Typename(),
1160 24 : "virtual-machine-interface") == 0) {
1161 12 : FindHbfInterfacesFromVmi(agent, adj_node, hbf_rintf, hbf_lintf);
1162 12 : break;
1163 : }
1164 : }
1165 18 : }
1166 :
1167 18 : static void BuildForwardingVrf(Agent *agent, IFMapNode *vn_node,
1168 : std::string &forwarding_vrf_name) {
1169 18 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
1170 18 : DBGraph *graph = table->GetGraph();
1171 18 : for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
1172 80 : iter != vn_node->end(graph); ++iter) {
1173 : IFMapNode *adj_node =
1174 62 : static_cast<IFMapNode *>(iter.operator->());
1175 124 : if (iter->IsDeleted() ||
1176 62 : (adj_node->table() != agent->cfg()->cfg_vn_table())) {
1177 62 : continue;
1178 : }
1179 :
1180 : VirtualNetwork *cfg =
1181 0 : static_cast <VirtualNetwork *> (adj_node->GetObject());
1182 0 : if (cfg == NULL) {
1183 0 : continue;
1184 : }
1185 :
1186 0 : if (adj_node->name() == agent->fabric_vn_name()) {
1187 0 : forwarding_vrf_name = agent->fabric_vrf_name();
1188 : }
1189 : }
1190 18 : }
1191 :
1192 47 : static VrfData *BuildData(Agent *agent, IFMapNode *node) {
1193 47 : boost::uuids::uuid vn_uuid = boost::uuids::nil_uuid();
1194 47 : boost::uuids::uuid si_vn_uuid = boost::uuids::nil_uuid();
1195 47 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1196 47 : DBGraph *graph = table->GetGraph();
1197 47 : bool learning_enabled = false;
1198 47 : std::string forwarding_vrf = "";
1199 47 : uint32_t hbf_rintf = Interface::kInvalidIndex;
1200 47 : uint32_t hbf_lintf = Interface::kInvalidIndex;
1201 :
1202 47 : uint32_t aging_timeout = 0;
1203 47 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
1204 104 : iter != node->end(graph); ++iter) {
1205 : IFMapNode *adj_node =
1206 75 : static_cast<IFMapNode *>(iter.operator->());
1207 :
1208 150 : if (iter->IsDeleted() ||
1209 75 : (adj_node->table() != agent->cfg()->cfg_vn_table())) {
1210 57 : continue;
1211 : }
1212 :
1213 : VirtualNetwork *cfg =
1214 18 : static_cast <VirtualNetwork *> (adj_node->GetObject());
1215 18 : if (cfg == NULL) {
1216 0 : continue;
1217 : }
1218 :
1219 18 : BuildForwardingVrf(agent, adj_node, forwarding_vrf);
1220 :
1221 18 : FindHbfInterfaces(agent, adj_node, hbf_rintf, hbf_lintf);
1222 :
1223 18 : if (!IsVRFServiceChainingInstance(adj_node->name(), node->name())) {
1224 18 : autogen::IdPermsType id_perms = cfg->id_perms();
1225 18 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1226 : vn_uuid);
1227 18 : aging_timeout = cfg->mac_aging_time();
1228 18 : break;
1229 18 : } else {
1230 0 : autogen::IdPermsType id_perms = cfg->id_perms();
1231 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1232 : si_vn_uuid);
1233 0 : break;
1234 0 : }
1235 : }
1236 :
1237 : VrfData *vrf_data = new VrfData(agent, node, VrfData::ConfigVrf,
1238 : vn_uuid, 0, "",
1239 : aging_timeout, learning_enabled,
1240 47 : hbf_rintf, hbf_lintf);
1241 47 : if (node->name() == agent->fabric_policy_vrf_name()) {
1242 0 : vrf_data->forwarding_vrf_name_ = agent->fabric_vrf_name();
1243 : } else {
1244 47 : vrf_data->forwarding_vrf_name_ = forwarding_vrf;
1245 : }
1246 :
1247 47 : vrf_data->si_vn_ref_uuid_ = si_vn_uuid;
1248 :
1249 47 : return vrf_data;
1250 47 : }
1251 :
1252 66 : bool VrfTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
1253 : const boost::uuids::uuid &u) {
1254 : //Trigger add or delete only for non fabric VRF
1255 66 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
1256 10 : req.key.reset(new VrfKey(node->name()));
1257 10 : if (IsStaticVrf(node->name())) {
1258 : //Fabric and link-local VRF will not be deleted,
1259 : //upon config delete
1260 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1261 : } else {
1262 10 : req.oper = DBRequest::DB_ENTRY_DELETE;
1263 : }
1264 :
1265 10 : VrfData *data = new VrfData(agent(), node, VrfData::ConfigVrf,
1266 10 : boost::uuids::nil_uuid(), 0, "", 0, false);
1267 10 : if (node->name() == agent()->fabric_policy_vrf_name()) {
1268 0 : data->forwarding_vrf_name_ = agent()->fabric_vrf_name();
1269 : }
1270 10 : req.data.reset(data);
1271 10 : Enqueue(&req);
1272 10 : return false;
1273 : }
1274 :
1275 56 : agent()->config_manager()->AddVrfNode(node);
1276 56 : return false;
1277 : }
1278 :
1279 47 : bool VrfTable::ProcessConfig(IFMapNode *node, DBRequest &req,
1280 : const boost::uuids::uuid &u) {
1281 47 : req.key.reset(new VrfKey(node->name()));
1282 :
1283 : //Trigger add or delete only for non fabric VRF
1284 47 : if (node->IsDeleted()) {
1285 0 : if (IsStaticVrf(node->name())) {
1286 : //Fabric and link-local VRF will not be deleted,
1287 : //upon config delete
1288 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1289 : } else {
1290 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
1291 : }
1292 :
1293 0 : VrfData *data = new VrfData(agent(), node, VrfData::ConfigVrf,
1294 0 : boost::uuids::nil_uuid(), 0, "", 0, false,
1295 : Interface::kInvalidIndex,
1296 0 : Interface::kInvalidIndex);
1297 0 : if (node->name() == agent()->fabric_policy_vrf_name()) {
1298 0 : data->forwarding_vrf_name_ = agent()->fabric_vrf_name();
1299 : }
1300 0 : req.data.reset(data);
1301 : } else {
1302 47 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1303 47 : req.data.reset(BuildData(agent(), node));
1304 : }
1305 :
1306 : //When VRF config delete comes, first enqueue VRF delete
1307 : //so that when link evaluation happens, all point to deleted VRF
1308 47 : Enqueue(&req);
1309 47 : return false;
1310 : }
1311 :
1312 0 : void VrfListReq::HandleRequest() const {
1313 0 : AgentSandeshPtr sand(new AgentVrfSandesh(context(), get_name()));
1314 0 : sand->DoSandesh(sand);
1315 0 : }
1316 :
1317 0 : AgentSandeshPtr VrfTable::GetAgentSandesh(const AgentSandeshArguments *args,
1318 : const std::string &context) {
1319 : return AgentSandeshPtr(new AgentVrfSandesh(context,
1320 0 : args->GetString("name")));
1321 : }
1322 :
1323 : class RouteDeleteWalker : public AgentRouteWalker {
1324 : public:
1325 1 : RouteDeleteWalker(const std::string &name, Agent *agent) :
1326 1 : AgentRouteWalker(name, agent) {
1327 1 : }
1328 :
1329 2 : ~RouteDeleteWalker() { }
1330 :
1331 : //Override route notification
1332 14 : bool RouteWalkNotify(DBTablePartBase *partition, DBEntryBase *e) {
1333 14 : AgentRoute *rt = static_cast<AgentRoute *>(e);
1334 28 : for(Route::PathList::const_iterator it = rt->GetPathList().begin();
1335 58 : it != rt->GetPathList().end(); ) {
1336 : const AgentPath *path =
1337 15 : static_cast<const AgentPath *>(it.operator->());
1338 15 : Route::PathList::const_iterator next = ++it;
1339 :
1340 15 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1341 15 : req.key = e->GetDBRequestKey();
1342 15 : AgentRouteKey *key = static_cast<AgentRouteKey *>(req.key.get());
1343 15 : key->peer_ = path->peer();
1344 15 : (static_cast<AgentRouteTable *>(e->get_table()))->Process(req);
1345 : it = next;
1346 15 : }
1347 :
1348 14 : return true;
1349 : }
1350 :
1351 1 : static void WalkDone(RouteDeleteWalker *walker) {
1352 1 : walk_done_++;
1353 1 : walker->mgr()->ReleaseWalker(walker);
1354 1 : walker->agent()->vrf_table()->reset_route_delete_walker();
1355 1 : }
1356 :
1357 : static uint32_t walk_start_;
1358 : static uint32_t walk_done_;
1359 : };
1360 : uint32_t RouteDeleteWalker::walk_start_;
1361 : uint32_t RouteDeleteWalker::walk_done_;
1362 :
1363 1 : void VrfTable::DeleteRoutes() {
1364 1 : if (route_delete_walker_.get() == NULL) {
1365 : route_delete_walker_ = new RouteDeleteWalker("RouteDeleteWalker",
1366 1 : agent());
1367 : agent()->oper_db()->agent_route_walk_manager()->
1368 1 : RegisterWalker(static_cast<AgentRouteWalker *>
1369 : (route_delete_walker_.get()));
1370 : }
1371 : route_delete_walker_->WalkDoneCallback
1372 2 : (boost::bind(&RouteDeleteWalker::WalkDone,
1373 1 : static_cast<RouteDeleteWalker *>(route_delete_walker_.get())));
1374 1 : route_delete_walker_->StartVrfWalk();
1375 1 : }
1376 :
1377 0 : void VrfTable::Shutdown() {
1378 0 : if (vrf_delete_walker_.get() == NULL) {
1379 : vrf_delete_walker_ = new VrfDeleteWalker("VrfDeleteWalker",
1380 0 : agent());
1381 : agent()->oper_db()->agent_route_walk_manager()->
1382 0 : RegisterWalker(static_cast<AgentRouteWalker *>
1383 : (vrf_delete_walker_.get()));
1384 : }
1385 0 : vrf_delete_walker_.get()->WalkDoneCallback(boost::bind
1386 : (&VrfDeleteWalker::WalkDone,
1387 0 : static_cast<VrfDeleteWalker *>( vrf_delete_walker_.get())));
1388 0 : vrf_delete_walker_.get()->StartVrfWalk();
1389 0 : }
|