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 "bgp/routing-instance/routing_instance.h"
7 :
8 : #include <boost/foreach.hpp>
9 : #include <boost/assign/list_of.hpp>
10 : #include <boost/functional/hash.hpp>
11 :
12 : #include <algorithm>
13 :
14 : #include "base/set_util.h"
15 : #include "base/task_annotations.h"
16 : #include "base/task_trigger.h"
17 : #include "bgp/bgp_config.h"
18 : #include "bgp/bgp_factory.h"
19 : #include "bgp/bgp_log.h"
20 : #include "bgp/bgp_mvpn.h"
21 : #include "bgp/bgp_server.h"
22 : #include "bgp/mvpn/mvpn_table.h"
23 : #include "bgp/routing-instance/iroute_aggregator.h"
24 : #include "bgp/routing-instance/istatic_route_mgr.h"
25 : #include "bgp/routing-instance/peer_manager.h"
26 : #include "bgp/routing-instance/routepath_replicator.h"
27 : #include "bgp/routing-instance/routing_instance_log.h"
28 : #include "bgp/routing-instance/routing_table_types.h"
29 : #include "bgp/routing-policy/routing_policy.h"
30 : #include "bgp/routing-instance/rtarget_group_mgr.h"
31 : #include "bgp/rtarget/rtarget_route.h"
32 :
33 : using boost::assign::list_of;
34 : using boost::system::error_code;
35 : using boost::tie;
36 : using std::make_pair;
37 : using std::ostringstream;
38 : using std::set;
39 : using std::string;
40 : using std::vector;
41 :
42 : SandeshTraceBufferPtr RoutingInstanceTraceBuf(
43 : SandeshTraceBufferCreate(RTINSTANCE_TRACE_BUF, 1000));
44 :
45 : class RoutingInstanceMgr::DeleteActor : public LifetimeActor {
46 : public:
47 9743 : explicit DeleteActor(RoutingInstanceMgr *manager)
48 9743 : : LifetimeActor(manager->server_->lifetime_manager()),
49 9743 : manager_(manager) {
50 9743 : }
51 9639 : virtual bool MayDelete() const {
52 9639 : return manager_->MayDelete();
53 : }
54 9639 : virtual void Shutdown() {
55 9639 : manager_->Shutdown();
56 9639 : }
57 9639 : virtual void Destroy() {
58 9639 : manager_->server_delete_ref_.Reset(NULL);
59 9639 : }
60 :
61 : private:
62 : RoutingInstanceMgr *manager_;
63 : };
64 :
65 9743 : RoutingInstanceMgr::RoutingInstanceMgr(BgpServer *server) :
66 9743 : server_(server),
67 19486 : instance_config_lists_(
68 9743 : TaskScheduler::GetInstance()->HardwareThreadCount()),
69 9743 : default_rtinstance_(NULL),
70 9743 : deleted_count_(0),
71 9743 : asn_listener_id_(server->RegisterASNUpdateCallback(
72 : boost::bind(&RoutingInstanceMgr::ASNUpdateCallback, this, _1, _2))),
73 9743 : identifier_listener_id_(server->RegisterIdentifierUpdateCallback(
74 : boost::bind(&RoutingInstanceMgr::IdentifierUpdateCallback,
75 : this, _1))),
76 9743 : dormant_trace_buf_size_(
77 9743 : GetEnvRoutingInstanceDormantTraceBufferCapacity()),
78 9743 : trace_buf_threshold_(
79 9743 : GetEnvRoutingInstanceDormantTraceBufferThreshold()),
80 9743 : deleter_(new DeleteActor(this)),
81 29229 : server_delete_ref_(this, server->deleter()) {
82 9743 : int task_id = TaskScheduler::GetInstance()->GetTaskId("bgp::ConfigHelper");
83 9743 : int hw_thread_count = TaskScheduler::GetInstance()->HardwareThreadCount();
84 48715 : for (int idx = 0; idx < hw_thread_count; ++idx) {
85 77944 : instance_config_triggers_.push_back(new TaskTrigger(boost::bind(
86 : &RoutingInstanceMgr::ProcessInstanceConfigList, this, idx),
87 38972 : task_id, idx));
88 : }
89 19486 : neighbor_config_trigger_.reset(new TaskTrigger(
90 : boost::bind(&RoutingInstanceMgr::ProcessNeighborConfigList, this),
91 19486 : TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0));
92 9743 : }
93 :
94 19486 : RoutingInstanceMgr::~RoutingInstanceMgr() {
95 9743 : assert(mvpn_project_managers_.empty());
96 9743 : assert(virtual_networks_.empty());
97 9743 : assert(deleted_count_ == 0);
98 9743 : server_->UnregisterASNUpdateCallback(asn_listener_id_);
99 9743 : server_->UnregisterIdentifierUpdateCallback(identifier_listener_id_);
100 9743 : STLDeleteValues(&instance_config_triggers_);
101 19486 : }
102 :
103 190 : size_t RoutingInstanceMgr::GetMvpnProjectManagerCount(
104 : const string &network) const {
105 190 : std::scoped_lock lock(mutex_);
106 :
107 : MvpnProjectManagerNetworks::const_iterator iter =
108 190 : mvpn_project_managers_.find(network);
109 190 : if (iter == mvpn_project_managers_.end())
110 184 : return 0;
111 6 : return iter->second.size();
112 190 : }
113 :
114 9639 : void RoutingInstanceMgr::ManagedDelete() {
115 9639 : deleter_->Delete();
116 9639 : }
117 :
118 9639 : void RoutingInstanceMgr::Shutdown() {
119 50539 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
120 40900 : InstanceTargetRemove(it->second);
121 40900 : InstanceVnIndexRemove(it->second);
122 : }
123 9639 : }
124 :
125 9639 : bool RoutingInstanceMgr::MayDelete() const {
126 9639 : if (!neighbor_config_list_.empty())
127 0 : return false;
128 48195 : for (size_t idx = 0; idx < instance_config_lists_.size(); ++idx) {
129 38556 : if (!instance_config_lists_[idx].empty())
130 0 : return false;
131 : }
132 9639 : return true;
133 : }
134 :
135 131485 : LifetimeActor *RoutingInstanceMgr::deleter() {
136 131485 : return deleter_.get();
137 : }
138 :
139 80360 : bool RoutingInstanceMgr::deleted() {
140 80360 : return deleter()->IsDeleted();
141 : }
142 :
143 : //
144 : // Go through all export targets for the RoutingInstance and add an entry for
145 : // each one to the InstanceTargetMap.
146 : //
147 : // Ignore export targets that are not in the import list. This is done since
148 : // export only targets are managed by user and the same export only target can
149 : // be configured on multiple virtual networks.
150 : //
151 69742 : void RoutingInstanceMgr::InstanceTargetAdd(RoutingInstance *rti) {
152 69742 : std::scoped_lock lock(mutex_);
153 69744 : for (RoutingInstance::RouteTargetList::const_iterator it =
154 578543 : rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
155 439055 : if (rti->GetImportList().find(*it) == rti->GetImportList().end())
156 448 : continue;
157 438607 : target_map_.insert(make_pair(*it, rti));
158 : }
159 69744 : }
160 :
161 : //
162 : // Go through all export targets for the RoutingInstance and remove the entry
163 : // for each one from the InstanceTargetMap. Note that there may be multiple
164 : // entries in the InstanceTargetMap for a given export target. Hence we need
165 : // to make sure that we only remove the entry that matches the RoutingInstance.
166 : //
167 : // Ignore export targets that are not in the import list. They shouldn't be in
168 : // in the map because of the same check in InstanceTargetAdd.
169 : //
170 69741 : void RoutingInstanceMgr::InstanceTargetRemove(const RoutingInstance *rti) {
171 69741 : std::scoped_lock lock(mutex_);
172 69744 : for (RoutingInstance::RouteTargetList::const_iterator it =
173 578543 : rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
174 439055 : if (rti->GetImportList().find(*it) == rti->GetImportList().end())
175 448 : continue;
176 438607 : for (InstanceTargetMap::iterator loc = target_map_.find(*it);
177 441821 : loc != target_map_.end() && loc->first == *it; ++loc) {
178 441821 : if (loc->second == rti) {
179 438607 : target_map_.erase(loc);
180 438607 : break;
181 : }
182 : }
183 : }
184 69744 : }
185 :
186 : //
187 : // Lookup the RoutingInstance for the given RouteTarget.
188 : //
189 432 : const RoutingInstance *RoutingInstanceMgr::GetInstanceByTarget(
190 : const RouteTarget &rtarget) const {
191 432 : InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
192 432 : if (loc == target_map_.end()) {
193 0 : return NULL;
194 : }
195 432 : return loc->second;
196 : }
197 :
198 : //
199 : // Add an entry for the vn index to the VnIndexMap.
200 : //
201 69744 : void RoutingInstanceMgr::InstanceVnIndexAdd(RoutingInstance *rti) {
202 69744 : std::scoped_lock lock(mutex_);
203 69744 : if (rti->virtual_network_index())
204 27194 : vn_index_map_.insert(make_pair(rti->virtual_network_index(), rti));
205 69744 : }
206 :
207 : //
208 : // Remove the entry for the vn index from the VnIndexMap. Note that there may
209 : // be multiple entries in the VnIndexMap for a given vn index target. Hence we
210 : // need to make sure that we remove the entry that matches the RoutingInstance.
211 : //
212 69744 : void RoutingInstanceMgr::InstanceVnIndexRemove(const RoutingInstance *rti) {
213 69744 : std::scoped_lock lock(mutex_);
214 69744 : if (!rti->virtual_network_index())
215 42550 : return;
216 :
217 27194 : int vn_index = rti->virtual_network_index();
218 27194 : for (VnIndexMap::iterator loc = vn_index_map_.find(vn_index);
219 28675 : loc != vn_index_map_.end() && loc->first == vn_index; ++loc) {
220 28675 : if (loc->second == rti) {
221 27194 : vn_index_map_.erase(loc);
222 27194 : break;
223 : }
224 : }
225 69744 : }
226 :
227 : //
228 : // Lookup the RoutingInstance for the given vn index.
229 : //
230 77150 : const RoutingInstance *RoutingInstanceMgr::GetInstanceByVnIndex(
231 : int vn_index) const {
232 77150 : VnIndexMap::const_iterator loc = vn_index_map_.find(vn_index);
233 77149 : if (loc == vn_index_map_.end())
234 18 : return NULL;
235 77131 : return loc->second;
236 : }
237 :
238 : //
239 : // Lookup the VN name for the given vn index.
240 : //
241 77150 : string RoutingInstanceMgr::GetVirtualNetworkByVnIndex(
242 : int vn_index) const {
243 77150 : const RoutingInstance *rti = GetInstanceByVnIndex(vn_index);
244 77149 : return rti ? rti->GetVirtualNetworkName() : "unresolved";
245 : }
246 :
247 : //
248 : // Lookup the vn index for the given RouteTarget.
249 : //
250 : // Return 0 if the RouteTarget does not map to a RoutingInstance.
251 : // Return -1 if the RouteTarget maps to multiple RoutingInstances
252 : // that belong to different VNs.
253 : //
254 644291 : int RoutingInstanceMgr::GetVnIndexByRouteTarget(
255 : const RouteTarget &rtarget) const {
256 644291 : int vn_index = 0;
257 644291 : for (InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
258 3108274 : loc != target_map_.end() && loc->first == rtarget; ++loc) {
259 2463698 : int ri_vn_index = loc->second->virtual_network_index();
260 2463858 : if (vn_index && ri_vn_index && ri_vn_index != vn_index)
261 11 : return -1;
262 2463847 : vn_index = ri_vn_index;
263 : }
264 :
265 645092 : return vn_index;
266 : }
267 :
268 : //
269 : // Derive the vn index from the route targets in the ExtCommunity.
270 : //
271 : // If the result is ambiguous i.e. we have a RouteTarget that maps
272 : // to multiple vn indexes or we have multiple RouteTargets that map
273 : // to different vn indexes, return 0.
274 : //
275 178210 : int RoutingInstanceMgr::GetVnIndexByExtCommunity(
276 : const ExtCommunity *ext_community) const {
277 178210 : int vn_index = 0;
278 2027515 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
279 : ext_community->communities()) {
280 924456 : if (!ExtCommunity::is_route_target(comm))
281 280239 : continue;
282 :
283 644157 : RouteTarget rtarget(comm);
284 644282 : int rtgt_vn_index = GetVnIndexByRouteTarget(rtarget);
285 644596 : if (rtgt_vn_index < 0 ||
286 172 : (vn_index && rtgt_vn_index && rtgt_vn_index != vn_index)) {
287 119 : vn_index = 0;
288 119 : break;
289 644477 : } else if (rtgt_vn_index) {
290 6357 : vn_index = rtgt_vn_index;
291 : }
292 : }
293 :
294 178364 : return vn_index;
295 : }
296 :
297 : int
298 41170 : RoutingInstanceMgr::RegisterInstanceOpCallback(RoutingInstanceCb callback) {
299 41170 : std::scoped_lock lock(mutex_);
300 41170 : size_t i = bmap_.find_first();
301 41170 : if (i == bmap_.npos) {
302 41169 : i = callbacks_.size();
303 41169 : callbacks_.push_back(callback);
304 : } else {
305 1 : bmap_.reset(i);
306 1 : if (bmap_.none()) {
307 1 : bmap_.clear();
308 : }
309 1 : callbacks_[i] = callback;
310 : }
311 41170 : return i;
312 41170 : }
313 :
314 40752 : void RoutingInstanceMgr::UnregisterInstanceOpCallback(int listener) {
315 40752 : std::scoped_lock lock(mutex_);
316 40752 : callbacks_[listener] = NULL;
317 40752 : if ((size_t) listener == callbacks_.size() - 1) {
318 51781 : while (!callbacks_.empty() && callbacks_.back() == NULL) {
319 40743 : callbacks_.pop_back();
320 : }
321 11038 : if (bmap_.size() > callbacks_.size()) {
322 10152 : bmap_.resize(callbacks_.size());
323 : }
324 : } else {
325 29714 : if ((size_t) listener >= bmap_.size()) {
326 29366 : bmap_.resize(listener + 1);
327 : }
328 29714 : bmap_.set(listener);
329 : }
330 40752 : }
331 :
332 131117 : void RoutingInstanceMgr::NotifyInstanceOp(string name, Operation op) {
333 131117 : std::scoped_lock lock(mutex_);
334 131118 : for (InstanceOpListenersList::iterator iter = callbacks_.begin();
335 565933 : iter != callbacks_.end(); ++iter) {
336 434816 : if (*iter != NULL) {
337 393100 : RoutingInstanceCb cb = *iter;
338 393100 : (cb)(name, op);
339 393099 : }
340 : }
341 131117 : }
342 :
343 29146 : bool RoutingInstanceMgr::ProcessInstanceConfigList(int idx) {
344 29146 : if (deleted()) {
345 0 : deleter()->RetryDelete();
346 : } else {
347 126744 : BOOST_FOREACH(const string &name, instance_config_lists_[idx]) {
348 : const BgpInstanceConfig *config =
349 48620 : server()->config_manager()->FindInstance(name);
350 48627 : if (!config)
351 1 : continue;
352 48626 : LocateRoutingInstance(config);
353 : }
354 : }
355 :
356 29254 : instance_config_lists_[idx].clear();
357 29254 : return true;
358 : }
359 :
360 354599 : RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() {
361 354599 : return default_rtinstance_;
362 : }
363 :
364 0 : const RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() const {
365 0 : return default_rtinstance_;
366 : }
367 :
368 313910 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(const string &name) {
369 313910 : RoutingInstanceList::iterator iter = instances_.find(name);
370 313910 : if (iter != instances_.end())
371 295984 : return iter->second;
372 17923 : return NULL;
373 : }
374 :
375 162764 : const RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(
376 : const string &name) const {
377 162764 : RoutingInstanceList::const_iterator iter = instances_.find(name);
378 162764 : if (iter != instances_.end())
379 157889 : return iter->second;
380 4875 : return NULL;
381 : }
382 :
383 68714 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstanceLocked(
384 : const string &name) {
385 68714 : std::scoped_lock lock(mutex_);
386 69104 : RoutingInstanceList::iterator iter = instances_.find(name);
387 69104 : if (iter != instances_.end())
388 18640 : return iter->second;
389 50464 : return NULL;
390 69104 : }
391 :
392 51137 : void RoutingInstanceMgr::InsertRoutingInstance(RoutingInstance *rtinstance) {
393 51137 : std::scoped_lock lock(mutex_);
394 51137 : instances_.insert(make_pair(rtinstance->config()->name(),
395 : rtinstance));
396 51137 : }
397 :
398 68693 : void RoutingInstanceMgr::LocateRoutingInstance(
399 : const BgpInstanceConfig *config) {
400 68693 : RoutingInstance *rtinstance = GetRoutingInstanceLocked(config->name());
401 69065 : if (rtinstance) {
402 18602 : if (rtinstance->deleted()) {
403 16 : RTINSTANCE_LOG_WARNING_MESSAGE(server_,
404 : RTINSTANCE_LOG_FLAG_ALL, rtinstance->GetVirtualNetworkName(),
405 : config->name(),
406 : "Instance recreated before pending deletion is complete");
407 : } else {
408 18593 : UpdateRoutingInstance(rtinstance, config);
409 : }
410 : } else {
411 50463 : rtinstance = CreateRoutingInstance(config);
412 : }
413 69067 : }
414 :
415 150762 : void RoutingInstanceMgr::LocateRoutingInstance(const string &name) {
416 : static boost::hash<string> string_hash;
417 :
418 150762 : if (name == BgpConfigManager::kMasterInstance) {
419 : const BgpInstanceConfig *config =
420 20070 : server()->config_manager()->FindInstance(name);
421 20070 : assert(config);
422 20070 : LocateRoutingInstance(config);
423 : } else {
424 130692 : size_t idx = string_hash(name) % instance_config_lists_.size();
425 130692 : instance_config_lists_[idx].insert(name);
426 130692 : instance_config_triggers_[idx]->Set();
427 : }
428 150762 : }
429 :
430 : // Update VirtualNetwork to RoutingInstance name mapping.
431 51151 : bool RoutingInstanceMgr::CreateVirtualNetworkMapping(
432 : const string &virtual_network, const string &instance_name) {
433 51151 : std::scoped_lock lock(mutex_);
434 :
435 51151 : VirtualNetworksMap::iterator iter;
436 : bool inserted;
437 102302 : tie(iter, inserted) = virtual_networks_.insert(make_pair(virtual_network,
438 153453 : set<string>()));
439 51151 : assert(iter->second.insert(instance_name).second);
440 51151 : return true;
441 51151 : }
442 :
443 51151 : bool RoutingInstanceMgr::DeleteVirtualNetworkMapping(
444 : const string &virtual_network, const string &instance_name) {
445 51151 : std::scoped_lock lock(mutex_);
446 :
447 51151 : VirtualNetworksMap::iterator iter = virtual_networks_.find(virtual_network);
448 51151 : assert(iter != virtual_networks_.end());
449 :
450 : // Delete this instance from the set of virtual-network to instances map.
451 51151 : assert(iter->second.erase(instance_name) == 1);
452 :
453 102302 : RoutingInstanceStatsData instance_info;
454 51151 : bool mapping_deleted = iter->second.empty();
455 :
456 : // Delete the mapping if the member set is empty.
457 51151 : if (mapping_deleted) {
458 37411 : virtual_networks_.erase(iter);
459 :
460 : // Delete the virtual-network specific UVE.
461 37411 : instance_info.set_deleted(true);
462 : } else {
463 :
464 : // Delete this instance's uve, by deleting all table stats.
465 13740 : map<string, RoutingTableStats> stats_map;
466 13740 : stats_map.insert(make_pair(instance_name, RoutingTableStats()));
467 13740 : stats_map[instance_name].set_deleted(true);
468 :
469 : // Delete all uve stats across all address families.
470 151140 : for (Address::Family i = Address::UNSPEC; i < Address::NUM_FAMILIES;
471 137400 : i = static_cast<Address::Family>(i + 1)) {
472 137400 : SetTableStatsUve(i, stats_map, &instance_info);
473 : }
474 13740 : }
475 :
476 : // Send delete uve.
477 51151 : instance_info.set_name(virtual_network);
478 51151 : assert(!instance_info.get_name().empty());
479 51151 : BGP_UVE_SEND(RoutingInstanceStats, instance_info);
480 :
481 51151 : return mapping_deleted;
482 51151 : }
483 :
484 139648 : void RoutingInstanceMgr::SetTableStatsUve(Address::Family family,
485 : const map<string, RoutingTableStats> &stats_map,
486 : RoutingInstanceStatsData *instance_info) const {
487 : // By switching over all families, we get compiler to tell us in future,
488 : // when ever familiy enum list gets modified.
489 139648 : switch (family) {
490 13740 : case Address::UNSPEC:
491 13740 : break;
492 27965 : case Address::INET:
493 : case Address::INETMPLS:
494 27965 : instance_info->set_raw_ipv4_stats(stats_map);
495 27965 : break;
496 14048 : case Address::INET6:
497 14048 : instance_info->set_raw_ipv6_stats(stats_map);
498 14048 : break;
499 13917 : case Address::INETVPN:
500 13917 : instance_info->set_raw_inetvpn_stats(stats_map);
501 13917 : break;
502 13917 : case Address::INET6VPN:
503 13917 : instance_info->set_raw_inet6vpn_stats(stats_map);
504 13917 : break;
505 13917 : case Address::RTARGET:
506 13917 : instance_info->set_raw_rtarget_stats(stats_map);
507 13917 : break;
508 14048 : case Address::EVPN:
509 14048 : instance_info->set_raw_evpn_stats(stats_map);
510 14048 : break;
511 14048 : case Address::ERMVPN:
512 14048 : instance_info->set_raw_ermvpn_stats(stats_map);
513 14048 : break;
514 14048 : case Address::MVPN:
515 14048 : instance_info->set_raw_mvpn_stats(stats_map);
516 14048 : break;
517 0 : case Address::NUM_FAMILIES:
518 0 : break;
519 : }
520 139648 : }
521 :
522 177 : uint32_t RoutingInstanceMgr::SendTableStatsUve() {
523 177 : uint32_t out_q_depth = 0;
524 :
525 485 : for (RoutingInstanceIterator rit = begin(); rit != end(); ++rit) {
526 616 : RoutingInstanceStatsData instance_info;
527 308 : map<string, RoutingTableStats> stats_map;
528 :
529 308 : stats_map.insert(make_pair(rit->second->name(), RoutingTableStats()));
530 : RoutingInstance::RouteTableList const rt_list =
531 308 : rit->second->GetTables();
532 :
533 : // Prepare and send Statistics UVE for each routing-instance.
534 308 : for (RoutingInstance::RouteTableList::const_iterator it =
535 2864 : rt_list.begin(); it != rt_list.end(); ++it) {
536 2248 : BgpTable *table = it->second;
537 :
538 : size_t markers;
539 2248 : out_q_depth += table->GetPendingRiboutsCount(&markers);
540 :
541 2248 : stats_map[rit->second->name()].set_prefixes(table->Size());
542 2248 : stats_map[rit->second->name()].set_primary_paths(
543 : table->GetPrimaryPathCount());
544 2248 : stats_map[rit->second->name()].set_secondary_paths(
545 : table->GetSecondaryPathCount());
546 2248 : stats_map[rit->second->name()].set_infeasible_paths(
547 : table->GetInfeasiblePathCount());
548 :
549 2248 : uint64_t total_paths = table->GetPrimaryPathCount() +
550 2248 : table->GetSecondaryPathCount() +
551 2248 : table->GetInfeasiblePathCount();
552 2248 : stats_map[rit->second->name()].set_total_paths(total_paths);
553 2248 : SetTableStatsUve(table->family(), stats_map, &instance_info);
554 : }
555 :
556 : // Set the primary key and trigger uve send.
557 308 : instance_info.set_name(rit->second->GetVirtualNetworkName());
558 308 : assert(!instance_info.get_name().empty());
559 308 : BGP_UVE_SEND(RoutingInstanceStats, instance_info);
560 308 : }
561 :
562 177 : return out_q_depth;
563 : }
564 :
565 51126 : RoutingInstance *RoutingInstanceMgr::CreateRoutingInstance(
566 : const BgpInstanceConfig *config) {
567 51133 : RoutingInstance *rtinstance = BgpStaticObjectFactory::Create<RoutingInstance>(
568 51126 : config->name(), server_, this, config);
569 51116 : uint32_t ri_index = config->index();
570 51112 : if (config->name() == BgpConfigManager::kMasterInstance) {
571 8228 : default_rtinstance_ = rtinstance;
572 8228 : ri_index = 0;
573 : }
574 :
575 51104 : rtinstance->ProcessConfig();
576 51126 : InsertRoutingInstance(rtinstance);
577 51137 : rtinstance->set_index(ri_index);
578 :
579 51137 : InstanceTargetAdd(rtinstance);
580 51137 : InstanceVnIndexAdd(rtinstance);
581 51137 : rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
582 :
583 : // Notify clients about routing instance create
584 51136 : NotifyInstanceOp(config->name(), INSTANCE_ADD);
585 :
586 51137 : vector<string> import_rt(config->import_list().begin(),
587 102274 : config->import_list().end());
588 51137 : vector<string> export_rt(config->export_list().begin(),
589 102274 : config->export_list().end());
590 51137 : RTINSTANCE_LOG(Create, rtinstance,
591 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL,
592 : import_rt, export_rt, rtinstance->virtual_network_index());
593 :
594 : // Schedule creation of neighbors for this instance.
595 51137 : CreateRoutingInstanceNeighbors(config);
596 :
597 : // Update instance to virtual-network mapping structures.
598 51137 : CreateVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
599 : rtinstance->name());
600 :
601 : // Create MvpnManager for all children mvpn networks.
602 : MvpnTable *mvpn_table =
603 51137 : dynamic_cast<MvpnTable *>(rtinstance->GetTable(Address::MVPN));
604 51137 : mvpn_table->CreateMvpnManagers();
605 51137 : return rtinstance;
606 51137 : }
607 :
608 18605 : void RoutingInstanceMgr::UpdateRoutingInstance(RoutingInstance *rtinstance,
609 : const BgpInstanceConfig *config) {
610 18605 : bool old_always_subscribe = rtinstance->always_subscribe();
611 :
612 : // Note that InstanceTarget[Remove|Add] depend on the RouteTargetList in
613 : // the RoutingInstance.
614 18604 : InstanceTargetRemove(rtinstance);
615 18607 : InstanceVnIndexRemove(rtinstance);
616 18607 : rtinstance->UpdateConfig(config);
617 18604 : InstanceTargetAdd(rtinstance);
618 18607 : InstanceVnIndexAdd(rtinstance);
619 :
620 18607 : if (old_always_subscribe != rtinstance->always_subscribe()) {
621 56 : rtinstance->FlushAllRTargetRoutes(server_->local_autonomous_system());
622 56 : rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
623 : }
624 :
625 : // Notify clients about routing instance create
626 18607 : NotifyInstanceOp(config->name(), INSTANCE_UPDATE);
627 :
628 18607 : vector<string> import_rt(config->import_list().begin(),
629 37214 : config->import_list().end());
630 18607 : vector<string> export_rt(config->export_list().begin(),
631 37214 : config->export_list().end());
632 18607 : RTINSTANCE_LOG(Update, rtinstance,
633 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL, import_rt, export_rt,
634 : rtinstance->virtual_network_index());
635 18607 : }
636 :
637 : //
638 : // Concurrency: BGP Config task
639 : //
640 : // Trigger deletion of a particular routing-instance
641 : //
642 : // This involves several asynchronous steps such as deleting all tables in
643 : // routing-instance (flush all notifications, registrations and user data).
644 : //
645 10369 : void RoutingInstanceMgr::DeleteRoutingInstance(const string &name) {
646 10369 : CHECK_CONCURRENCY("bgp::Config");
647 :
648 10369 : RoutingInstance *rtinstance = GetRoutingInstance(name);
649 :
650 : // Ignore if instance is not found as it might already have been deleted.
651 10369 : if (rtinstance && rtinstance->deleted()) {
652 4 : RTINSTANCE_LOG_WARNING_MESSAGE(server_, RTINSTANCE_LOG_FLAG_ALL,
653 : rtinstance->GetVirtualNetworkName(), name,
654 : "Duplicate instance delete while pending deletion");
655 2 : return;
656 10367 : } else if (!rtinstance) {
657 260 : RTINSTANCE_LOG_WARNING_MESSAGE(server_, RTINSTANCE_LOG_FLAG_ALL,
658 : name, name, "Instance not found during delete");
659 130 : return;
660 : }
661 :
662 10237 : InstanceVnIndexRemove(rtinstance);
663 10237 : InstanceTargetRemove(rtinstance);
664 10237 : rtinstance->ClearConfig();
665 :
666 10237 : RTINSTANCE_LOG(Delete, rtinstance,
667 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
668 :
669 10237 : rtinstance->ProcessServiceChainConfig();
670 10237 : rtinstance->FlushStaticRouteConfig();
671 10237 : rtinstance->FlushRouteAggregationConfig();
672 :
673 10237 : NotifyInstanceOp(name, INSTANCE_DELETE);
674 10237 : rtinstance->ManagedDelete();
675 : }
676 :
677 : //
678 : // Concurrency: Called from BGP config task manager
679 : //
680 : // Destroy a routing instance from the data structures
681 : //
682 51137 : void RoutingInstanceMgr::DestroyRoutingInstance(RoutingInstance *rtinstance) {
683 51137 : CHECK_CONCURRENCY("bgp::Config");
684 :
685 51137 : RTINSTANCE_LOG(Destroy, rtinstance,
686 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
687 :
688 51137 : DeleteVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
689 : rtinstance->name());
690 :
691 : // instance should also be deleted here
692 51137 : const string name = rtinstance->name();
693 51137 : RoutingInstanceList::iterator loc = instances_.find(rtinstance->name());
694 51137 : assert(loc != instances_.end());
695 51137 : instances_.erase(loc);
696 51137 : int index = rtinstance->index();
697 51137 : delete rtinstance;
698 : // disable the TraceBuf for the deleted RoutingInstance
699 51137 : DisableTraceBuffer(name);
700 : // index was allocated in Config Manager so needs to be freed
701 51137 : if (index >= 0)
702 50664 : server()->config_manager()->ResetRoutingInstanceIndexBit(index);
703 :
704 51137 : if (deleted())
705 40900 : return;
706 :
707 10237 : if (rtinstance == default_rtinstance_) {
708 0 : default_rtinstance_ = NULL;
709 0 : return;
710 : }
711 :
712 : const BgpInstanceConfig *config
713 10237 : = server()->config_manager()->FindInstance(name);
714 10237 : if (config) {
715 5 : CreateRoutingInstance(config);
716 5 : return;
717 : }
718 51137 : }
719 :
720 828097 : SandeshTraceBufferPtr RoutingInstanceMgr::LocateTraceBuffer(
721 : const std::string &name) {
722 828097 : SandeshTraceBufferPtr trace_buf;
723 :
724 828097 : trace_buf = GetActiveTraceBuffer(name);
725 828066 : if (trace_buf == NULL) {
726 29454 : trace_buf = GetTraceBuffer(name);
727 : }
728 :
729 828087 : return trace_buf;
730 0 : }
731 :
732 29454 : SandeshTraceBufferPtr RoutingInstanceMgr::GetTraceBuffer(
733 : const std::string &name) {
734 29454 : tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
735 29466 : SandeshTraceBufferPtr trace_buf;
736 29466 : RoutingInstanceTraceBufferMap::iterator iter;
737 :
738 29466 : iter = trace_buffer_active_.find(name);
739 29466 : if (iter != trace_buffer_active_.end()) {
740 0 : return iter->second;
741 : }
742 :
743 29466 : iter = trace_buffer_dormant_.find(name);
744 29466 : if (iter != trace_buffer_dormant_.end()) {
745 : // tracebuf was created for this RoutingInstance in its prior
746 : // incarnation
747 2 : trace_buf = iter->second;
748 2 : trace_buffer_dormant_.erase(iter);
749 2 : trace_buffer_dormant_list_.remove(name);
750 2 : trace_buffer_active_.insert(make_pair(name, trace_buf));
751 2 : return trace_buf;
752 : }
753 :
754 : // create new sandesh Buffer
755 58928 : trace_buf = SandeshTraceBufferCreate(
756 88392 : name + RTINSTANCE_TRACE_BUF, 1000);
757 29464 : trace_buffer_active_.insert(make_pair(name, trace_buf));
758 :
759 29464 : return trace_buf;
760 29466 : }
761 :
762 51137 : void RoutingInstanceMgr::DisableTraceBuffer(const std::string &name) {
763 51137 : tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
764 51137 : SandeshTraceBufferPtr trace_buf;
765 51137 : SandeshTraceBufferPtr trace_buf_delete;
766 51137 : RoutingInstanceTraceBufferMap::iterator iter;
767 51137 : std::pair<RoutingInstanceTraceBufferMap::iterator, bool> ret;
768 51137 : std::string ri_name;
769 :
770 : // Moving the trace buff from Active map to Dormant map
771 51137 : iter = trace_buffer_active_.find(name);
772 51137 : if (iter != trace_buffer_active_.end()) {
773 29466 : trace_buf = iter->second;
774 29466 : trace_buffer_active_.erase(iter);
775 29466 : if (dormant_trace_buf_size_) {
776 : // Move to Dormant map.
777 43 : if (trace_buffer_dormant_.size() >= dormant_trace_buf_size_) {
778 : // Make room in the Dormant map, so creating by:
779 : // 1. Delete oldest entries in dormant map
780 : // 2. Insert the new entry.
781 5 : size_t del_count = std::min(trace_buffer_dormant_list_.size(),
782 5 : trace_buf_threshold_);
783 5 : if (!del_count) {
784 : // retain the latest deleted RI's TraceBuf
785 3 : del_count = 1;
786 : }
787 12 : for (size_t i = 0; i < del_count; i++) {
788 7 : iter = trace_buffer_dormant_.find(
789 7 : trace_buffer_dormant_list_.front());
790 7 : assert(iter != trace_buffer_dormant_.end());
791 7 : trace_buf_delete = iter->second;
792 7 : trace_buffer_dormant_.erase(iter);
793 7 : trace_buffer_dormant_list_.pop_front();
794 7 : trace_buf_delete.reset();
795 : }
796 : }
797 43 : ret = trace_buffer_dormant_.insert(make_pair(name, trace_buf));
798 43 : assert(ret.second == true);
799 43 : trace_buffer_dormant_list_.push_back(name);
800 : }
801 : }
802 :
803 102274 : return;
804 51137 : }
805 :
806 : SandeshTraceBufferPtr
807 828099 : RoutingInstanceMgr::GetActiveTraceBuffer(const std::string &name) const {
808 828099 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
809 : RoutingInstanceTraceBufferMap::const_iterator iter =
810 828088 : trace_buffer_active_.find(name);
811 :
812 828021 : if (iter != trace_buffer_active_.end()) {
813 798614 : return iter->second;
814 : } else {
815 29438 : return SandeshTraceBufferPtr();
816 : }
817 828071 : }
818 :
819 : SandeshTraceBufferPtr
820 2 : RoutingInstanceMgr::GetDormantTraceBuffer(const std::string &name) const {
821 2 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
822 : RoutingInstanceTraceBufferMap::const_iterator iter =
823 2 : trace_buffer_dormant_.find(name);
824 :
825 2 : if (iter != trace_buffer_dormant_.end()) {
826 1 : return iter->second;
827 : } else {
828 1 : return SandeshTraceBufferPtr();
829 : }
830 2 : }
831 :
832 15 : bool RoutingInstanceMgr::HasRoutingInstanceActiveTraceBuf(const std::string
833 : &name) const {
834 15 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
835 : RoutingInstanceTraceBufferMap::const_iterator iter =
836 15 : trace_buffer_active_.find(name);
837 :
838 30 : return (iter != trace_buffer_active_.end());
839 15 : }
840 :
841 19 : bool RoutingInstanceMgr::HasRoutingInstanceDormantTraceBuf(const std::string
842 : &name) const {
843 19 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
844 : RoutingInstanceTraceBufferMap::const_iterator iter =
845 19 : trace_buffer_dormant_.find(name);
846 38 : return (iter != trace_buffer_dormant_.end());
847 19 : }
848 :
849 : size_t
850 9744 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferCapacity() const {
851 9744 : char *buffer_capacity_str = getenv(
852 : "CONTRAIL_ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_SIZE");
853 : // return Trace buf capacity 0, if not set in env variable.
854 9744 : if (buffer_capacity_str) {
855 17 : size_t env_buffer_capacity = strtoul(buffer_capacity_str, NULL, 0);
856 17 : return env_buffer_capacity;
857 : }
858 9727 : return 0;
859 : }
860 :
861 : size_t
862 9743 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferThreshold() const {
863 9743 : char *buffer_threshold_str = getenv(
864 : "CONTRAIL_ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD");
865 9743 : if (buffer_threshold_str) {
866 16 : size_t env_buffer_threshold = strtoul(buffer_threshold_str, NULL, 0);
867 16 : return env_buffer_threshold;
868 : }
869 9727 : return ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD_1K;
870 : }
871 :
872 10 : size_t RoutingInstanceMgr::GetRoutingInstanceActiveTraceBufSize() const {
873 10 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
874 20 : return trace_buffer_active_.size();
875 10 : }
876 :
877 13 : size_t RoutingInstanceMgr::GetRoutingInstanceDormantTraceBufSize() const {
878 13 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
879 26 : return trace_buffer_dormant_.size();
880 13 : }
881 :
882 51137 : void RoutingInstanceMgr::CreateRoutingInstanceNeighbors(
883 : const BgpInstanceConfig *config) {
884 51137 : if (config->neighbor_list().empty())
885 51076 : return;
886 61 : std::scoped_lock lock(mutex_);
887 61 : neighbor_config_list_.insert(config->name());
888 61 : neighbor_config_trigger_->Set();
889 61 : }
890 :
891 61 : bool RoutingInstanceMgr::ProcessNeighborConfigList() {
892 61 : if (deleted()) {
893 0 : deleter()->RetryDelete();
894 : } else {
895 183 : BOOST_FOREACH(const string &name, neighbor_config_list_) {
896 61 : RoutingInstance *rtinstance = GetRoutingInstance(name);
897 61 : if (!rtinstance || rtinstance->deleted())
898 2 : continue;
899 59 : rtinstance->CreateNeighbors();
900 : }
901 : }
902 :
903 61 : neighbor_config_list_.clear();
904 61 : return true;
905 : }
906 :
907 7398 : void RoutingInstanceMgr::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) {
908 7398 : if (server_->local_autonomous_system() == old_local_asn)
909 0 : return;
910 18380 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
911 10982 : it->second->FlushAllRTargetRoutes(old_local_asn);
912 10982 : it->second->InitAllRTargetRoutes(server_->local_autonomous_system());
913 : }
914 7398 : RoutingInstance *master = GetDefaultRoutingInstance();
915 7398 : const Ip4Address old_identifier(server()->bgp_identifier());
916 7398 : master->DeleteMvpnRTargetRoute(old_local_asn, old_identifier);
917 7398 : master->AddMvpnRTargetRoute(server_->local_autonomous_system());
918 : }
919 :
920 7439 : void RoutingInstanceMgr::IdentifierUpdateCallback(Ip4Address old_identifier) {
921 19623 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
922 12184 : it->second->ProcessIdentifierUpdate(server_->local_autonomous_system());
923 : }
924 7439 : RoutingInstance *master = GetDefaultRoutingInstance();
925 7439 : master->DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
926 : old_identifier);
927 7439 : master->AddMvpnRTargetRoute(server_->local_autonomous_system());
928 7439 : }
929 :
930 : //
931 : // Disable processing of all instance config lists.
932 : // For testing only.
933 : //
934 12 : void RoutingInstanceMgr::DisableInstanceConfigListProcessing() {
935 60 : for (size_t idx = 0; idx < instance_config_triggers_.size(); ++idx) {
936 48 : instance_config_triggers_[idx]->set_disable();
937 : }
938 12 : }
939 :
940 : //
941 : // Enable processing of all instance config lists.
942 : // For testing only.
943 : //
944 12 : void RoutingInstanceMgr::EnableInstanceConfigListProcessing() {
945 60 : for (size_t idx = 0; idx < instance_config_triggers_.size(); ++idx) {
946 48 : instance_config_triggers_[idx]->set_enable();
947 : }
948 12 : }
949 :
950 : //
951 : // Disable processing of neighbor config list.
952 : // For testing only.
953 : //
954 4 : void RoutingInstanceMgr::DisableNeighborConfigListProcessing() {
955 4 : neighbor_config_trigger_->set_disable();
956 4 : }
957 :
958 : //
959 : // Enable processing of neighbor config list.
960 : // For testing only.
961 : //
962 4 : void RoutingInstanceMgr::EnableNeighborConfigListProcessing() {
963 4 : neighbor_config_trigger_->set_enable();
964 4 : }
965 :
966 : class RoutingInstance::DeleteActor : public LifetimeActor {
967 : public:
968 51004 : DeleteActor(BgpServer *server, RoutingInstance *parent)
969 50969 : : LifetimeActor(server ? server->lifetime_manager() : NULL),
970 101968 : parent_(parent) {
971 51150 : }
972 51137 : virtual bool MayDelete() const {
973 51137 : return parent_->MayDelete();
974 : }
975 51137 : virtual void Shutdown() {
976 51137 : parent_->mgr_->increment_deleted_count();
977 51137 : parent_->mgr_->NotifyInstanceOp(parent_->name(),
978 : RoutingInstanceMgr::INSTANCE_DELETE);
979 51137 : parent_->Shutdown();
980 51137 : }
981 51137 : virtual void Destroy() {
982 51137 : parent_->mgr_->decrement_deleted_count();
983 51137 : parent_->mgr_->DestroyRoutingInstance(parent_);
984 51137 : }
985 :
986 : private:
987 : RoutingInstance *parent_;
988 : };
989 :
990 51096 : RoutingInstance::RoutingInstance(string name, BgpServer *server,
991 : RoutingInstanceMgr *mgr,
992 51096 : const BgpInstanceConfig *config)
993 153115 : : name_(name), index_(-1), server_(server), mgr_(mgr), config_(config),
994 101869 : is_master_(false), always_subscribe_(false), virtual_network_index_(0),
995 50928 : virtual_network_allow_transit_(false),
996 50928 : virtual_network_pbb_evpn_enable_(false),
997 50928 : vxlan_id_(0),
998 50952 : deleter_(new DeleteActor(server, this)),
999 51094 : manager_delete_ref_(this, NULL),
1000 102139 : mvpn_project_manager_network_(BgpConfigManager::kFabricInstance) {
1001 50931 : if (mgr) {
1002 50897 : std::scoped_lock lock(mgr->mutex());
1003 51137 : manager_delete_ref_.Reset(mgr->deleter());
1004 51137 : }
1005 51171 : }
1006 :
1007 82366 : RoutingInstance::~RoutingInstance() {
1008 82366 : }
1009 :
1010 59 : void RoutingInstance::CreateNeighbors() {
1011 59 : CHECK_CONCURRENCY("bgp::Config");
1012 :
1013 59 : if (config_->neighbor_list().empty())
1014 1 : return;
1015 58 : PeerManager *peer_manager = LocatePeerManager();
1016 280 : BOOST_FOREACH(const string &name, config_->neighbor_list()) {
1017 111 : if (peer_manager->PeerLookup(name))
1018 2 : continue;
1019 109 : peer_manager->PeerResurrect(name);
1020 : }
1021 : }
1022 :
1023 51134 : void RoutingInstance::ProcessRoutingPolicyConfig() {
1024 51134 : RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1025 51449 : BOOST_FOREACH(RoutingPolicyAttachInfo info,
1026 : config_->routing_policy_list()) {
1027 : RoutingPolicy *policy =
1028 158 : policy_mgr->GetRoutingPolicy(info.routing_policy_);
1029 158 : if (policy) {
1030 158 : routing_policies_.push_back(make_pair(policy,
1031 316 : policy->generation()));
1032 : }
1033 158 : }
1034 51135 : }
1035 :
1036 828097 : SandeshTraceBufferPtr RoutingInstance::trace_buffer() const {
1037 828097 : return mgr_->LocateTraceBuffer(name_);
1038 : }
1039 :
1040 : //
1041 : // Update the routing policy on the instance
1042 : // 1. New policy is added
1043 : // 2. Policy order changed
1044 : // 3. Policy is removed
1045 : // 4. Existing policy gets updated(terms in the policy got modified)
1046 : // In any of the above cases, we call routing policy manager to re-evaluate the
1047 : // routes in the BgpTables of this routing instance with new set of policies
1048 : //
1049 6565 : void RoutingInstance::UpdateRoutingPolicyConfig() {
1050 6565 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1051 6565 : RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1052 6563 : if (policy_mgr->UpdateRoutingPolicyList(config_->routing_policy_list(),
1053 : routing_policies())) {
1054 : // Let RoutingPolicyMgr handle update of routing policy on the instance
1055 37 : policy_mgr->ApplyRoutingPolicy(this);
1056 : }
1057 6568 : }
1058 :
1059 119076 : void RoutingInstance::ProcessServiceChainConfig() {
1060 119076 : if (is_master_)
1061 16456 : return;
1062 :
1063 : /**
1064 : * If any VN (both internal and non-internal) is connnected to an internal
1065 : * VN via a service-chain, we will create a service chain for EVPN address
1066 : * family as well so that we can re-originate routes from the internal VN
1067 : * RI's EVPN table.
1068 : * For other cases (any VN communicating with a non-internal VN via service
1069 : * chain), we do not need a service chain to watch the EVPN table.
1070 : * Schema-transformer needs to make sure to add the service chain config for
1071 : * EVPN address family to all VNs which need to communicate via a
1072 : * service-chain with an internal VN.
1073 : */
1074 : vector<SCAddress::Family> families = list_of
1075 102620 : (SCAddress::INET) (SCAddress::INET6)
1076 102619 : (SCAddress::EVPN) (SCAddress::EVPN6);
1077 :
1078 923564 : BOOST_FOREACH(SCAddress::Family family, families) {
1079 : const ServiceChainConfig *sc_config =
1080 410463 : config_ ? config_->service_chain_info(family) : NULL;
1081 410457 : IServiceChainMgr *manager = server_->service_chain_mgr(family);
1082 410450 : if (sc_config && !sc_config->routing_instance.empty()) {
1083 2810 : manager->LocateServiceChain(this, *sc_config);
1084 : } else {
1085 407644 : manager->StopServiceChain(this);
1086 : }
1087 : }
1088 102622 : }
1089 :
1090 51136 : void RoutingInstance::ProcessStaticRouteConfig() {
1091 51136 : if (is_master_)
1092 8228 : return;
1093 :
1094 42908 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1095 214541 : BOOST_FOREACH(Address::Family family, families) {
1096 85815 : IStaticRouteMgr *manager = static_route_mgr(family);
1097 85817 : if (!manager && !config_->static_routes(family).empty())
1098 36 : manager = LocateStaticRouteMgr(family);
1099 85817 : if (manager)
1100 36 : manager->ProcessStaticRouteConfig();
1101 : }
1102 42909 : }
1103 :
1104 6567 : void RoutingInstance::UpdateStaticRouteConfig() {
1105 6567 : if (is_master_)
1106 0 : return;
1107 :
1108 6567 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1109 32836 : BOOST_FOREACH(Address::Family family, families) {
1110 13134 : IStaticRouteMgr *manager = static_route_mgr(family);
1111 13134 : if (!manager && !config_->static_routes(family).empty())
1112 86 : manager = LocateStaticRouteMgr(family);
1113 13134 : if (manager)
1114 138 : manager->UpdateStaticRouteConfig();
1115 : }
1116 6567 : }
1117 :
1118 61374 : void RoutingInstance::FlushStaticRouteConfig() {
1119 61374 : if (is_master_)
1120 8228 : return;
1121 :
1122 53146 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1123 265730 : BOOST_FOREACH(Address::Family family, families) {
1124 106292 : IStaticRouteMgr *manager = static_route_mgr(family);
1125 106292 : if (manager)
1126 167 : manager->FlushStaticRouteConfig();
1127 : }
1128 53146 : }
1129 :
1130 180 : void RoutingInstance::UpdateAllStaticRoutes() {
1131 180 : if (is_master_)
1132 88 : return;
1133 :
1134 92 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1135 460 : BOOST_FOREACH(Address::Family family, families) {
1136 184 : IStaticRouteMgr *manager = static_route_mgr(family);
1137 184 : if (manager)
1138 2 : manager->UpdateAllRoutes();
1139 : }
1140 92 : }
1141 :
1142 51136 : void RoutingInstance::ProcessRouteAggregationConfig() {
1143 51136 : if (is_master_)
1144 8228 : return;
1145 :
1146 42908 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1147 214540 : BOOST_FOREACH(Address::Family family, families) {
1148 85813 : IRouteAggregator *aggregator = route_aggregator(family);
1149 85813 : if (!aggregator && !config_->aggregate_routes(family).empty())
1150 158 : aggregator = LocateRouteAggregator(family);
1151 85818 : if (aggregator)
1152 158 : aggregator->ProcessAggregateRouteConfig();
1153 : }
1154 42909 : }
1155 :
1156 6567 : void RoutingInstance::UpdateRouteAggregationConfig() {
1157 6567 : if (is_master_)
1158 0 : return;
1159 :
1160 6567 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1161 32812 : BOOST_FOREACH(Address::Family family, families) {
1162 13124 : IRouteAggregator *aggregator = route_aggregator(family);
1163 13125 : if (!aggregator && !config_->aggregate_routes(family).empty())
1164 2 : aggregator = LocateRouteAggregator(family);
1165 13125 : if (aggregator)
1166 71 : aggregator->UpdateAggregateRouteConfig();
1167 : }
1168 6566 : }
1169 :
1170 61374 : void RoutingInstance::FlushRouteAggregationConfig() {
1171 61374 : if (is_master_)
1172 8228 : return;
1173 :
1174 53146 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1175 265730 : BOOST_FOREACH(Address::Family family, families) {
1176 106292 : IRouteAggregator *aggregator = route_aggregator(family);
1177 106292 : if (aggregator)
1178 277 : aggregator->FlushAggregateRouteConfig();
1179 : }
1180 53146 : }
1181 :
1182 23065 : void RoutingInstance::DeleteMvpnRTargetRoute(as_t asn, Ip4Address old_ip) {
1183 23065 : if (asn == 0)
1184 14670 : return;
1185 16790 : string id_str = "target:" + old_ip.to_string() + ":0";
1186 8395 : RouteTarget rtarget = RouteTarget::FromString(id_str);
1187 8395 : DeleteRTargetRoute(asn, rtarget);
1188 8395 : }
1189 :
1190 14837 : void RoutingInstance::AddMvpnRTargetRoute(as_t asn) {
1191 14837 : if (asn == 0)
1192 7280 : return;
1193 7557 : const Ip4Address server_ip(server()->bgp_identifier());
1194 15114 : string id_str = "target:" + server_ip.to_string() + ":0";
1195 7557 : RouteTarget rtarget = RouteTarget::FromString(id_str);
1196 7557 : AddRTargetRoute(asn, rtarget);
1197 7557 : }
1198 :
1199 51112 : void RoutingInstance::ProcessConfig() {
1200 51112 : RoutingInstanceInfo info = GetDataCollection("");
1201 :
1202 : // Initialize virtual network info.
1203 51016 : virtual_network_ = config_->virtual_network();
1204 51011 : virtual_network_index_ = config_->virtual_network_index();
1205 51003 : virtual_network_allow_transit_ = config_->virtual_network_allow_transit();
1206 50996 : virtual_network_pbb_evpn_enable_ =
1207 51005 : config_->virtual_network_pbb_evpn_enable();
1208 50996 : vxlan_id_ = config_->vxlan_id();
1209 50989 : routing_instance_vxlan_ = config_->routing_instance_vxlan();
1210 :
1211 : // Always subscribe (using RTF) for RTs of PNF service chain instances.
1212 50988 : always_subscribe_ = config_->has_pnf();
1213 :
1214 50982 : vector<string> import_rt, export_rt;
1215 319698 : BOOST_FOREACH(string irt, config_->import_list()) {
1216 134259 : error_code error;
1217 134259 : RouteTarget rt = RouteTarget::FromString(irt, &error);
1218 134330 : if (!error) {
1219 134338 : import_.insert(rt);
1220 135542 : import_rt.push_back(irt);
1221 : }
1222 134317 : }
1223 143451 : BOOST_FOREACH(string ert, config_->export_list()) {
1224 46099 : error_code error;
1225 46099 : RouteTarget rt = RouteTarget::FromString(ert, &error);
1226 46254 : if (!error) {
1227 46252 : export_.insert(rt);
1228 46441 : export_rt.push_back(ert);
1229 : }
1230 46274 : }
1231 50932 : RTINSTANCE_LOG(Update, this,
1232 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL,
1233 : import_rt, export_rt, this->virtual_network_index());
1234 :
1235 51072 : if (import_rt.size())
1236 42723 : info.set_add_import_rt(import_rt);
1237 51082 : if (export_rt.size())
1238 42568 : info.set_add_export_rt(export_rt);
1239 51079 : if (import_rt.size() || export_rt.size())
1240 42742 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1241 :
1242 : // Create BGP Table
1243 51070 : if (name_ == BgpConfigManager::kMasterInstance) {
1244 8228 : assert(mgr_->count() == 0);
1245 8228 : is_master_ = true;
1246 :
1247 8228 : LocatePeerManager();
1248 8228 : VpnTableCreate(Address::INETVPN);
1249 8228 : VpnTableCreate(Address::INET6VPN);
1250 8228 : VpnTableCreate(Address::ERMVPN);
1251 8228 : VpnTableCreate(Address::MVPN);
1252 8228 : VpnTableCreate(Address::EVPN);
1253 8228 : RTargetTableCreate();
1254 :
1255 : BgpTable *table_inet = static_cast<BgpTable *>(
1256 8228 : server_->database()->CreateTable("inet.0"));
1257 8228 : assert(table_inet);
1258 8228 : AddTable(table_inet);
1259 :
1260 : BgpTable *table_inetmpls = static_cast<BgpTable *>(
1261 8228 : server_->database()->CreateTable("inet.3"));
1262 8228 : assert(table_inetmpls);
1263 8228 : AddTable(table_inetmpls);
1264 :
1265 : BgpTable *table_inet6 = static_cast<BgpTable *>(
1266 8228 : server_->database()->CreateTable("inet6.0"));
1267 8228 : assert(table_inet6);
1268 8228 : AddTable(table_inet6);
1269 : } else {
1270 : // Create foo.family.0.
1271 : // Create path-resolver in INET, INET6 and EVPN VRF tables to enable
1272 : // nh_reachability check for fast convergence.
1273 42848 : BgpTable *inet_table = VrfTableCreate(Address::INET, Address::INETVPN);
1274 42908 : inet_table->LocatePathResolver();
1275 :
1276 : BgpTable *inet6_table =
1277 42908 : VrfTableCreate(Address::INET6, Address::INET6VPN);
1278 42907 : inet6_table->LocatePathResolver();
1279 :
1280 42909 : VrfTableCreate(Address::ERMVPN, Address::ERMVPN);
1281 :
1282 42909 : BgpTable *evpn_table = VrfTableCreate(Address::EVPN, Address::EVPN);
1283 42908 : evpn_table->LocatePathResolver();
1284 :
1285 42909 : BgpTable *table = VrfTableCreate(Address::MVPN, Address::MVPN);
1286 :
1287 : // Create path-resolver in mvpn table.
1288 42909 : table->LocatePathResolver();
1289 : }
1290 :
1291 51137 : ProcessServiceChainConfig();
1292 51137 : ProcessStaticRouteConfig();
1293 51137 : ProcessRouteAggregationConfig();
1294 51136 : ProcessRoutingPolicyConfig();
1295 51133 : }
1296 :
1297 18607 : void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) {
1298 18607 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1299 :
1300 : // This is a noop in production code. However unit tests may pass a
1301 : // new object.
1302 18604 : config_ = cfg;
1303 :
1304 : // Always subscribe (using RTF) for RTs of PNF service chain instances.
1305 18604 : always_subscribe_ = config_->has_pnf();
1306 :
1307 : // Figure out if there's a significant configuration change that requires
1308 : // notifying routes to all listeners.
1309 18604 : bool notify_routes = false;
1310 18604 : if (virtual_network_allow_transit_ != cfg->virtual_network_allow_transit())
1311 128 : notify_routes = true;
1312 18604 : if (virtual_network_pbb_evpn_enable_ !=
1313 18604 : cfg->virtual_network_pbb_evpn_enable())
1314 0 : notify_routes = true;
1315 18604 : if (virtual_network_ != cfg->virtual_network())
1316 168 : notify_routes = true;
1317 18605 : if (virtual_network_index_ != cfg->virtual_network_index())
1318 180 : notify_routes = true;
1319 :
1320 : // Trigger notification of all routes in each table.
1321 18605 : if (notify_routes) {
1322 4092 : BOOST_FOREACH(RouteTableList::value_type &entry, vrf_tables_by_name_) {
1323 1892 : BgpTable *table = entry.second;
1324 1892 : table->NotifyAllEntries();
1325 : }
1326 : }
1327 :
1328 : // Update all static routes so that they reflect the new OriginVn.
1329 18605 : if (virtual_network_index_ != cfg->virtual_network_index())
1330 180 : UpdateAllStaticRoutes();
1331 :
1332 18605 : string prev_vn_name = GetVirtualNetworkName();
1333 :
1334 : // Update virtual network info.
1335 18605 : virtual_network_ = cfg->virtual_network();
1336 :
1337 : // Recreate instance stats' UVE, if its key: virtual_network is modified.
1338 18604 : if (prev_vn_name != GetVirtualNetworkName()) {
1339 5 : mgr_->DeleteVirtualNetworkMapping(prev_vn_name, name_);
1340 5 : mgr_->CreateVirtualNetworkMapping(GetVirtualNetworkName(), name_);
1341 : }
1342 :
1343 18606 : virtual_network_index_ = cfg->virtual_network_index();
1344 18606 : virtual_network_allow_transit_ = cfg->virtual_network_allow_transit();
1345 18606 : virtual_network_pbb_evpn_enable_ = cfg->virtual_network_pbb_evpn_enable();
1346 18605 : vxlan_id_ = cfg->vxlan_id();
1347 18605 : routing_instance_vxlan_ = cfg->routing_instance_vxlan();
1348 :
1349 : // Master routing instance doesn't have import & export list
1350 : // Master instance imports and exports all RT
1351 18605 : if (IsMasterRoutingInstance())
1352 12039 : return;
1353 :
1354 6566 : RouteTargetList future_import;
1355 6566 : vector<string> add_import_rt, remove_import_rt;
1356 818831 : BOOST_FOREACH(const string &rtarget_str, cfg->import_list()) {
1357 406118 : error_code error;
1358 406118 : RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
1359 406104 : if (!error)
1360 406105 : future_import.insert(rt);
1361 : }
1362 6562 : set_synchronize(&import_, &future_import,
1363 : boost::bind(&RoutingInstance::AddRouteTarget, this, true,
1364 : &add_import_rt, _1),
1365 : boost::bind(&RoutingInstance::DeleteRouteTarget, this, true,
1366 : &remove_import_rt, _1));
1367 :
1368 6566 : RouteTargetList future_export;
1369 6566 : vector<string> add_export_rt, remove_export_rt;
1370 791743 : BOOST_FOREACH(const string &rtarget_str, cfg->export_list()) {
1371 392587 : error_code error;
1372 392587 : RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
1373 392588 : if (!error)
1374 392587 : future_export.insert(rt);
1375 : }
1376 6567 : set_synchronize(&export_, &future_export,
1377 : boost::bind(&RoutingInstance::AddRouteTarget, this, false,
1378 : &add_export_rt, _1),
1379 : boost::bind(&RoutingInstance::DeleteRouteTarget, this, false,
1380 : &remove_export_rt, _1));
1381 :
1382 6563 : RoutingInstanceInfo info = GetDataCollection("");
1383 6565 : if (add_import_rt.size())
1384 2256 : info.set_add_import_rt(add_import_rt);
1385 6566 : if (remove_import_rt.size())
1386 1015 : info.set_remove_import_rt(remove_import_rt);
1387 6566 : if (add_export_rt.size())
1388 1257 : info.set_add_export_rt(add_export_rt);
1389 6566 : if (remove_export_rt.size())
1390 699 : info.set_remove_export_rt(remove_export_rt);
1391 14344 : if (add_import_rt.size() || remove_import_rt.size() ||
1392 14343 : add_export_rt.size() || remove_export_rt.size())
1393 3104 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1394 :
1395 6565 : ProcessServiceChainConfig();
1396 6567 : UpdateStaticRouteConfig();
1397 6567 : UpdateRouteAggregationConfig();
1398 6566 : UpdateRoutingPolicyConfig();
1399 18607 : }
1400 :
1401 61374 : void RoutingInstance::ClearConfig() {
1402 61374 : CHECK_CONCURRENCY("bgp::Config");
1403 61374 : config_ = NULL;
1404 61374 : }
1405 :
1406 51137 : void RoutingInstance::ManagedDelete() {
1407 : // RoutingInstanceMgr logs the delete for non-master instances.
1408 51137 : if (IsMasterRoutingInstance()) {
1409 8228 : RTINSTANCE_LOG(Delete, this,
1410 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1411 : }
1412 51137 : deleter_->Delete();
1413 51137 : }
1414 :
1415 51137 : void RoutingInstance::Shutdown() {
1416 51137 : CHECK_CONCURRENCY("bgp::Config");
1417 :
1418 51137 : RTINSTANCE_LOG(Shutdown, this,
1419 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1420 :
1421 51137 : ClearConfig();
1422 51137 : FlushAllRTargetRoutes(server_->local_autonomous_system());
1423 51137 : if (is_master_) {
1424 8228 : const Ip4Address old_identifier(server()->bgp_identifier());
1425 8228 : DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
1426 : old_identifier);
1427 : }
1428 51137 : ClearRouteTarget();
1429 :
1430 51137 : ProcessServiceChainConfig();
1431 51137 : FlushStaticRouteConfig();
1432 51137 : FlushRouteAggregationConfig();
1433 51137 : }
1434 :
1435 51137 : bool RoutingInstance::MayDelete() const {
1436 51137 : return true;
1437 : }
1438 :
1439 305058 : LifetimeActor *RoutingInstance::deleter() {
1440 305058 : return deleter_.get();
1441 : }
1442 :
1443 693818 : const LifetimeActor *RoutingInstance::deleter() const {
1444 693818 : return deleter_.get();
1445 : }
1446 :
1447 693399 : bool RoutingInstance::deleted() const {
1448 693399 : return deleter()->IsDeleted();
1449 : }
1450 :
1451 2593108 : const string RoutingInstance::GetVirtualNetworkName() const {
1452 2593108 : if (!virtual_network_.empty())
1453 494639 : return virtual_network_;
1454 2098516 : size_t pos = name_.rfind(':');
1455 2098509 : if (pos == string::npos) {
1456 807861 : return name_;
1457 : } else {
1458 1290648 : return name_.substr(0, pos);
1459 : }
1460 : }
1461 :
1462 4265870 : int RoutingInstance::virtual_network_index() const {
1463 4265870 : return virtual_network_index_;
1464 : }
1465 :
1466 2325 : bool RoutingInstance::virtual_network_allow_transit() const {
1467 2325 : return virtual_network_allow_transit_;
1468 : }
1469 :
1470 7518 : bool RoutingInstance::virtual_network_pbb_evpn_enable() const {
1471 7518 : return virtual_network_pbb_evpn_enable_;
1472 : }
1473 :
1474 8660 : int RoutingInstance::vxlan_id() const {
1475 8660 : return vxlan_id_;
1476 : }
1477 :
1478 214545 : void RoutingInstance::ClearFamilyRouteTarget(Address::Family vrf_family,
1479 : Address::Family vpn_family) {
1480 214545 : BgpTable *table = GetTable(vrf_family);
1481 214545 : if (table) {
1482 214545 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1483 1583475 : BOOST_FOREACH(RouteTarget rt, import_) {
1484 684465 : replicator->Leave(table, rt, true);
1485 : }
1486 684855 : BOOST_FOREACH(RouteTarget rt, export_) {
1487 235155 : replicator->Leave(table, rt, false);
1488 : }
1489 : }
1490 214545 : }
1491 :
1492 7953 : void RoutingInstance::AddRTargetRoute(uint32_t asn,
1493 : const RouteTarget &rtarget) {
1494 7953 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1495 :
1496 7953 : RTargetPrefix prefix(asn, rtarget);
1497 7953 : RTargetRoute rt_key(prefix);
1498 :
1499 7953 : RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
1500 7953 : BgpTable *table = master->GetTable(Address::RTARGET);
1501 : DBTablePartition *tbl_partition =
1502 7953 : static_cast<DBTablePartition *>(table->GetTablePartition(0));
1503 :
1504 7953 : std::scoped_lock lock(mgr_->mutex());
1505 : RTargetRoute *route =
1506 7953 : static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
1507 7953 : if (!route) {
1508 7822 : route = new RTargetRoute(prefix);
1509 7822 : tbl_partition->Add(route);
1510 : } else {
1511 131 : route->ClearDelete();
1512 : }
1513 :
1514 7953 : if (route->FindPath(BgpPath::Local, index_))
1515 0 : return;
1516 :
1517 7953 : BgpAttrSpec attr_spec;
1518 7953 : BgpAttrNextHop nexthop(server_->bgp_identifier());
1519 7953 : attr_spec.push_back(&nexthop);
1520 7953 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
1521 7953 : attr_spec.push_back(&origin);
1522 7953 : BgpAttrPtr attr = server_->attr_db()->Locate(attr_spec);
1523 :
1524 7953 : BgpPath *path = new BgpPath(index_, BgpPath::Local, attr);
1525 7953 : route->InsertPath(path);
1526 7953 : tbl_partition->Notify(route);
1527 7953 : BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
1528 : route, "Insert Local path with path id " << index_);
1529 7953 : }
1530 :
1531 176431 : void RoutingInstance::DeleteRTargetRoute(as_t asn,
1532 : const RouteTarget &rtarget) {
1533 176431 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1534 :
1535 176430 : if (asn == 0)
1536 168478 : return;
1537 :
1538 144612 : RTargetPrefix prefix(asn, rtarget);
1539 144612 : RTargetRoute rt_key(prefix);
1540 :
1541 144613 : RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
1542 144613 : BgpTable *table = master->GetTable(Address::RTARGET);
1543 : DBTablePartition *tbl_partition =
1544 144613 : static_cast<DBTablePartition *>(table->GetTablePartition(0));
1545 :
1546 144613 : std::scoped_lock lock(mgr_->mutex());
1547 : RTargetRoute *route =
1548 144613 : static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
1549 144613 : if (!route || !route->RemovePath(BgpPath::Local, index_))
1550 136660 : return;
1551 :
1552 7953 : BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
1553 : route, "Delete Local path with path id " << index_);
1554 7953 : if (!route->HasPaths()) {
1555 7824 : tbl_partition->Delete(route);
1556 : } else {
1557 129 : tbl_partition->Notify(route);
1558 : }
1559 281273 : }
1560 :
1561 74359 : void RoutingInstance::InitAllRTargetRoutes(as_t asn) {
1562 74359 : if (is_master_)
1563 23065 : return;
1564 :
1565 51294 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1566 382788 : BOOST_FOREACH(RouteTarget rtarget, import_) {
1567 165747 : if (asn != 0 && always_subscribe_)
1568 350 : AddRTargetRoute(asn, rtarget);
1569 : }
1570 : }
1571 :
1572 74359 : void RoutingInstance::FlushAllRTargetRoutes(as_t asn) {
1573 74359 : if (is_master_)
1574 23065 : return;
1575 :
1576 51294 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1577 385150 : BOOST_FOREACH(RouteTarget rtarget, import_) {
1578 166928 : DeleteRTargetRoute(asn, rtarget);
1579 : }
1580 : }
1581 :
1582 12184 : void RoutingInstance::ProcessIdentifierUpdate(as_t asn) {
1583 12184 : FlushAllRTargetRoutes(asn);
1584 12184 : InitAllRTargetRoutes(asn);
1585 12184 : rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index_));
1586 12184 : }
1587 :
1588 3550 : void RoutingInstance::AddRouteTarget(bool import,
1589 : vector<string> *change_list, RouteTargetList::const_iterator it) {
1590 3550 : BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
1591 : RoutePathReplicator *ermvpn_replicator =
1592 3548 : server_->replicator(Address::ERMVPN);
1593 3548 : BgpTable *mvpn_table = GetTable(Address::MVPN);
1594 : RoutePathReplicator *mvpn_replicator =
1595 3547 : server_->replicator(Address::MVPN);
1596 3547 : BgpTable *evpn_table = GetTable(Address::EVPN);
1597 : RoutePathReplicator *evpn_replicator =
1598 3545 : server_->replicator(Address::EVPN);
1599 3545 : BgpTable *inet_table = GetTable(Address::INET);
1600 : RoutePathReplicator *inetvpn_replicator =
1601 3546 : server_->replicator(Address::INETVPN);
1602 3546 : BgpTable *inet6_table = GetTable(Address::INET6);
1603 : RoutePathReplicator *inet6vpn_replicator =
1604 3547 : server_->replicator(Address::INET6VPN);
1605 :
1606 3547 : change_list->push_back(it->ToString());
1607 3547 : if (import) {
1608 2282 : import_.insert(*it);
1609 2287 : if (server_->local_autonomous_system() != 0 && always_subscribe_)
1610 46 : AddRTargetRoute(server_->local_autonomous_system(), *it);
1611 : } else {
1612 1265 : export_.insert(*it);
1613 : }
1614 :
1615 3551 : ermvpn_replicator->Join(ermvpn_table, *it, import);
1616 3552 : mvpn_replicator->Join(mvpn_table, *it, import);
1617 3552 : evpn_replicator->Join(evpn_table, *it, import);
1618 3552 : inetvpn_replicator->Join(inet_table, *it, import);
1619 3552 : inet6vpn_replicator->Join(inet6_table, *it, import);
1620 3552 : }
1621 :
1622 1807 : void RoutingInstance::DeleteRouteTarget(bool import,
1623 : vector<string> *change_list, RouteTargetList::iterator it) {
1624 1807 : BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
1625 : RoutePathReplicator *ermvpn_replicator =
1626 1805 : server_->replicator(Address::ERMVPN);
1627 1805 : BgpTable *mvpn_table = GetTable(Address::MVPN);
1628 : RoutePathReplicator *mvpn_replicator =
1629 1806 : server_->replicator(Address::MVPN);
1630 1806 : BgpTable *evpn_table = GetTable(Address::EVPN);
1631 : RoutePathReplicator *evpn_replicator =
1632 1806 : server_->replicator(Address::EVPN);
1633 1806 : BgpTable *inet_table = GetTable(Address::INET);
1634 : RoutePathReplicator *inetvpn_replicator =
1635 1806 : server_->replicator(Address::INETVPN);
1636 1806 : BgpTable *inet6_table = GetTable(Address::INET6);
1637 : RoutePathReplicator *inet6vpn_replicator =
1638 1806 : server_->replicator(Address::INET6VPN);
1639 :
1640 1806 : ermvpn_replicator->Leave(ermvpn_table, *it, import);
1641 1808 : mvpn_replicator->Leave(mvpn_table, *it, import);
1642 1808 : evpn_replicator->Leave(evpn_table, *it, import);
1643 1808 : inetvpn_replicator->Leave(inet_table, *it, import);
1644 1808 : inet6vpn_replicator->Leave(inet6_table, *it, import);
1645 :
1646 1808 : change_list->push_back(it->ToString());
1647 1808 : if (import) {
1648 1108 : DeleteRTargetRoute(server_->local_autonomous_system(), *it);
1649 1108 : import_.erase(it);
1650 : } else {
1651 700 : export_.erase(it);
1652 : }
1653 1808 : }
1654 :
1655 51137 : void RoutingInstance::ClearRouteTarget() {
1656 51137 : CHECK_CONCURRENCY("bgp::Config");
1657 51137 : if (IsMasterRoutingInstance()) {
1658 8228 : return;
1659 : }
1660 :
1661 42909 : ClearFamilyRouteTarget(Address::INET, Address::INETVPN);
1662 42909 : ClearFamilyRouteTarget(Address::INET6, Address::INET6VPN);
1663 42909 : ClearFamilyRouteTarget(Address::ERMVPN, Address::ERMVPN);
1664 42909 : ClearFamilyRouteTarget(Address::MVPN, Address::MVPN);
1665 42909 : ClearFamilyRouteTarget(Address::EVPN, Address::EVPN);
1666 :
1667 42909 : import_.clear();
1668 42909 : export_.clear();
1669 : }
1670 :
1671 8228 : BgpTable *RoutingInstance::RTargetTableCreate() {
1672 : BgpTable *rtargettbl = static_cast<BgpTable *>(
1673 8228 : server_->database()->CreateTable("bgp.rtarget.0"));
1674 8228 : RTINSTANCE_LOG_TABLE(Create, this, rtargettbl, SandeshLevel::SYS_DEBUG,
1675 : RTINSTANCE_LOG_FLAG_ALL);
1676 8228 : AddTable(rtargettbl);
1677 8228 : return rtargettbl;
1678 : }
1679 :
1680 41140 : BgpTable *RoutingInstance::VpnTableCreate(Address::Family vpn_family) {
1681 41140 : string table_name = GetTableName(name(), vpn_family);
1682 : BgpTable *table = static_cast<BgpTable *>(
1683 41140 : server_->database()->CreateTable(table_name));
1684 41140 : assert(table);
1685 :
1686 41140 : AddTable(table);
1687 41140 : RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
1688 : RTINSTANCE_LOG_FLAG_ALL);
1689 41140 : assert(server_->rtarget_group_mgr()->empty());
1690 41140 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1691 41140 : replicator->Initialize();
1692 41140 : return table;
1693 41140 : }
1694 :
1695 214450 : BgpTable *RoutingInstance::VrfTableCreate(Address::Family vrf_family,
1696 : Address::Family vpn_family) {
1697 214450 : string table_name = GetTableName(name(), vrf_family);
1698 : BgpTable *table = static_cast<BgpTable *>(
1699 214497 : server_->database()->CreateTable(table_name));
1700 214544 : assert(table);
1701 :
1702 214544 : AddTable(table);
1703 214504 : RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
1704 : RTINSTANCE_LOG_FLAG_ALL);
1705 214505 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1706 1571534 : BOOST_FOREACH(RouteTarget rt, import_) {
1707 678182 : replicator->Join(table, rt, true);
1708 : }
1709 679143 : BOOST_FOREACH(RouteTarget rt, export_) {
1710 232261 : replicator->Join(table, rt, false);
1711 : }
1712 214535 : return table;
1713 214537 : }
1714 :
1715 288596 : void RoutingInstance::AddTable(BgpTable *tbl) {
1716 288596 : vrf_tables_by_name_.insert(make_pair(tbl->name(), tbl));
1717 288597 : vrf_tables_by_family_.insert(make_pair(tbl->family(), tbl));
1718 288594 : tbl->set_routing_instance(this);
1719 288575 : RoutingInstanceInfo info = GetDataCollection("Add");
1720 288554 : info.set_family(Address::FamilyToString(tbl->family()));
1721 288580 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1722 288581 : }
1723 :
1724 288597 : void RoutingInstance::RemoveTable(BgpTable *tbl) {
1725 288597 : RoutingInstanceInfo info = GetDataCollection("Remove");
1726 288597 : info.set_family(Address::FamilyToString(tbl->family()));
1727 288597 : vrf_tables_by_name_.erase(tbl->name());
1728 288597 : vrf_tables_by_family_.erase(tbl->family());
1729 288597 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1730 288597 : }
1731 :
1732 : //
1733 : // Concurrency: BGP Config task
1734 : //
1735 : // Remove the table from the map and delete the table data structure
1736 : //
1737 288597 : void RoutingInstance::DestroyDBTable(DBTable *dbtable) {
1738 288597 : CHECK_CONCURRENCY("bgp::Config");
1739 :
1740 288597 : BgpTable *table = static_cast<BgpTable *>(dbtable);
1741 :
1742 288597 : RTINSTANCE_LOG_TABLE(Destroy, this, table,
1743 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1744 :
1745 : // Remove this table from various data structures
1746 288597 : server_->database()->RemoveTable(table);
1747 288597 : RemoveTable(table);
1748 :
1749 : // Make sure that there are no routes left in this table
1750 288597 : assert(table->Size() == 0);
1751 :
1752 288597 : delete table;
1753 288597 : }
1754 :
1755 256887 : string RoutingInstance::GetTableName(string instance_name,
1756 : Address::Family fmly) {
1757 256887 : string table_name;
1758 256888 : if (instance_name == BgpConfigManager::kMasterInstance) {
1759 41234 : if ((fmly == Address::INET) || (fmly == Address::INET6)) {
1760 94 : table_name = Address::FamilyToTableString(fmly) + ".0";
1761 41140 : } else if (fmly == Address::INETMPLS) {
1762 0 : table_name = Address::FamilyToTableString(fmly) + ".3";
1763 : } else {
1764 41140 : table_name = "bgp." + Address::FamilyToTableString(fmly) + ".0";
1765 : }
1766 : } else {
1767 : table_name =
1768 215718 : instance_name + "." + Address::FamilyToTableString(fmly) + ".0";
1769 : }
1770 256947 : return table_name;
1771 0 : }
1772 :
1773 1251734 : BgpTable *RoutingInstance::GetTable(Address::Family fmly) {
1774 1251734 : RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
1775 1251612 : return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
1776 : }
1777 :
1778 141138 : const BgpTable *RoutingInstance::GetTable(Address::Family fmly) const {
1779 141138 : RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
1780 141138 : return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
1781 : }
1782 :
1783 252 : string RoutingInstance::GetVrfFromTableName(const string table) {
1784 252 : static set<string> master_tables = list_of("inet.0")("inet.3")("inet6.0");
1785 : static set<string> vpn_tables =
1786 8 : list_of("bgp.l3vpn.0")("bgp.ermvpn.0")("bgp.evpn.0")("bgp.rtarget.0")
1787 256 : ("bgp.l3vpn-inet6.0")("bgp.mvpn.0");
1788 :
1789 252 : if (master_tables.find(table) != master_tables.end())
1790 0 : return BgpConfigManager::kMasterInstance;
1791 248 : if (vpn_tables.find(table) != vpn_tables.end())
1792 16 : return BgpConfigManager::kMasterInstance;
1793 :
1794 234 : size_t pos1 = table.rfind('.');
1795 234 : if (pos1 == string::npos)
1796 4 : return "__unknown__";
1797 230 : size_t pos2 = table.rfind('.', pos1 - 1);
1798 230 : if (pos2 == string::npos)
1799 4 : return "__unknown__";
1800 :
1801 226 : return table.substr(0, pos2);
1802 : }
1803 :
1804 51137 : void RoutingInstance::set_index(int index) {
1805 51137 : index_ = index;
1806 51137 : if (is_master_)
1807 8228 : return;
1808 :
1809 42909 : rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index));
1810 : }
1811 :
1812 651128 : RoutingInstanceInfo RoutingInstance::GetDataCollection(const char *operation) {
1813 1302098 : RoutingInstanceInfo info;
1814 650969 : info.set_name(GetVirtualNetworkName());
1815 651076 : info.set_instance_name(name_);
1816 651076 : info.set_hostname(server_->localname());
1817 651057 : if (rd_.get()) info.set_route_distinguisher(rd_->ToString());
1818 651036 : if (operation) info.set_operation(operation);
1819 651012 : return info;
1820 0 : }
1821 :
1822 : //
1823 : // Return true if one of the route targets in the ExtCommunity is in the
1824 : // set of export RouteTargets for this RoutingInstance.
1825 : //
1826 468 : bool RoutingInstance::HasExportTarget(const ExtCommunity *extcomm) const {
1827 468 : if (!extcomm)
1828 0 : return false;
1829 :
1830 1544 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &value,
1831 : extcomm->communities()) {
1832 906 : if (!ExtCommunity::is_route_target(value))
1833 32 : continue;
1834 874 : RouteTarget rtarget(value);
1835 874 : if (export_.find(rtarget) != export_.end())
1836 368 : return true;
1837 : }
1838 :
1839 100 : return false;
1840 : }
1841 :
1842 : // Return true if the route is a service-chain route
1843 387146 : bool RoutingInstance::IsServiceChainRoute(const BgpRoute *route) const {
1844 387146 : const BgpTable *table = route->table();
1845 387172 : if (!table) {
1846 0 : return false;
1847 : }
1848 387172 : const BgpInstanceConfig *rt_config = this->config();
1849 387171 : if (!rt_config) {
1850 0 : return false;
1851 : }
1852 : SCAddress::Family sc_family =
1853 387171 : SCAddress::AddressFamilyToSCFamily(table->family());
1854 : const ServiceChainConfig *sc_config =
1855 387171 : rt_config->service_chain_info(sc_family);
1856 387160 : if (!sc_config) {
1857 384183 : return false;
1858 : }
1859 2977 : return true;
1860 : }
1861 :
1862 : //
1863 : // On given route/path apply the routing policy
1864 : // Called from
1865 : // * InsertPath [While adding the path for the first time]
1866 : // * While walking the routing table to apply updating routing policy
1867 : //
1868 :
1869 451420 : bool RoutingInstance::ProcessRoutingPolicy(const BgpRoute *route,
1870 : BgpPath *path) const {
1871 451420 : ExtCommunityPtr ext_community = path->GetOriginalAttr()->ext_community();
1872 838705 : if (path->IsReplicated() &&
1873 838700 : ext_community && ext_community->GetSubClusterId()) {
1874 : // If self sub-cluster id macthes with what is associated with the route
1875 : // then no need to apply policy.
1876 0 : if (route->SubClusterId() == ext_community->GetSubClusterId()) {
1877 0 : BGP_LOG_ROUTE(route->table(), static_cast<IPeer *>(path->GetPeer()),
1878 : route, "Not applying policy since sub-cluster associated "
1879 : "with path is same as that with route");
1880 0 : return true;
1881 : }
1882 : }
1883 : // Don't apply routing policy on secondary path for service chain route
1884 451415 : if (path->IsReplicated() && IsServiceChainRoute(route)) {
1885 2974 : BGP_LOG_ROUTE(route->table(), static_cast<IPeer *>(path->GetPeer()),
1886 : route, "Not applying policy for service-chain secondary "
1887 : "routes");
1888 2974 : return true;
1889 : }
1890 448443 : const RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1891 : // Take snapshot of original attribute
1892 448448 : BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
1893 449774 : BOOST_FOREACH(RoutingPolicyInfo info, routing_policies()) {
1894 763 : RoutingPolicyPtr policy = info.first;
1895 : // Process the routing policy on original attribute and prefix
1896 : // Update of the attribute based on routing policy action is done
1897 : // on the snapshot of original attribute passed to this function
1898 : RoutingPolicy::PolicyResult result =
1899 762 : policy_mgr->ExecuteRoutingPolicy(policy.get(), route,
1900 : path, out_attr);
1901 761 : if (result.first) {
1902 : // Hit a terminal policy
1903 144 : if (!result.second) {
1904 : // Result of the policy is reject
1905 14 : path->SetPolicyReject();
1906 130 : } else if (path->IsPolicyReject()) {
1907 : // Result of the policy is Accept
1908 : // Clear the reject flag is marked before
1909 1 : path->ResetPolicyReject();
1910 : }
1911 144 : IPeer *peer = path->GetPeer();
1912 : // Process default tunnel encapsulation that may be configured per
1913 : // address family on the peer. 'peer' is not expected to be NULL
1914 : // except in unit tests.
1915 144 : if (peer) {
1916 278 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
1917 139 : server_->extcomm_db(), route->table());
1918 : }
1919 144 : BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
1920 : // Update the path with new set of attributes
1921 144 : path->SetAttr(modified_attr, path->GetOriginalAttr());
1922 144 : return result.second;
1923 144 : }
1924 1524 : }
1925 : // After processing all the routing policy,,
1926 : // We are here means, all the routing policies have accepted the route
1927 448229 : IPeer *peer = path->GetPeer();
1928 448228 : if (peer) {
1929 758571 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
1930 379317 : server_->extcomm_db(), route->table());
1931 : }
1932 448248 : BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
1933 448392 : path->SetAttr(modified_attr, path->GetOriginalAttr());
1934 : // Clear the reject if marked so in past
1935 448397 : if (path->IsPolicyReject()) path->ResetPolicyReject();
1936 448387 : return true;
1937 451505 : }
1938 :
1939 122 : IStaticRouteMgr *RoutingInstance::LocateStaticRouteMgr(
1940 : Address::Family family) {
1941 122 : IStaticRouteMgr *manager = static_route_mgr(family);
1942 122 : if (manager)
1943 0 : return manager;
1944 122 : if (family == Address::INET) {
1945 79 : inet_static_route_mgr_.reset(
1946 79 : BgpStaticObjectFactory::Create<IStaticRouteMgr, Address::INET>(this));
1947 79 : return inet_static_route_mgr_.get();
1948 43 : } else if (family == Address::INET6) {
1949 43 : inet6_static_route_mgr_.reset(
1950 43 : BgpStaticObjectFactory::Create<IStaticRouteMgr, Address::INET6>(this));
1951 43 : return inet6_static_route_mgr_.get();
1952 : }
1953 0 : return NULL;
1954 : }
1955 :
1956 160 : IRouteAggregator *RoutingInstance::LocateRouteAggregator(
1957 : Address::Family family) {
1958 160 : IRouteAggregator *aggregator = route_aggregator(family);
1959 160 : if (aggregator)
1960 0 : return aggregator;
1961 160 : if (family == Address::INET) {
1962 152 : GetTable(family)->LocatePathResolver();
1963 152 : inet_route_aggregator_.reset(
1964 152 : BgpStaticObjectFactory::Create<IRouteAggregator, Address::INET>(this));
1965 152 : inet_route_aggregator_->Initialize();
1966 152 : return inet_route_aggregator_.get();
1967 8 : } else if (family == Address::INET6) {
1968 8 : GetTable(family)->LocatePathResolver();
1969 8 : inet6_route_aggregator_.reset(
1970 8 : BgpStaticObjectFactory::Create<IRouteAggregator, Address::INET6>(this));
1971 8 : inet6_route_aggregator_->Initialize();
1972 8 : return inet6_route_aggregator_.get();
1973 : }
1974 0 : return NULL;
1975 : }
1976 :
1977 160 : void RoutingInstance::DestroyRouteAggregator(Address::Family family) {
1978 160 : if (family == Address::INET) {
1979 152 : inet_route_aggregator_.reset();
1980 8 : } else if (family == Address::INET6) {
1981 8 : inet6_route_aggregator_.reset();
1982 : }
1983 160 : }
1984 :
1985 : // Check whether the route is aggregating route
1986 200 : bool RoutingInstance::IsAggregateRoute(const BgpTable *table,
1987 : const BgpRoute *route) const {
1988 200 : if (!route_aggregator(table->family())) return false;
1989 200 : return route_aggregator(table->family())->IsAggregateRoute(route);
1990 : }
1991 :
1992 : // Check whether the route is contributing route to aggregate route
1993 920761 : bool RoutingInstance::IsContributingRoute(const BgpTable *table,
1994 : const BgpRoute *route) const {
1995 920761 : if (!route_aggregator(table->family())) return false;
1996 1894 : return route_aggregator(table->family())->IsContributingRoute(route);
1997 : }
1998 :
1999 2045 : int RoutingInstance::GetOriginVnForAggregateRoute(Address::Family fmly) const {
2000 : SCAddress sc_addr;
2001 : SCAddress::Family sc_family =
2002 2045 : sc_addr.AddressFamilyToSCFamily(fmly);
2003 : const ServiceChainConfig *sc_config =
2004 2045 : config_ ? config_->service_chain_info(sc_family) : NULL;
2005 2045 : if (sc_config && !sc_config->routing_instance.empty()) {
2006 : RoutingInstance *dest =
2007 37 : mgr_->GetRoutingInstanceLocked(sc_config->routing_instance);
2008 37 : if (dest) return dest->virtual_network_index();
2009 : }
2010 2008 : return virtual_network_index_;
2011 : }
2012 :
2013 25 : size_t RoutingInstance::peer_manager_size() const {
2014 25 : return (peer_manager_ ? peer_manager_->size() : 0);
2015 : }
2016 :
2017 19224 : PeerManager *RoutingInstance::LocatePeerManager() {
2018 19224 : if (!peer_manager_)
2019 8350 : peer_manager_.reset(BgpStaticObjectFactory::Create<PeerManager>(this));
2020 19224 : return peer_manager_.get();
2021 : }
2022 :
2023 : // Get primary routing instance name from service RI names which works for both
2024 : // in-network and transparent service chains. Use name based lookup to identify
2025 : // the primary RI of service instance.
2026 : // Service RI Name Format: <domain>:<project>:<VN>:<ServiceRI>
2027 : // Primaru RI Name Format: <domain>:<project>:<VN>:<VN>
2028 16487 : string RoutingInstanceMgr::GetPrimaryRoutingInstanceName(const string &name) {
2029 16487 : string n = name;
2030 16487 : vector<string> tokens;
2031 16487 : boost::split(tokens, n, boost::is_any_of(":"));
2032 16487 : if (tokens.size() < 3)
2033 16485 : return "";
2034 2 : ostringstream os;
2035 2 : os << tokens[0] << ":" << tokens[1] << ":" << tokens[2] << ":" << tokens[2];
2036 2 : return os.str();
2037 16487 : }
|