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