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