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 32 : explicit DeleteActor(RoutingInstanceMgr *manager)
47 32 : : LifetimeActor(manager->server_->lifetime_manager()),
48 32 : manager_(manager) {
49 32 : }
50 32 : virtual bool MayDelete() const {
51 32 : return manager_->MayDelete();
52 : }
53 32 : virtual void Shutdown() {
54 32 : manager_->Shutdown();
55 32 : }
56 32 : virtual void Destroy() {
57 32 : manager_->server_delete_ref_.Reset(NULL);
58 32 : }
59 :
60 : private:
61 : RoutingInstanceMgr *manager_;
62 : };
63 :
64 32 : RoutingInstanceMgr::RoutingInstanceMgr(BgpServer *server) :
65 32 : server_(server),
66 64 : instance_config_lists_(
67 32 : TaskScheduler::GetInstance()->HardwareThreadCount()),
68 32 : default_rtinstance_(NULL),
69 32 : deleted_count_(0),
70 32 : asn_listener_id_(server->RegisterASNUpdateCallback(
71 : boost::bind(&RoutingInstanceMgr::ASNUpdateCallback, this, _1, _2))),
72 32 : identifier_listener_id_(server->RegisterIdentifierUpdateCallback(
73 : boost::bind(&RoutingInstanceMgr::IdentifierUpdateCallback,
74 : this, _1))),
75 32 : dormant_trace_buf_size_(
76 32 : GetEnvRoutingInstanceDormantTraceBufferCapacity()),
77 32 : trace_buf_threshold_(
78 32 : GetEnvRoutingInstanceDormantTraceBufferThreshold()),
79 32 : deleter_(new DeleteActor(this)),
80 96 : server_delete_ref_(this, server->deleter()) {
81 32 : int task_id = TaskScheduler::GetInstance()->GetTaskId("bgp::ConfigHelper");
82 32 : int hw_thread_count = TaskScheduler::GetInstance()->HardwareThreadCount();
83 160 : for (int idx = 0; idx < hw_thread_count; ++idx) {
84 256 : instance_config_triggers_.push_back(new TaskTrigger(boost::bind(
85 : &RoutingInstanceMgr::ProcessInstanceConfigList, this, idx),
86 128 : task_id, idx));
87 : }
88 64 : neighbor_config_trigger_.reset(new TaskTrigger(
89 : boost::bind(&RoutingInstanceMgr::ProcessNeighborConfigList, this),
90 64 : TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0));
91 32 : }
92 :
93 64 : RoutingInstanceMgr::~RoutingInstanceMgr() {
94 32 : assert(mvpn_project_managers_.empty());
95 32 : assert(virtual_networks_.empty());
96 32 : assert(deleted_count_ == 0);
97 32 : server_->UnregisterASNUpdateCallback(asn_listener_id_);
98 32 : server_->UnregisterIdentifierUpdateCallback(identifier_listener_id_);
99 32 : STLDeleteValues(&instance_config_triggers_);
100 64 : }
101 :
102 0 : size_t RoutingInstanceMgr::GetMvpnProjectManagerCount(
103 : const string &network) const {
104 0 : std::scoped_lock lock(mutex_);
105 :
106 : MvpnProjectManagerNetworks::const_iterator iter =
107 0 : mvpn_project_managers_.find(network);
108 0 : if (iter == mvpn_project_managers_.end())
109 0 : return 0;
110 0 : return iter->second.size();
111 0 : }
112 :
113 32 : void RoutingInstanceMgr::ManagedDelete() {
114 32 : deleter_->Delete();
115 32 : }
116 :
117 32 : void RoutingInstanceMgr::Shutdown() {
118 160 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
119 128 : InstanceTargetRemove(it->second);
120 128 : InstanceVnIndexRemove(it->second);
121 : }
122 32 : }
123 :
124 32 : bool RoutingInstanceMgr::MayDelete() const {
125 32 : if (!neighbor_config_list_.empty())
126 0 : return false;
127 160 : for (size_t idx = 0; idx < instance_config_lists_.size(); ++idx) {
128 128 : if (!instance_config_lists_[idx].empty())
129 0 : return false;
130 : }
131 32 : return true;
132 : }
133 :
134 319 : LifetimeActor *RoutingInstanceMgr::deleter() {
135 319 : return deleter_.get();
136 : }
137 :
138 191 : bool RoutingInstanceMgr::deleted() {
139 191 : 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 192 : void RoutingInstanceMgr::InstanceTargetAdd(RoutingInstance *rti) {
151 192 : std::scoped_lock lock(mutex_);
152 192 : for (RoutingInstance::RouteTargetList::const_iterator it =
153 480 : rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
154 96 : if (rti->GetImportList().find(*it) == rti->GetImportList().end())
155 0 : continue;
156 96 : target_map_.insert(make_pair(*it, rti));
157 : }
158 192 : }
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 192 : void RoutingInstanceMgr::InstanceTargetRemove(const RoutingInstance *rti) {
170 192 : std::scoped_lock lock(mutex_);
171 192 : for (RoutingInstance::RouteTargetList::const_iterator it =
172 480 : rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
173 96 : if (rti->GetImportList().find(*it) == rti->GetImportList().end())
174 0 : continue;
175 96 : for (InstanceTargetMap::iterator loc = target_map_.find(*it);
176 96 : loc != target_map_.end() && loc->first == *it; ++loc) {
177 96 : if (loc->second == rti) {
178 96 : target_map_.erase(loc);
179 96 : break;
180 : }
181 : }
182 : }
183 192 : }
184 :
185 : //
186 : // Lookup the RoutingInstance for the given RouteTarget.
187 : //
188 0 : const RoutingInstance *RoutingInstanceMgr::GetInstanceByTarget(
189 : const RouteTarget &rtarget) const {
190 0 : InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
191 0 : if (loc == target_map_.end()) {
192 0 : return NULL;
193 : }
194 0 : return loc->second;
195 : }
196 :
197 : //
198 : // Add an entry for the vn index to the VnIndexMap.
199 : //
200 192 : void RoutingInstanceMgr::InstanceVnIndexAdd(RoutingInstance *rti) {
201 192 : std::scoped_lock lock(mutex_);
202 192 : if (rti->virtual_network_index())
203 0 : vn_index_map_.insert(make_pair(rti->virtual_network_index(), rti));
204 192 : }
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 192 : void RoutingInstanceMgr::InstanceVnIndexRemove(const RoutingInstance *rti) {
212 192 : std::scoped_lock lock(mutex_);
213 192 : if (!rti->virtual_network_index())
214 192 : return;
215 :
216 0 : int vn_index = rti->virtual_network_index();
217 0 : for (VnIndexMap::iterator loc = vn_index_map_.find(vn_index);
218 0 : loc != vn_index_map_.end() && loc->first == vn_index; ++loc) {
219 0 : if (loc->second == rti) {
220 0 : vn_index_map_.erase(loc);
221 0 : break;
222 : }
223 : }
224 192 : }
225 :
226 : //
227 : // Lookup the RoutingInstance for the given vn index.
228 : //
229 0 : const RoutingInstance *RoutingInstanceMgr::GetInstanceByVnIndex(
230 : int vn_index) const {
231 0 : VnIndexMap::const_iterator loc = vn_index_map_.find(vn_index);
232 0 : if (loc == vn_index_map_.end())
233 0 : return NULL;
234 0 : return loc->second;
235 : }
236 :
237 : //
238 : // Lookup the VN name for the given vn index.
239 : //
240 0 : string RoutingInstanceMgr::GetVirtualNetworkByVnIndex(
241 : int vn_index) const {
242 0 : const RoutingInstance *rti = GetInstanceByVnIndex(vn_index);
243 0 : 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 180 : int RoutingInstanceMgr::GetVnIndexByRouteTarget(
254 : const RouteTarget &rtarget) const {
255 180 : int vn_index = 0;
256 180 : for (InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
257 312 : loc != target_map_.end() && loc->first == rtarget; ++loc) {
258 132 : int ri_vn_index = loc->second->virtual_network_index();
259 132 : if (vn_index && ri_vn_index && ri_vn_index != vn_index)
260 0 : return -1;
261 132 : vn_index = ri_vn_index;
262 : }
263 :
264 180 : 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 176 : int RoutingInstanceMgr::GetVnIndexByExtCommunity(
275 : const ExtCommunity *ext_community) const {
276 176 : int vn_index = 0;
277 664 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
278 : ext_community->communities()) {
279 244 : if (!ExtCommunity::is_route_target(comm))
280 64 : continue;
281 :
282 180 : RouteTarget rtarget(comm);
283 180 : int rtgt_vn_index = GetVnIndexByRouteTarget(rtarget);
284 180 : if (rtgt_vn_index < 0 ||
285 0 : (vn_index && rtgt_vn_index && rtgt_vn_index != vn_index)) {
286 0 : vn_index = 0;
287 0 : break;
288 180 : } else if (rtgt_vn_index) {
289 0 : vn_index = rtgt_vn_index;
290 : }
291 : }
292 :
293 176 : return vn_index;
294 : }
295 :
296 : int
297 128 : RoutingInstanceMgr::RegisterInstanceOpCallback(RoutingInstanceCb callback) {
298 128 : std::scoped_lock lock(mutex_);
299 128 : size_t i = bmap_.find_first();
300 128 : if (i == bmap_.npos) {
301 128 : i = callbacks_.size();
302 128 : callbacks_.push_back(callback);
303 : } else {
304 0 : bmap_.reset(i);
305 0 : if (bmap_.none()) {
306 0 : bmap_.clear();
307 : }
308 0 : callbacks_[i] = callback;
309 : }
310 128 : return i;
311 128 : }
312 :
313 128 : void RoutingInstanceMgr::UnregisterInstanceOpCallback(int listener) {
314 128 : std::scoped_lock lock(mutex_);
315 128 : callbacks_[listener] = NULL;
316 128 : if ((size_t) listener == callbacks_.size() - 1) {
317 160 : while (!callbacks_.empty() && callbacks_.back() == NULL) {
318 128 : callbacks_.pop_back();
319 : }
320 32 : if (bmap_.size() > callbacks_.size()) {
321 32 : bmap_.resize(callbacks_.size());
322 : }
323 : } else {
324 96 : if ((size_t) listener >= bmap_.size()) {
325 96 : bmap_.resize(listener + 1);
326 : }
327 96 : bmap_.set(listener);
328 : }
329 128 : }
330 :
331 320 : void RoutingInstanceMgr::NotifyInstanceOp(string name, Operation op) {
332 320 : std::scoped_lock lock(mutex_);
333 320 : for (InstanceOpListenersList::iterator iter = callbacks_.begin();
334 1088 : iter != callbacks_.end(); ++iter) {
335 768 : if (*iter != NULL) {
336 768 : RoutingInstanceCb cb = *iter;
337 768 : (cb)(name, op);
338 768 : }
339 : }
340 320 : }
341 :
342 63 : bool RoutingInstanceMgr::ProcessInstanceConfigList(int idx) {
343 63 : if (deleted()) {
344 0 : deleter()->RetryDelete();
345 : } else {
346 254 : BOOST_FOREACH(const string &name, instance_config_lists_[idx]) {
347 : const BgpInstanceConfig *config =
348 95 : server()->config_manager()->FindInstance(name);
349 96 : if (!config)
350 0 : continue;
351 96 : LocateRoutingInstance(config);
352 : }
353 : }
354 :
355 64 : instance_config_lists_[idx].clear();
356 64 : return true;
357 : }
358 :
359 704 : RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() {
360 704 : return default_rtinstance_;
361 : }
362 :
363 0 : const RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() const {
364 0 : return default_rtinstance_;
365 : }
366 :
367 216 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(const string &name) {
368 216 : RoutingInstanceList::iterator iter = instances_.find(name);
369 216 : if (iter != instances_.end())
370 216 : return iter->second;
371 0 : return NULL;
372 : }
373 :
374 119 : const RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(
375 : const string &name) const {
376 119 : RoutingInstanceList::const_iterator iter = instances_.find(name);
377 119 : if (iter != instances_.end())
378 96 : return iter->second;
379 23 : return NULL;
380 : }
381 :
382 191 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstanceLocked(
383 : const string &name) {
384 191 : std::scoped_lock lock(mutex_);
385 192 : RoutingInstanceList::iterator iter = instances_.find(name);
386 192 : if (iter != instances_.end())
387 64 : return iter->second;
388 128 : return NULL;
389 192 : }
390 :
391 128 : void RoutingInstanceMgr::InsertRoutingInstance(RoutingInstance *rtinstance) {
392 128 : std::scoped_lock lock(mutex_);
393 128 : instances_.insert(make_pair(rtinstance->config()->name(),
394 : rtinstance));
395 128 : }
396 :
397 191 : void RoutingInstanceMgr::LocateRoutingInstance(
398 : const BgpInstanceConfig *config) {
399 191 : RoutingInstance *rtinstance = GetRoutingInstanceLocked(config->name());
400 192 : if (rtinstance) {
401 64 : if (rtinstance->deleted()) {
402 0 : 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 64 : UpdateRoutingInstance(rtinstance, config);
408 : }
409 : } else {
410 128 : rtinstance = CreateRoutingInstance(config);
411 : }
412 192 : }
413 :
414 384 : void RoutingInstanceMgr::LocateRoutingInstance(const string &name) {
415 : static boost::hash<string> string_hash;
416 :
417 384 : if (name == BgpConfigManager::kMasterInstance) {
418 : const BgpInstanceConfig *config =
419 96 : server()->config_manager()->FindInstance(name);
420 96 : assert(config);
421 96 : LocateRoutingInstance(config);
422 : } else {
423 288 : size_t idx = string_hash(name) % instance_config_lists_.size();
424 288 : instance_config_lists_[idx].insert(name);
425 288 : instance_config_triggers_[idx]->Set();
426 : }
427 384 : }
428 :
429 : // Update VirtualNetwork to RoutingInstance name mapping.
430 128 : bool RoutingInstanceMgr::CreateVirtualNetworkMapping(
431 : const string &virtual_network, const string &instance_name) {
432 128 : std::scoped_lock lock(mutex_);
433 :
434 128 : VirtualNetworksMap::iterator iter;
435 : bool inserted;
436 256 : tie(iter, inserted) = virtual_networks_.insert(make_pair(virtual_network,
437 384 : set<string>()));
438 128 : assert(iter->second.insert(instance_name).second);
439 128 : return true;
440 128 : }
441 :
442 128 : bool RoutingInstanceMgr::DeleteVirtualNetworkMapping(
443 : const string &virtual_network, const string &instance_name) {
444 128 : std::scoped_lock lock(mutex_);
445 :
446 128 : VirtualNetworksMap::iterator iter = virtual_networks_.find(virtual_network);
447 128 : assert(iter != virtual_networks_.end());
448 :
449 : // Delete this instance from the set of virtual-network to instances map.
450 128 : assert(iter->second.erase(instance_name) == 1);
451 :
452 256 : RoutingInstanceStatsData instance_info;
453 128 : bool mapping_deleted = iter->second.empty();
454 :
455 : // Delete the mapping if the member set is empty.
456 128 : if (mapping_deleted) {
457 96 : virtual_networks_.erase(iter);
458 :
459 : // Delete the virtual-network specific UVE.
460 96 : instance_info.set_deleted(true);
461 : } else {
462 :
463 : // Delete this instance's uve, by deleting all table stats.
464 32 : map<string, RoutingTableStats> stats_map;
465 32 : stats_map.insert(make_pair(instance_name, RoutingTableStats()));
466 32 : stats_map[instance_name].set_deleted(true);
467 :
468 : // Delete all uve stats across all address families.
469 352 : for (Address::Family i = Address::UNSPEC; i < Address::NUM_FAMILIES;
470 320 : i = static_cast<Address::Family>(i + 1)) {
471 320 : SetTableStatsUve(i, stats_map, &instance_info);
472 : }
473 32 : }
474 :
475 : // Send delete uve.
476 128 : instance_info.set_name(virtual_network);
477 128 : assert(!instance_info.get_name().empty());
478 128 : BGP_UVE_SEND(RoutingInstanceStats, instance_info);
479 :
480 128 : return mapping_deleted;
481 128 : }
482 :
483 320 : 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 320 : switch (family) {
489 32 : case Address::UNSPEC:
490 32 : break;
491 64 : case Address::INET:
492 : case Address::INETMPLS:
493 64 : instance_info->set_raw_ipv4_stats(stats_map);
494 64 : break;
495 32 : case Address::INET6:
496 32 : instance_info->set_raw_ipv6_stats(stats_map);
497 32 : break;
498 32 : case Address::INETVPN:
499 32 : instance_info->set_raw_inetvpn_stats(stats_map);
500 32 : break;
501 32 : case Address::INET6VPN:
502 32 : instance_info->set_raw_inet6vpn_stats(stats_map);
503 32 : break;
504 32 : case Address::RTARGET:
505 32 : instance_info->set_raw_rtarget_stats(stats_map);
506 32 : break;
507 32 : case Address::EVPN:
508 32 : instance_info->set_raw_evpn_stats(stats_map);
509 32 : break;
510 32 : case Address::ERMVPN:
511 32 : instance_info->set_raw_ermvpn_stats(stats_map);
512 32 : break;
513 32 : case Address::MVPN:
514 32 : instance_info->set_raw_mvpn_stats(stats_map);
515 32 : break;
516 0 : case Address::NUM_FAMILIES:
517 0 : break;
518 : }
519 320 : }
520 :
521 0 : uint32_t RoutingInstanceMgr::SendTableStatsUve() {
522 0 : uint32_t out_q_depth = 0;
523 :
524 0 : for (RoutingInstanceIterator rit = begin(); rit != end(); ++rit) {
525 0 : RoutingInstanceStatsData instance_info;
526 0 : map<string, RoutingTableStats> stats_map;
527 :
528 0 : stats_map.insert(make_pair(rit->second->name(), RoutingTableStats()));
529 : RoutingInstance::RouteTableList const rt_list =
530 0 : rit->second->GetTables();
531 :
532 : // Prepare and send Statistics UVE for each routing-instance.
533 0 : for (RoutingInstance::RouteTableList::const_iterator it =
534 0 : rt_list.begin(); it != rt_list.end(); ++it) {
535 0 : BgpTable *table = it->second;
536 :
537 : size_t markers;
538 0 : out_q_depth += table->GetPendingRiboutsCount(&markers);
539 :
540 0 : stats_map[rit->second->name()].set_prefixes(table->Size());
541 0 : stats_map[rit->second->name()].set_primary_paths(
542 : table->GetPrimaryPathCount());
543 0 : stats_map[rit->second->name()].set_secondary_paths(
544 : table->GetSecondaryPathCount());
545 0 : stats_map[rit->second->name()].set_infeasible_paths(
546 : table->GetInfeasiblePathCount());
547 :
548 0 : uint64_t total_paths = table->GetPrimaryPathCount() +
549 0 : table->GetSecondaryPathCount() +
550 0 : table->GetInfeasiblePathCount();
551 0 : stats_map[rit->second->name()].set_total_paths(total_paths);
552 0 : SetTableStatsUve(table->family(), stats_map, &instance_info);
553 : }
554 :
555 : // Set the primary key and trigger uve send.
556 0 : instance_info.set_name(rit->second->GetVirtualNetworkName());
557 0 : assert(!instance_info.get_name().empty());
558 0 : BGP_UVE_SEND(RoutingInstanceStats, instance_info);
559 0 : }
560 :
561 0 : return out_q_depth;
562 : }
563 :
564 128 : RoutingInstance *RoutingInstanceMgr::CreateRoutingInstance(
565 : const BgpInstanceConfig *config) {
566 128 : RoutingInstance *rtinstance = BgpStaticObjectFactory::Create<RoutingInstance>(
567 128 : config->name(), server_, this, config);
568 128 : uint32_t ri_index = config->index();
569 128 : if (config->name() == BgpConfigManager::kMasterInstance) {
570 32 : default_rtinstance_ = rtinstance;
571 32 : ri_index = 0;
572 : }
573 :
574 128 : rtinstance->ProcessConfig();
575 128 : InsertRoutingInstance(rtinstance);
576 128 : rtinstance->set_index(ri_index);
577 :
578 128 : InstanceTargetAdd(rtinstance);
579 128 : InstanceVnIndexAdd(rtinstance);
580 128 : rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
581 :
582 : // Notify clients about routing instance create
583 128 : NotifyInstanceOp(config->name(), INSTANCE_ADD);
584 :
585 128 : vector<string> import_rt(config->import_list().begin(),
586 256 : config->import_list().end());
587 128 : vector<string> export_rt(config->export_list().begin(),
588 256 : config->export_list().end());
589 128 : 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 128 : CreateRoutingInstanceNeighbors(config);
595 :
596 : // Update instance to virtual-network mapping structures.
597 128 : CreateVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
598 : rtinstance->name());
599 :
600 : // Create MvpnManager for all children mvpn networks.
601 : MvpnTable *mvpn_table =
602 128 : dynamic_cast<MvpnTable *>(rtinstance->GetTable(Address::MVPN));
603 128 : mvpn_table->CreateMvpnManagers();
604 128 : return rtinstance;
605 128 : }
606 :
607 64 : void RoutingInstanceMgr::UpdateRoutingInstance(RoutingInstance *rtinstance,
608 : const BgpInstanceConfig *config) {
609 64 : bool old_always_subscribe = rtinstance->always_subscribe();
610 :
611 : // Note that InstanceTarget[Remove|Add] depend on the RouteTargetList in
612 : // the RoutingInstance.
613 64 : InstanceTargetRemove(rtinstance);
614 64 : InstanceVnIndexRemove(rtinstance);
615 64 : rtinstance->UpdateConfig(config);
616 64 : InstanceTargetAdd(rtinstance);
617 64 : InstanceVnIndexAdd(rtinstance);
618 :
619 64 : if (old_always_subscribe != rtinstance->always_subscribe()) {
620 0 : rtinstance->FlushAllRTargetRoutes(server_->local_autonomous_system());
621 0 : rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
622 : }
623 :
624 : // Notify clients about routing instance create
625 64 : NotifyInstanceOp(config->name(), INSTANCE_UPDATE);
626 :
627 64 : vector<string> import_rt(config->import_list().begin(),
628 128 : config->import_list().end());
629 64 : vector<string> export_rt(config->export_list().begin(),
630 128 : config->export_list().end());
631 64 : RTINSTANCE_LOG(Update, rtinstance,
632 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL, import_rt, export_rt,
633 : rtinstance->virtual_network_index());
634 64 : }
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 0 : void RoutingInstanceMgr::DeleteRoutingInstance(const string &name) {
645 0 : CHECK_CONCURRENCY("bgp::Config");
646 :
647 0 : RoutingInstance *rtinstance = GetRoutingInstance(name);
648 :
649 : // Ignore if instance is not found as it might already have been deleted.
650 0 : if (rtinstance && rtinstance->deleted()) {
651 0 : RTINSTANCE_LOG_WARNING_MESSAGE(server_, RTINSTANCE_LOG_FLAG_ALL,
652 : rtinstance->GetVirtualNetworkName(), name,
653 : "Duplicate instance delete while pending deletion");
654 0 : return;
655 0 : } else if (!rtinstance) {
656 0 : RTINSTANCE_LOG_WARNING_MESSAGE(server_, RTINSTANCE_LOG_FLAG_ALL,
657 : name, name, "Instance not found during delete");
658 0 : return;
659 : }
660 :
661 0 : InstanceVnIndexRemove(rtinstance);
662 0 : InstanceTargetRemove(rtinstance);
663 0 : rtinstance->ClearConfig();
664 :
665 0 : RTINSTANCE_LOG(Delete, rtinstance,
666 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
667 :
668 0 : rtinstance->ProcessServiceChainConfig();
669 0 : rtinstance->FlushStaticRouteConfig();
670 0 : rtinstance->FlushRouteAggregationConfig();
671 :
672 0 : NotifyInstanceOp(name, INSTANCE_DELETE);
673 0 : 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 128 : void RoutingInstanceMgr::DestroyRoutingInstance(RoutingInstance *rtinstance) {
682 128 : CHECK_CONCURRENCY("bgp::Config");
683 :
684 128 : RTINSTANCE_LOG(Destroy, rtinstance,
685 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
686 :
687 128 : DeleteVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
688 : rtinstance->name());
689 :
690 : // instance should also be deleted here
691 128 : const string name = rtinstance->name();
692 128 : RoutingInstanceList::iterator loc = instances_.find(rtinstance->name());
693 128 : assert(loc != instances_.end());
694 128 : instances_.erase(loc);
695 128 : int index = rtinstance->index();
696 128 : delete rtinstance;
697 : // disable the TraceBuf for the deleted RoutingInstance
698 128 : DisableTraceBuffer(name);
699 : // index was allocated in Config Manager so needs to be freed
700 128 : if (index >= 0)
701 128 : server()->config_manager()->ResetRoutingInstanceIndexBit(index);
702 :
703 128 : if (deleted())
704 128 : return;
705 :
706 0 : if (rtinstance == default_rtinstance_) {
707 0 : default_rtinstance_ = NULL;
708 0 : return;
709 : }
710 :
711 : const BgpInstanceConfig *config
712 0 : = server()->config_manager()->FindInstance(name);
713 0 : if (config) {
714 0 : CreateRoutingInstance(config);
715 0 : return;
716 : }
717 128 : }
718 :
719 0 : SandeshTraceBufferPtr RoutingInstanceMgr::LocateTraceBuffer(
720 : const std::string &name) {
721 0 : SandeshTraceBufferPtr trace_buf;
722 :
723 0 : trace_buf = GetActiveTraceBuffer(name);
724 0 : if (trace_buf == NULL) {
725 0 : trace_buf = GetTraceBuffer(name);
726 : }
727 :
728 0 : return trace_buf;
729 0 : }
730 :
731 0 : SandeshTraceBufferPtr RoutingInstanceMgr::GetTraceBuffer(
732 : const std::string &name) {
733 0 : tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
734 0 : SandeshTraceBufferPtr trace_buf;
735 0 : RoutingInstanceTraceBufferMap::iterator iter;
736 :
737 0 : iter = trace_buffer_active_.find(name);
738 0 : if (iter != trace_buffer_active_.end()) {
739 0 : return iter->second;
740 : }
741 :
742 0 : iter = trace_buffer_dormant_.find(name);
743 0 : if (iter != trace_buffer_dormant_.end()) {
744 : // tracebuf was created for this RoutingInstance in its prior
745 : // incarnation
746 0 : trace_buf = iter->second;
747 0 : trace_buffer_dormant_.erase(iter);
748 0 : trace_buffer_dormant_list_.remove(name);
749 0 : trace_buffer_active_.insert(make_pair(name, trace_buf));
750 0 : return trace_buf;
751 : }
752 :
753 : // create new sandesh Buffer
754 0 : trace_buf = SandeshTraceBufferCreate(
755 0 : name + RTINSTANCE_TRACE_BUF, 1000);
756 0 : trace_buffer_active_.insert(make_pair(name, trace_buf));
757 :
758 0 : return trace_buf;
759 0 : }
760 :
761 128 : void RoutingInstanceMgr::DisableTraceBuffer(const std::string &name) {
762 128 : tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
763 128 : SandeshTraceBufferPtr trace_buf;
764 128 : SandeshTraceBufferPtr trace_buf_delete;
765 128 : RoutingInstanceTraceBufferMap::iterator iter;
766 128 : std::pair<RoutingInstanceTraceBufferMap::iterator, bool> ret;
767 128 : std::string ri_name;
768 :
769 : // Moving the trace buff from Active map to Dormant map
770 128 : iter = trace_buffer_active_.find(name);
771 128 : if (iter != trace_buffer_active_.end()) {
772 0 : trace_buf = iter->second;
773 0 : trace_buffer_active_.erase(iter);
774 0 : if (dormant_trace_buf_size_) {
775 : // Move to Dormant map.
776 0 : 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 0 : size_t del_count = std::min(trace_buffer_dormant_list_.size(),
781 0 : trace_buf_threshold_);
782 0 : if (!del_count) {
783 : // retain the latest deleted RI's TraceBuf
784 0 : del_count = 1;
785 : }
786 0 : for (size_t i = 0; i < del_count; i++) {
787 0 : iter = trace_buffer_dormant_.find(
788 0 : trace_buffer_dormant_list_.front());
789 0 : assert(iter != trace_buffer_dormant_.end());
790 0 : trace_buf_delete = iter->second;
791 0 : trace_buffer_dormant_.erase(iter);
792 0 : trace_buffer_dormant_list_.pop_front();
793 0 : trace_buf_delete.reset();
794 : }
795 : }
796 0 : ret = trace_buffer_dormant_.insert(make_pair(name, trace_buf));
797 0 : assert(ret.second == true);
798 0 : trace_buffer_dormant_list_.push_back(name);
799 : }
800 : }
801 :
802 256 : return;
803 128 : }
804 :
805 : SandeshTraceBufferPtr
806 0 : RoutingInstanceMgr::GetActiveTraceBuffer(const std::string &name) const {
807 0 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
808 : RoutingInstanceTraceBufferMap::const_iterator iter =
809 0 : trace_buffer_active_.find(name);
810 :
811 0 : if (iter != trace_buffer_active_.end()) {
812 0 : return iter->second;
813 : } else {
814 0 : return SandeshTraceBufferPtr();
815 : }
816 0 : }
817 :
818 : SandeshTraceBufferPtr
819 0 : RoutingInstanceMgr::GetDormantTraceBuffer(const std::string &name) const {
820 0 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
821 : RoutingInstanceTraceBufferMap::const_iterator iter =
822 0 : trace_buffer_dormant_.find(name);
823 :
824 0 : if (iter != trace_buffer_dormant_.end()) {
825 0 : return iter->second;
826 : } else {
827 0 : return SandeshTraceBufferPtr();
828 : }
829 0 : }
830 :
831 0 : bool RoutingInstanceMgr::HasRoutingInstanceActiveTraceBuf(const std::string
832 : &name) const {
833 0 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
834 : RoutingInstanceTraceBufferMap::const_iterator iter =
835 0 : trace_buffer_active_.find(name);
836 :
837 0 : return (iter != trace_buffer_active_.end());
838 0 : }
839 :
840 0 : bool RoutingInstanceMgr::HasRoutingInstanceDormantTraceBuf(const std::string
841 : &name) const {
842 0 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
843 : RoutingInstanceTraceBufferMap::const_iterator iter =
844 0 : trace_buffer_dormant_.find(name);
845 0 : return (iter != trace_buffer_dormant_.end());
846 0 : }
847 :
848 : size_t
849 32 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferCapacity() const {
850 32 : 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 32 : if (buffer_capacity_str) {
854 0 : size_t env_buffer_capacity = strtoul(buffer_capacity_str, NULL, 0);
855 0 : return env_buffer_capacity;
856 : }
857 32 : return 0;
858 : }
859 :
860 : size_t
861 32 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferThreshold() const {
862 32 : char *buffer_threshold_str = getenv(
863 : "CONTRAIL_ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD");
864 32 : if (buffer_threshold_str) {
865 0 : size_t env_buffer_threshold = strtoul(buffer_threshold_str, NULL, 0);
866 0 : return env_buffer_threshold;
867 : }
868 32 : return ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD_1K;
869 : }
870 :
871 0 : size_t RoutingInstanceMgr::GetRoutingInstanceActiveTraceBufSize() const {
872 0 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
873 0 : return trace_buffer_active_.size();
874 0 : }
875 :
876 0 : size_t RoutingInstanceMgr::GetRoutingInstanceDormantTraceBufSize() const {
877 0 : tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
878 0 : return trace_buffer_dormant_.size();
879 0 : }
880 :
881 128 : void RoutingInstanceMgr::CreateRoutingInstanceNeighbors(
882 : const BgpInstanceConfig *config) {
883 128 : if (config->neighbor_list().empty())
884 128 : return;
885 0 : std::scoped_lock lock(mutex_);
886 0 : neighbor_config_list_.insert(config->name());
887 0 : neighbor_config_trigger_->Set();
888 0 : }
889 :
890 0 : bool RoutingInstanceMgr::ProcessNeighborConfigList() {
891 0 : if (deleted()) {
892 0 : deleter()->RetryDelete();
893 : } else {
894 0 : BOOST_FOREACH(const string &name, neighbor_config_list_) {
895 0 : RoutingInstance *rtinstance = GetRoutingInstance(name);
896 0 : if (!rtinstance || rtinstance->deleted())
897 0 : continue;
898 0 : rtinstance->CreateNeighbors();
899 : }
900 : }
901 :
902 0 : neighbor_config_list_.clear();
903 0 : return true;
904 : }
905 :
906 32 : void RoutingInstanceMgr::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) {
907 32 : if (server_->local_autonomous_system() == old_local_asn)
908 0 : return;
909 64 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
910 32 : it->second->FlushAllRTargetRoutes(old_local_asn);
911 32 : it->second->InitAllRTargetRoutes(server_->local_autonomous_system());
912 : }
913 32 : RoutingInstance *master = GetDefaultRoutingInstance();
914 32 : const Ip4Address old_identifier(server()->bgp_identifier());
915 32 : master->DeleteMvpnRTargetRoute(old_local_asn, old_identifier);
916 32 : master->AddMvpnRTargetRoute(server_->local_autonomous_system());
917 : }
918 :
919 32 : void RoutingInstanceMgr::IdentifierUpdateCallback(Ip4Address old_identifier) {
920 64 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
921 32 : it->second->ProcessIdentifierUpdate(server_->local_autonomous_system());
922 : }
923 32 : RoutingInstance *master = GetDefaultRoutingInstance();
924 32 : master->DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
925 : old_identifier);
926 32 : master->AddMvpnRTargetRoute(server_->local_autonomous_system());
927 32 : }
928 :
929 : //
930 : // Disable processing of all instance config lists.
931 : // For testing only.
932 : //
933 0 : void RoutingInstanceMgr::DisableInstanceConfigListProcessing() {
934 0 : for (size_t idx = 0; idx < instance_config_triggers_.size(); ++idx) {
935 0 : instance_config_triggers_[idx]->set_disable();
936 : }
937 0 : }
938 :
939 : //
940 : // Enable processing of all instance config lists.
941 : // For testing only.
942 : //
943 0 : void RoutingInstanceMgr::EnableInstanceConfigListProcessing() {
944 0 : for (size_t idx = 0; idx < instance_config_triggers_.size(); ++idx) {
945 0 : instance_config_triggers_[idx]->set_enable();
946 : }
947 0 : }
948 :
949 : //
950 : // Disable processing of neighbor config list.
951 : // For testing only.
952 : //
953 0 : void RoutingInstanceMgr::DisableNeighborConfigListProcessing() {
954 0 : neighbor_config_trigger_->set_disable();
955 0 : }
956 :
957 : //
958 : // Enable processing of neighbor config list.
959 : // For testing only.
960 : //
961 0 : void RoutingInstanceMgr::EnableNeighborConfigListProcessing() {
962 0 : neighbor_config_trigger_->set_enable();
963 0 : }
964 :
965 : class RoutingInstance::DeleteActor : public LifetimeActor {
966 : public:
967 128 : DeleteActor(BgpServer *server, RoutingInstance *parent)
968 128 : : LifetimeActor(server ? server->lifetime_manager() : NULL),
969 256 : parent_(parent) {
970 128 : }
971 128 : virtual bool MayDelete() const {
972 128 : return parent_->MayDelete();
973 : }
974 128 : virtual void Shutdown() {
975 128 : parent_->mgr_->increment_deleted_count();
976 128 : parent_->mgr_->NotifyInstanceOp(parent_->name(),
977 : RoutingInstanceMgr::INSTANCE_DELETE);
978 128 : parent_->Shutdown();
979 128 : }
980 128 : virtual void Destroy() {
981 128 : parent_->mgr_->decrement_deleted_count();
982 128 : parent_->mgr_->DestroyRoutingInstance(parent_);
983 128 : }
984 :
985 : private:
986 : RoutingInstance *parent_;
987 : };
988 :
989 128 : RoutingInstance::RoutingInstance(string name, BgpServer *server,
990 : RoutingInstanceMgr *mgr,
991 128 : const BgpInstanceConfig *config)
992 384 : : name_(name), index_(-1), server_(server), mgr_(mgr), config_(config),
993 256 : is_master_(false), always_subscribe_(false), virtual_network_index_(0),
994 128 : virtual_network_allow_transit_(false),
995 128 : virtual_network_pbb_evpn_enable_(false),
996 128 : vxlan_id_(0),
997 128 : deleter_(new DeleteActor(server, this)),
998 128 : manager_delete_ref_(this, NULL),
999 256 : mvpn_project_manager_network_(BgpConfigManager::kFabricInstance) {
1000 128 : if (mgr) {
1001 128 : std::scoped_lock lock(mgr->mutex());
1002 128 : manager_delete_ref_.Reset(mgr->deleter());
1003 128 : }
1004 128 : }
1005 :
1006 256 : RoutingInstance::~RoutingInstance() {
1007 256 : }
1008 :
1009 0 : void RoutingInstance::CreateNeighbors() {
1010 0 : CHECK_CONCURRENCY("bgp::Config");
1011 :
1012 0 : if (config_->neighbor_list().empty())
1013 0 : return;
1014 0 : PeerManager *peer_manager = LocatePeerManager();
1015 0 : BOOST_FOREACH(const string &name, config_->neighbor_list()) {
1016 0 : if (peer_manager->PeerLookup(name))
1017 0 : continue;
1018 0 : peer_manager->PeerResurrect(name);
1019 : }
1020 : }
1021 :
1022 128 : void RoutingInstance::ProcessRoutingPolicyConfig() {
1023 128 : RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1024 128 : BOOST_FOREACH(RoutingPolicyAttachInfo info,
1025 : config_->routing_policy_list()) {
1026 : RoutingPolicy *policy =
1027 0 : policy_mgr->GetRoutingPolicy(info.routing_policy_);
1028 0 : if (policy) {
1029 0 : routing_policies_.push_back(make_pair(policy,
1030 0 : policy->generation()));
1031 : }
1032 0 : }
1033 128 : }
1034 :
1035 0 : SandeshTraceBufferPtr RoutingInstance::trace_buffer() const {
1036 0 : 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 0 : void RoutingInstance::UpdateRoutingPolicyConfig() {
1049 0 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1050 0 : RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1051 0 : if (policy_mgr->UpdateRoutingPolicyList(config_->routing_policy_list(),
1052 : routing_policies())) {
1053 : // Let RoutingPolicyMgr handle update of routing policy on the instance
1054 0 : policy_mgr->ApplyRoutingPolicy(this);
1055 : }
1056 0 : }
1057 :
1058 256 : void RoutingInstance::ProcessServiceChainConfig() {
1059 256 : if (is_master_)
1060 64 : 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 192 : (SCAddress::INET) (SCAddress::INET6)
1075 192 : (SCAddress::EVPN) (SCAddress::EVPN6);
1076 :
1077 1726 : BOOST_FOREACH(SCAddress::Family family, families) {
1078 : const ServiceChainConfig *sc_config =
1079 767 : config_ ? config_->service_chain_info(family) : NULL;
1080 766 : IServiceChainMgr *manager = server_->service_chain_mgr(family);
1081 766 : if (sc_config && !sc_config->routing_instance.empty()) {
1082 0 : manager->LocateServiceChain(this, *sc_config);
1083 : } else {
1084 766 : manager->StopServiceChain(this);
1085 : }
1086 : }
1087 192 : }
1088 :
1089 128 : void RoutingInstance::ProcessStaticRouteConfig() {
1090 128 : if (is_master_)
1091 32 : return;
1092 :
1093 96 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1094 480 : BOOST_FOREACH(Address::Family family, families) {
1095 192 : IStaticRouteMgr *manager = static_route_mgr(family);
1096 192 : if (!manager && !config_->static_routes(family).empty())
1097 0 : manager = LocateStaticRouteMgr(family);
1098 192 : if (manager)
1099 0 : manager->ProcessStaticRouteConfig();
1100 : }
1101 96 : }
1102 :
1103 0 : void RoutingInstance::UpdateStaticRouteConfig() {
1104 0 : if (is_master_)
1105 0 : return;
1106 :
1107 0 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1108 0 : BOOST_FOREACH(Address::Family family, families) {
1109 0 : IStaticRouteMgr *manager = static_route_mgr(family);
1110 0 : if (!manager && !config_->static_routes(family).empty())
1111 0 : manager = LocateStaticRouteMgr(family);
1112 0 : if (manager)
1113 0 : manager->UpdateStaticRouteConfig();
1114 : }
1115 0 : }
1116 :
1117 128 : void RoutingInstance::FlushStaticRouteConfig() {
1118 128 : if (is_master_)
1119 32 : return;
1120 :
1121 96 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1122 480 : BOOST_FOREACH(Address::Family family, families) {
1123 192 : IStaticRouteMgr *manager = static_route_mgr(family);
1124 192 : if (manager)
1125 0 : manager->FlushStaticRouteConfig();
1126 : }
1127 96 : }
1128 :
1129 0 : void RoutingInstance::UpdateAllStaticRoutes() {
1130 0 : if (is_master_)
1131 0 : return;
1132 :
1133 0 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1134 0 : BOOST_FOREACH(Address::Family family, families) {
1135 0 : IStaticRouteMgr *manager = static_route_mgr(family);
1136 0 : if (manager)
1137 0 : manager->UpdateAllRoutes();
1138 : }
1139 0 : }
1140 :
1141 128 : void RoutingInstance::ProcessRouteAggregationConfig() {
1142 128 : if (is_master_)
1143 32 : return;
1144 :
1145 96 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1146 480 : BOOST_FOREACH(Address::Family family, families) {
1147 192 : IRouteAggregator *aggregator = route_aggregator(family);
1148 192 : if (!aggregator && !config_->aggregate_routes(family).empty())
1149 0 : aggregator = LocateRouteAggregator(family);
1150 192 : if (aggregator)
1151 0 : aggregator->ProcessAggregateRouteConfig();
1152 : }
1153 96 : }
1154 :
1155 0 : void RoutingInstance::UpdateRouteAggregationConfig() {
1156 0 : if (is_master_)
1157 0 : return;
1158 :
1159 0 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1160 0 : BOOST_FOREACH(Address::Family family, families) {
1161 0 : IRouteAggregator *aggregator = route_aggregator(family);
1162 0 : if (!aggregator && !config_->aggregate_routes(family).empty())
1163 0 : aggregator = LocateRouteAggregator(family);
1164 0 : if (aggregator)
1165 0 : aggregator->UpdateAggregateRouteConfig();
1166 : }
1167 0 : }
1168 :
1169 128 : void RoutingInstance::FlushRouteAggregationConfig() {
1170 128 : if (is_master_)
1171 32 : return;
1172 :
1173 96 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1174 480 : BOOST_FOREACH(Address::Family family, families) {
1175 192 : IRouteAggregator *aggregator = route_aggregator(family);
1176 192 : if (aggregator)
1177 0 : aggregator->FlushAggregateRouteConfig();
1178 : }
1179 96 : }
1180 :
1181 96 : void RoutingInstance::DeleteMvpnRTargetRoute(as_t asn, Ip4Address old_ip) {
1182 96 : if (asn == 0)
1183 64 : return;
1184 64 : string id_str = "target:" + old_ip.to_string() + ":0";
1185 32 : RouteTarget rtarget = RouteTarget::FromString(id_str);
1186 32 : DeleteRTargetRoute(asn, rtarget);
1187 32 : }
1188 :
1189 64 : void RoutingInstance::AddMvpnRTargetRoute(as_t asn) {
1190 64 : if (asn == 0)
1191 32 : return;
1192 32 : const Ip4Address server_ip(server()->bgp_identifier());
1193 64 : string id_str = "target:" + server_ip.to_string() + ":0";
1194 32 : RouteTarget rtarget = RouteTarget::FromString(id_str);
1195 32 : AddRTargetRoute(asn, rtarget);
1196 32 : }
1197 :
1198 128 : void RoutingInstance::ProcessConfig() {
1199 128 : RoutingInstanceInfo info = GetDataCollection("");
1200 :
1201 : // Initialize virtual network info.
1202 128 : virtual_network_ = config_->virtual_network();
1203 128 : virtual_network_index_ = config_->virtual_network_index();
1204 128 : virtual_network_allow_transit_ = config_->virtual_network_allow_transit();
1205 128 : virtual_network_pbb_evpn_enable_ =
1206 128 : config_->virtual_network_pbb_evpn_enable();
1207 128 : vxlan_id_ = config_->vxlan_id();
1208 128 : routing_instance_vxlan_ = config_->routing_instance_vxlan();
1209 :
1210 : // Always subscribe (using RTF) for RTs of PNF service chain instances.
1211 128 : always_subscribe_ = config_->has_pnf();
1212 :
1213 128 : vector<string> import_rt, export_rt;
1214 700 : BOOST_FOREACH(string irt, config_->import_list()) {
1215 284 : error_code error;
1216 284 : RouteTarget rt = RouteTarget::FromString(irt, &error);
1217 287 : if (!error) {
1218 287 : import_.insert(rt);
1219 287 : import_rt.push_back(irt);
1220 : }
1221 286 : }
1222 317 : BOOST_FOREACH(string ert, config_->export_list()) {
1223 95 : error_code error;
1224 95 : RouteTarget rt = RouteTarget::FromString(ert, &error);
1225 95 : if (!error) {
1226 95 : export_.insert(rt);
1227 96 : export_rt.push_back(ert);
1228 : }
1229 95 : }
1230 127 : RTINSTANCE_LOG(Update, this,
1231 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL,
1232 : import_rt, export_rt, this->virtual_network_index());
1233 :
1234 127 : if (import_rt.size())
1235 95 : info.set_add_import_rt(import_rt);
1236 127 : if (export_rt.size())
1237 95 : info.set_add_export_rt(export_rt);
1238 128 : if (import_rt.size() || export_rt.size())
1239 96 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1240 :
1241 : // Create BGP Table
1242 128 : if (name_ == BgpConfigManager::kMasterInstance) {
1243 32 : assert(mgr_->count() == 0);
1244 32 : is_master_ = true;
1245 :
1246 32 : LocatePeerManager();
1247 32 : VpnTableCreate(Address::INETVPN);
1248 32 : VpnTableCreate(Address::INET6VPN);
1249 32 : VpnTableCreate(Address::ERMVPN);
1250 32 : VpnTableCreate(Address::MVPN);
1251 32 : VpnTableCreate(Address::EVPN);
1252 32 : RTargetTableCreate();
1253 :
1254 : BgpTable *table_inet = static_cast<BgpTable *>(
1255 32 : server_->database()->CreateTable("inet.0"));
1256 32 : assert(table_inet);
1257 32 : AddTable(table_inet);
1258 :
1259 : BgpTable *table_inetmpls = static_cast<BgpTable *>(
1260 32 : server_->database()->CreateTable("inet.3"));
1261 32 : assert(table_inetmpls);
1262 32 : AddTable(table_inetmpls);
1263 :
1264 : BgpTable *table_inet6 = static_cast<BgpTable *>(
1265 32 : server_->database()->CreateTable("inet6.0"));
1266 32 : assert(table_inet6);
1267 32 : 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 96 : BgpTable *inet_table = VrfTableCreate(Address::INET, Address::INETVPN);
1273 96 : inet_table->LocatePathResolver();
1274 :
1275 : BgpTable *inet6_table =
1276 96 : VrfTableCreate(Address::INET6, Address::INET6VPN);
1277 96 : inet6_table->LocatePathResolver();
1278 :
1279 96 : VrfTableCreate(Address::ERMVPN, Address::ERMVPN);
1280 :
1281 96 : BgpTable *evpn_table = VrfTableCreate(Address::EVPN, Address::EVPN);
1282 96 : evpn_table->LocatePathResolver();
1283 :
1284 96 : BgpTable *table = VrfTableCreate(Address::MVPN, Address::MVPN);
1285 :
1286 : // Create path-resolver in mvpn table.
1287 96 : table->LocatePathResolver();
1288 : }
1289 :
1290 128 : ProcessServiceChainConfig();
1291 128 : ProcessStaticRouteConfig();
1292 128 : ProcessRouteAggregationConfig();
1293 128 : ProcessRoutingPolicyConfig();
1294 128 : }
1295 :
1296 64 : void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) {
1297 64 : 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 64 : config_ = cfg;
1302 :
1303 : // Always subscribe (using RTF) for RTs of PNF service chain instances.
1304 64 : 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 64 : bool notify_routes = false;
1309 64 : if (virtual_network_allow_transit_ != cfg->virtual_network_allow_transit())
1310 0 : notify_routes = true;
1311 64 : if (virtual_network_pbb_evpn_enable_ !=
1312 64 : cfg->virtual_network_pbb_evpn_enable())
1313 0 : notify_routes = true;
1314 64 : if (virtual_network_ != cfg->virtual_network())
1315 0 : notify_routes = true;
1316 64 : if (virtual_network_index_ != cfg->virtual_network_index())
1317 0 : notify_routes = true;
1318 :
1319 : // Trigger notification of all routes in each table.
1320 64 : if (notify_routes) {
1321 0 : BOOST_FOREACH(RouteTableList::value_type &entry, vrf_tables_by_name_) {
1322 0 : BgpTable *table = entry.second;
1323 0 : table->NotifyAllEntries();
1324 : }
1325 : }
1326 :
1327 : // Update all static routes so that they reflect the new OriginVn.
1328 64 : if (virtual_network_index_ != cfg->virtual_network_index())
1329 0 : UpdateAllStaticRoutes();
1330 :
1331 64 : string prev_vn_name = GetVirtualNetworkName();
1332 :
1333 : // Update virtual network info.
1334 64 : virtual_network_ = cfg->virtual_network();
1335 :
1336 : // Recreate instance stats' UVE, if its key: virtual_network is modified.
1337 64 : if (prev_vn_name != GetVirtualNetworkName()) {
1338 0 : mgr_->DeleteVirtualNetworkMapping(prev_vn_name, name_);
1339 0 : mgr_->CreateVirtualNetworkMapping(GetVirtualNetworkName(), name_);
1340 : }
1341 :
1342 64 : virtual_network_index_ = cfg->virtual_network_index();
1343 64 : virtual_network_allow_transit_ = cfg->virtual_network_allow_transit();
1344 64 : virtual_network_pbb_evpn_enable_ = cfg->virtual_network_pbb_evpn_enable();
1345 64 : vxlan_id_ = cfg->vxlan_id();
1346 64 : 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 64 : if (IsMasterRoutingInstance())
1351 64 : return;
1352 :
1353 0 : RouteTargetList future_import;
1354 0 : vector<string> add_import_rt, remove_import_rt;
1355 0 : BOOST_FOREACH(const string &rtarget_str, cfg->import_list()) {
1356 0 : error_code error;
1357 0 : RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
1358 0 : if (!error)
1359 0 : future_import.insert(rt);
1360 : }
1361 0 : 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 0 : RouteTargetList future_export;
1368 0 : vector<string> add_export_rt, remove_export_rt;
1369 0 : BOOST_FOREACH(const string &rtarget_str, cfg->export_list()) {
1370 0 : error_code error;
1371 0 : RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
1372 0 : if (!error)
1373 0 : future_export.insert(rt);
1374 : }
1375 0 : 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 0 : RoutingInstanceInfo info = GetDataCollection("");
1382 0 : if (add_import_rt.size())
1383 0 : info.set_add_import_rt(add_import_rt);
1384 0 : if (remove_import_rt.size())
1385 0 : info.set_remove_import_rt(remove_import_rt);
1386 0 : if (add_export_rt.size())
1387 0 : info.set_add_export_rt(add_export_rt);
1388 0 : if (remove_export_rt.size())
1389 0 : info.set_remove_export_rt(remove_export_rt);
1390 0 : if (add_import_rt.size() || remove_import_rt.size() ||
1391 0 : add_export_rt.size() || remove_export_rt.size())
1392 0 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1393 :
1394 0 : ProcessServiceChainConfig();
1395 0 : UpdateStaticRouteConfig();
1396 0 : UpdateRouteAggregationConfig();
1397 0 : UpdateRoutingPolicyConfig();
1398 64 : }
1399 :
1400 128 : void RoutingInstance::ClearConfig() {
1401 128 : CHECK_CONCURRENCY("bgp::Config");
1402 128 : config_ = NULL;
1403 128 : }
1404 :
1405 128 : void RoutingInstance::ManagedDelete() {
1406 : // RoutingInstanceMgr logs the delete for non-master instances.
1407 128 : if (IsMasterRoutingInstance()) {
1408 32 : RTINSTANCE_LOG(Delete, this,
1409 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1410 : }
1411 128 : deleter_->Delete();
1412 128 : }
1413 :
1414 128 : void RoutingInstance::Shutdown() {
1415 128 : CHECK_CONCURRENCY("bgp::Config");
1416 :
1417 128 : RTINSTANCE_LOG(Shutdown, this,
1418 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1419 :
1420 128 : ClearConfig();
1421 128 : FlushAllRTargetRoutes(server_->local_autonomous_system());
1422 128 : if (is_master_) {
1423 32 : const Ip4Address old_identifier(server()->bgp_identifier());
1424 32 : DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
1425 : old_identifier);
1426 : }
1427 128 : ClearRouteTarget();
1428 :
1429 128 : ProcessServiceChainConfig();
1430 128 : FlushStaticRouteConfig();
1431 128 : FlushRouteAggregationConfig();
1432 128 : }
1433 :
1434 128 : bool RoutingInstance::MayDelete() const {
1435 128 : return true;
1436 : }
1437 :
1438 879 : LifetimeActor *RoutingInstance::deleter() {
1439 879 : return deleter_.get();
1440 : }
1441 :
1442 448 : const LifetimeActor *RoutingInstance::deleter() const {
1443 448 : return deleter_.get();
1444 : }
1445 :
1446 448 : bool RoutingInstance::deleted() const {
1447 448 : return deleter()->IsDeleted();
1448 : }
1449 :
1450 2127 : const string RoutingInstance::GetVirtualNetworkName() const {
1451 2127 : if (!virtual_network_.empty())
1452 0 : return virtual_network_;
1453 2127 : size_t pos = name_.rfind(':');
1454 2127 : if (pos == string::npos) {
1455 879 : return name_;
1456 : } else {
1457 1248 : return name_.substr(0, pos);
1458 : }
1459 : }
1460 :
1461 1140 : int RoutingInstance::virtual_network_index() const {
1462 1140 : return virtual_network_index_;
1463 : }
1464 :
1465 0 : bool RoutingInstance::virtual_network_allow_transit() const {
1466 0 : return virtual_network_allow_transit_;
1467 : }
1468 :
1469 0 : bool RoutingInstance::virtual_network_pbb_evpn_enable() const {
1470 0 : return virtual_network_pbb_evpn_enable_;
1471 : }
1472 :
1473 0 : int RoutingInstance::vxlan_id() const {
1474 0 : return vxlan_id_;
1475 : }
1476 :
1477 480 : void RoutingInstance::ClearFamilyRouteTarget(Address::Family vrf_family,
1478 : Address::Family vpn_family) {
1479 480 : BgpTable *table = GetTable(vrf_family);
1480 480 : if (table) {
1481 480 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1482 3360 : BOOST_FOREACH(RouteTarget rt, import_) {
1483 1440 : replicator->Leave(table, rt, true);
1484 : }
1485 1440 : BOOST_FOREACH(RouteTarget rt, export_) {
1486 480 : replicator->Leave(table, rt, false);
1487 : }
1488 : }
1489 480 : }
1490 :
1491 32 : void RoutingInstance::AddRTargetRoute(uint32_t asn,
1492 : const RouteTarget &rtarget) {
1493 32 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1494 :
1495 32 : RTargetPrefix prefix(asn, rtarget);
1496 32 : RTargetRoute rt_key(prefix);
1497 :
1498 32 : RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
1499 32 : BgpTable *table = master->GetTable(Address::RTARGET);
1500 : DBTablePartition *tbl_partition =
1501 32 : static_cast<DBTablePartition *>(table->GetTablePartition(0));
1502 :
1503 32 : std::scoped_lock lock(mgr_->mutex());
1504 : RTargetRoute *route =
1505 32 : static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
1506 32 : if (!route) {
1507 32 : route = new RTargetRoute(prefix);
1508 32 : tbl_partition->Add(route);
1509 : } else {
1510 0 : route->ClearDelete();
1511 : }
1512 :
1513 32 : if (route->FindPath(BgpPath::Local, index_))
1514 0 : return;
1515 :
1516 32 : BgpAttrSpec attr_spec;
1517 32 : BgpAttrNextHop nexthop(server_->bgp_identifier());
1518 32 : attr_spec.push_back(&nexthop);
1519 32 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
1520 32 : attr_spec.push_back(&origin);
1521 32 : BgpAttrPtr attr = server_->attr_db()->Locate(attr_spec);
1522 :
1523 32 : BgpPath *path = new BgpPath(index_, BgpPath::Local, attr);
1524 32 : route->InsertPath(path);
1525 32 : tbl_partition->Notify(route);
1526 32 : BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
1527 : route, "Insert Local path with path id " << index_);
1528 32 : }
1529 :
1530 320 : void RoutingInstance::DeleteRTargetRoute(as_t asn,
1531 : const RouteTarget &rtarget) {
1532 320 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1533 :
1534 320 : if (asn == 0)
1535 288 : return;
1536 :
1537 320 : RTargetPrefix prefix(asn, rtarget);
1538 320 : RTargetRoute rt_key(prefix);
1539 :
1540 320 : RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
1541 320 : BgpTable *table = master->GetTable(Address::RTARGET);
1542 : DBTablePartition *tbl_partition =
1543 320 : static_cast<DBTablePartition *>(table->GetTablePartition(0));
1544 :
1545 320 : std::scoped_lock lock(mgr_->mutex());
1546 : RTargetRoute *route =
1547 320 : static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
1548 320 : if (!route || !route->RemovePath(BgpPath::Local, index_))
1549 288 : return;
1550 :
1551 32 : BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
1552 : route, "Delete Local path with path id " << index_);
1553 32 : if (!route->HasPaths()) {
1554 32 : tbl_partition->Delete(route);
1555 : } else {
1556 0 : tbl_partition->Notify(route);
1557 : }
1558 608 : }
1559 :
1560 192 : void RoutingInstance::InitAllRTargetRoutes(as_t asn) {
1561 192 : if (is_master_)
1562 96 : return;
1563 :
1564 96 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1565 672 : BOOST_FOREACH(RouteTarget rtarget, import_) {
1566 288 : if (asn != 0 && always_subscribe_)
1567 0 : AddRTargetRoute(asn, rtarget);
1568 : }
1569 : }
1570 :
1571 192 : void RoutingInstance::FlushAllRTargetRoutes(as_t asn) {
1572 192 : if (is_master_)
1573 96 : return;
1574 :
1575 96 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1576 672 : BOOST_FOREACH(RouteTarget rtarget, import_) {
1577 288 : DeleteRTargetRoute(asn, rtarget);
1578 : }
1579 : }
1580 :
1581 32 : void RoutingInstance::ProcessIdentifierUpdate(as_t asn) {
1582 32 : FlushAllRTargetRoutes(asn);
1583 32 : InitAllRTargetRoutes(asn);
1584 32 : rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index_));
1585 32 : }
1586 :
1587 0 : void RoutingInstance::AddRouteTarget(bool import,
1588 : vector<string> *change_list, RouteTargetList::const_iterator it) {
1589 0 : BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
1590 : RoutePathReplicator *ermvpn_replicator =
1591 0 : server_->replicator(Address::ERMVPN);
1592 0 : BgpTable *mvpn_table = GetTable(Address::MVPN);
1593 : RoutePathReplicator *mvpn_replicator =
1594 0 : server_->replicator(Address::MVPN);
1595 0 : BgpTable *evpn_table = GetTable(Address::EVPN);
1596 : RoutePathReplicator *evpn_replicator =
1597 0 : server_->replicator(Address::EVPN);
1598 0 : BgpTable *inet_table = GetTable(Address::INET);
1599 : RoutePathReplicator *inetvpn_replicator =
1600 0 : server_->replicator(Address::INETVPN);
1601 0 : BgpTable *inet6_table = GetTable(Address::INET6);
1602 : RoutePathReplicator *inet6vpn_replicator =
1603 0 : server_->replicator(Address::INET6VPN);
1604 :
1605 0 : change_list->push_back(it->ToString());
1606 0 : if (import) {
1607 0 : import_.insert(*it);
1608 0 : if (server_->local_autonomous_system() != 0 && always_subscribe_)
1609 0 : AddRTargetRoute(server_->local_autonomous_system(), *it);
1610 : } else {
1611 0 : export_.insert(*it);
1612 : }
1613 :
1614 0 : ermvpn_replicator->Join(ermvpn_table, *it, import);
1615 0 : mvpn_replicator->Join(mvpn_table, *it, import);
1616 0 : evpn_replicator->Join(evpn_table, *it, import);
1617 0 : inetvpn_replicator->Join(inet_table, *it, import);
1618 0 : inet6vpn_replicator->Join(inet6_table, *it, import);
1619 0 : }
1620 :
1621 0 : void RoutingInstance::DeleteRouteTarget(bool import,
1622 : vector<string> *change_list, RouteTargetList::iterator it) {
1623 0 : BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
1624 : RoutePathReplicator *ermvpn_replicator =
1625 0 : server_->replicator(Address::ERMVPN);
1626 0 : BgpTable *mvpn_table = GetTable(Address::MVPN);
1627 : RoutePathReplicator *mvpn_replicator =
1628 0 : server_->replicator(Address::MVPN);
1629 0 : BgpTable *evpn_table = GetTable(Address::EVPN);
1630 : RoutePathReplicator *evpn_replicator =
1631 0 : server_->replicator(Address::EVPN);
1632 0 : BgpTable *inet_table = GetTable(Address::INET);
1633 : RoutePathReplicator *inetvpn_replicator =
1634 0 : server_->replicator(Address::INETVPN);
1635 0 : BgpTable *inet6_table = GetTable(Address::INET6);
1636 : RoutePathReplicator *inet6vpn_replicator =
1637 0 : server_->replicator(Address::INET6VPN);
1638 :
1639 0 : ermvpn_replicator->Leave(ermvpn_table, *it, import);
1640 0 : mvpn_replicator->Leave(mvpn_table, *it, import);
1641 0 : evpn_replicator->Leave(evpn_table, *it, import);
1642 0 : inetvpn_replicator->Leave(inet_table, *it, import);
1643 0 : inet6vpn_replicator->Leave(inet6_table, *it, import);
1644 :
1645 0 : change_list->push_back(it->ToString());
1646 0 : if (import) {
1647 0 : DeleteRTargetRoute(server_->local_autonomous_system(), *it);
1648 0 : import_.erase(it);
1649 : } else {
1650 0 : export_.erase(it);
1651 : }
1652 0 : }
1653 :
1654 128 : void RoutingInstance::ClearRouteTarget() {
1655 128 : CHECK_CONCURRENCY("bgp::Config");
1656 128 : if (IsMasterRoutingInstance()) {
1657 32 : return;
1658 : }
1659 :
1660 96 : ClearFamilyRouteTarget(Address::INET, Address::INETVPN);
1661 96 : ClearFamilyRouteTarget(Address::INET6, Address::INET6VPN);
1662 96 : ClearFamilyRouteTarget(Address::ERMVPN, Address::ERMVPN);
1663 96 : ClearFamilyRouteTarget(Address::MVPN, Address::MVPN);
1664 96 : ClearFamilyRouteTarget(Address::EVPN, Address::EVPN);
1665 :
1666 96 : import_.clear();
1667 96 : export_.clear();
1668 : }
1669 :
1670 32 : BgpTable *RoutingInstance::RTargetTableCreate() {
1671 : BgpTable *rtargettbl = static_cast<BgpTable *>(
1672 32 : server_->database()->CreateTable("bgp.rtarget.0"));
1673 32 : RTINSTANCE_LOG_TABLE(Create, this, rtargettbl, SandeshLevel::SYS_DEBUG,
1674 : RTINSTANCE_LOG_FLAG_ALL);
1675 32 : AddTable(rtargettbl);
1676 32 : return rtargettbl;
1677 : }
1678 :
1679 160 : BgpTable *RoutingInstance::VpnTableCreate(Address::Family vpn_family) {
1680 160 : string table_name = GetTableName(name(), vpn_family);
1681 : BgpTable *table = static_cast<BgpTable *>(
1682 160 : server_->database()->CreateTable(table_name));
1683 160 : assert(table);
1684 :
1685 160 : AddTable(table);
1686 160 : RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
1687 : RTINSTANCE_LOG_FLAG_ALL);
1688 160 : assert(server_->rtarget_group_mgr()->empty());
1689 160 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1690 160 : replicator->Initialize();
1691 160 : return table;
1692 160 : }
1693 :
1694 480 : BgpTable *RoutingInstance::VrfTableCreate(Address::Family vrf_family,
1695 : Address::Family vpn_family) {
1696 480 : string table_name = GetTableName(name(), vrf_family);
1697 : BgpTable *table = static_cast<BgpTable *>(
1698 480 : server_->database()->CreateTable(table_name));
1699 480 : assert(table);
1700 :
1701 480 : AddTable(table);
1702 480 : RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
1703 : RTINSTANCE_LOG_FLAG_ALL);
1704 480 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1705 3356 : BOOST_FOREACH(RouteTarget rt, import_) {
1706 1436 : replicator->Join(table, rt, true);
1707 : }
1708 1440 : BOOST_FOREACH(RouteTarget rt, export_) {
1709 480 : replicator->Join(table, rt, false);
1710 : }
1711 480 : return table;
1712 480 : }
1713 :
1714 768 : void RoutingInstance::AddTable(BgpTable *tbl) {
1715 768 : vrf_tables_by_name_.insert(make_pair(tbl->name(), tbl));
1716 768 : vrf_tables_by_family_.insert(make_pair(tbl->family(), tbl));
1717 768 : tbl->set_routing_instance(this);
1718 767 : RoutingInstanceInfo info = GetDataCollection("Add");
1719 767 : info.set_family(Address::FamilyToString(tbl->family()));
1720 768 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1721 768 : }
1722 :
1723 768 : void RoutingInstance::RemoveTable(BgpTable *tbl) {
1724 768 : RoutingInstanceInfo info = GetDataCollection("Remove");
1725 768 : info.set_family(Address::FamilyToString(tbl->family()));
1726 768 : vrf_tables_by_name_.erase(tbl->name());
1727 768 : vrf_tables_by_family_.erase(tbl->family());
1728 768 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1729 768 : }
1730 :
1731 : //
1732 : // Concurrency: BGP Config task
1733 : //
1734 : // Remove the table from the map and delete the table data structure
1735 : //
1736 768 : void RoutingInstance::DestroyDBTable(DBTable *dbtable) {
1737 768 : CHECK_CONCURRENCY("bgp::Config");
1738 :
1739 768 : BgpTable *table = static_cast<BgpTable *>(dbtable);
1740 :
1741 768 : RTINSTANCE_LOG_TABLE(Destroy, this, table,
1742 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1743 :
1744 : // Remove this table from various data structures
1745 768 : server_->database()->RemoveTable(table);
1746 768 : RemoveTable(table);
1747 :
1748 : // Make sure that there are no routes left in this table
1749 768 : assert(table->Size() == 0);
1750 :
1751 768 : delete table;
1752 768 : }
1753 :
1754 640 : string RoutingInstance::GetTableName(string instance_name,
1755 : Address::Family fmly) {
1756 640 : string table_name;
1757 640 : if (instance_name == BgpConfigManager::kMasterInstance) {
1758 160 : if ((fmly == Address::INET) || (fmly == Address::INET6)) {
1759 0 : table_name = Address::FamilyToTableString(fmly) + ".0";
1760 160 : } else if (fmly == Address::INETMPLS) {
1761 0 : table_name = Address::FamilyToTableString(fmly) + ".3";
1762 : } else {
1763 160 : table_name = "bgp." + Address::FamilyToTableString(fmly) + ".0";
1764 : }
1765 : } else {
1766 : table_name =
1767 479 : instance_name + "." + Address::FamilyToTableString(fmly) + ".0";
1768 : }
1769 640 : return table_name;
1770 0 : }
1771 :
1772 1737 : BgpTable *RoutingInstance::GetTable(Address::Family fmly) {
1773 1737 : RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
1774 1737 : return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
1775 : }
1776 :
1777 96 : const BgpTable *RoutingInstance::GetTable(Address::Family fmly) const {
1778 96 : RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
1779 96 : return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
1780 : }
1781 :
1782 0 : string RoutingInstance::GetVrfFromTableName(const string table) {
1783 0 : static set<string> master_tables = list_of("inet.0")("inet.3")("inet6.0");
1784 : static set<string> vpn_tables =
1785 0 : list_of("bgp.l3vpn.0")("bgp.ermvpn.0")("bgp.evpn.0")("bgp.rtarget.0")
1786 0 : ("bgp.l3vpn-inet6.0")("bgp.mvpn.0");
1787 :
1788 0 : if (master_tables.find(table) != master_tables.end())
1789 0 : return BgpConfigManager::kMasterInstance;
1790 0 : if (vpn_tables.find(table) != vpn_tables.end())
1791 0 : return BgpConfigManager::kMasterInstance;
1792 :
1793 0 : size_t pos1 = table.rfind('.');
1794 0 : if (pos1 == string::npos)
1795 0 : return "__unknown__";
1796 0 : size_t pos2 = table.rfind('.', pos1 - 1);
1797 0 : if (pos2 == string::npos)
1798 0 : return "__unknown__";
1799 :
1800 0 : return table.substr(0, pos2);
1801 : }
1802 :
1803 128 : void RoutingInstance::set_index(int index) {
1804 128 : index_ = index;
1805 128 : if (is_master_)
1806 32 : return;
1807 :
1808 96 : rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index));
1809 : }
1810 :
1811 1742 : RoutingInstanceInfo RoutingInstance::GetDataCollection(const char *operation) {
1812 3485 : RoutingInstanceInfo info;
1813 1743 : info.set_name(GetVirtualNetworkName());
1814 1743 : info.set_instance_name(name_);
1815 1743 : info.set_hostname(server_->localname());
1816 1743 : if (rd_.get()) info.set_route_distinguisher(rd_->ToString());
1817 1743 : if (operation) info.set_operation(operation);
1818 1743 : 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 0 : bool RoutingInstance::HasExportTarget(const ExtCommunity *extcomm) const {
1826 0 : if (!extcomm)
1827 0 : return false;
1828 :
1829 0 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &value,
1830 : extcomm->communities()) {
1831 0 : if (!ExtCommunity::is_route_target(value))
1832 0 : continue;
1833 0 : RouteTarget rtarget(value);
1834 0 : if (export_.find(rtarget) != export_.end())
1835 0 : return true;
1836 : }
1837 :
1838 0 : return false;
1839 : }
1840 :
1841 : // Return true if the route is a service-chain route
1842 40 : bool RoutingInstance::IsServiceChainRoute(const BgpRoute *route) const {
1843 40 : const BgpTable *table = route->table();
1844 40 : if (!table) {
1845 0 : return false;
1846 : }
1847 40 : const BgpInstanceConfig *rt_config = this->config();
1848 40 : if (!rt_config) {
1849 0 : return false;
1850 : }
1851 : SCAddress::Family sc_family =
1852 40 : SCAddress::AddressFamilyToSCFamily(table->family());
1853 : const ServiceChainConfig *sc_config =
1854 40 : rt_config->service_chain_info(sc_family);
1855 40 : if (!sc_config) {
1856 40 : return false;
1857 : }
1858 0 : 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 92 : bool RoutingInstance::ProcessRoutingPolicy(const BgpRoute *route,
1869 : BgpPath *path) const {
1870 92 : ExtCommunityPtr ext_community = path->GetOriginalAttr()->ext_community();
1871 132 : if (path->IsReplicated() &&
1872 132 : 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 92 : if (path->IsReplicated() && IsServiceChainRoute(route)) {
1884 0 : BGP_LOG_ROUTE(route->table(), static_cast<IPeer *>(path->GetPeer()),
1885 : route, "Not applying policy for service-chain secondary "
1886 : "routes");
1887 0 : return true;
1888 : }
1889 92 : const RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1890 : // Take snapshot of original attribute
1891 92 : BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
1892 92 : BOOST_FOREACH(RoutingPolicyInfo info, routing_policies()) {
1893 0 : 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 0 : policy_mgr->ExecuteRoutingPolicy(policy.get(), route,
1899 : path, out_attr);
1900 0 : if (result.first) {
1901 : // Hit a terminal policy
1902 0 : if (!result.second) {
1903 : // Result of the policy is reject
1904 0 : path->SetPolicyReject();
1905 0 : } else if (path->IsPolicyReject()) {
1906 : // Result of the policy is Accept
1907 : // Clear the reject flag is marked before
1908 0 : path->ResetPolicyReject();
1909 : }
1910 0 : 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 0 : if (peer) {
1915 0 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
1916 0 : server_->extcomm_db(), route->table());
1917 : }
1918 0 : BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
1919 : // Update the path with new set of attributes
1920 0 : path->SetAttr(modified_attr, path->GetOriginalAttr());
1921 0 : return result.second;
1922 0 : }
1923 0 : }
1924 : // After processing all the routing policy,,
1925 : // We are here means, all the routing policies have accepted the route
1926 92 : IPeer *peer = path->GetPeer();
1927 92 : if (peer) {
1928 184 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
1929 92 : server_->extcomm_db(), route->table());
1930 : }
1931 92 : BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
1932 92 : path->SetAttr(modified_attr, path->GetOriginalAttr());
1933 : // Clear the reject if marked so in past
1934 92 : if (path->IsPolicyReject()) path->ResetPolicyReject();
1935 92 : return true;
1936 92 : }
1937 :
1938 0 : IStaticRouteMgr *RoutingInstance::LocateStaticRouteMgr(
1939 : Address::Family family) {
1940 0 : IStaticRouteMgr *manager = static_route_mgr(family);
1941 0 : if (manager)
1942 0 : return manager;
1943 0 : if (family == Address::INET) {
1944 0 : inet_static_route_mgr_.reset(
1945 0 : BgpStaticObjectFactory::Create<IStaticRouteMgr, Address::INET>(this));
1946 0 : return inet_static_route_mgr_.get();
1947 0 : } else if (family == Address::INET6) {
1948 0 : inet6_static_route_mgr_.reset(
1949 0 : BgpStaticObjectFactory::Create<IStaticRouteMgr, Address::INET6>(this));
1950 0 : return inet6_static_route_mgr_.get();
1951 : }
1952 0 : return NULL;
1953 : }
1954 :
1955 0 : IRouteAggregator *RoutingInstance::LocateRouteAggregator(
1956 : Address::Family family) {
1957 0 : IRouteAggregator *aggregator = route_aggregator(family);
1958 0 : if (aggregator)
1959 0 : return aggregator;
1960 0 : if (family == Address::INET) {
1961 0 : GetTable(family)->LocatePathResolver();
1962 0 : inet_route_aggregator_.reset(
1963 0 : BgpStaticObjectFactory::Create<IRouteAggregator, Address::INET>(this));
1964 0 : inet_route_aggregator_->Initialize();
1965 0 : return inet_route_aggregator_.get();
1966 0 : } else if (family == Address::INET6) {
1967 0 : GetTable(family)->LocatePathResolver();
1968 0 : inet6_route_aggregator_.reset(
1969 0 : BgpStaticObjectFactory::Create<IRouteAggregator, Address::INET6>(this));
1970 0 : inet6_route_aggregator_->Initialize();
1971 0 : return inet6_route_aggregator_.get();
1972 : }
1973 0 : return NULL;
1974 : }
1975 :
1976 0 : void RoutingInstance::DestroyRouteAggregator(Address::Family family) {
1977 0 : if (family == Address::INET) {
1978 0 : inet_route_aggregator_.reset();
1979 0 : } else if (family == Address::INET6) {
1980 0 : inet6_route_aggregator_.reset();
1981 : }
1982 0 : }
1983 :
1984 : // Check whether the route is aggregating route
1985 0 : bool RoutingInstance::IsAggregateRoute(const BgpTable *table,
1986 : const BgpRoute *route) const {
1987 0 : if (!route_aggregator(table->family())) return false;
1988 0 : return route_aggregator(table->family())->IsAggregateRoute(route);
1989 : }
1990 :
1991 : // Check whether the route is contributing route to aggregate route
1992 168 : bool RoutingInstance::IsContributingRoute(const BgpTable *table,
1993 : const BgpRoute *route) const {
1994 168 : if (!route_aggregator(table->family())) return false;
1995 0 : return route_aggregator(table->family())->IsContributingRoute(route);
1996 : }
1997 :
1998 0 : int RoutingInstance::GetOriginVnForAggregateRoute(Address::Family fmly) const {
1999 : SCAddress sc_addr;
2000 : SCAddress::Family sc_family =
2001 0 : sc_addr.AddressFamilyToSCFamily(fmly);
2002 : const ServiceChainConfig *sc_config =
2003 0 : config_ ? config_->service_chain_info(sc_family) : NULL;
2004 0 : if (sc_config && !sc_config->routing_instance.empty()) {
2005 : RoutingInstance *dest =
2006 0 : mgr_->GetRoutingInstanceLocked(sc_config->routing_instance);
2007 0 : if (dest) return dest->virtual_network_index();
2008 : }
2009 0 : return virtual_network_index_;
2010 : }
2011 :
2012 0 : size_t RoutingInstance::peer_manager_size() const {
2013 0 : return (peer_manager_ ? peer_manager_->size() : 0);
2014 : }
2015 :
2016 128 : PeerManager *RoutingInstance::LocatePeerManager() {
2017 128 : if (!peer_manager_)
2018 96 : peer_manager_.reset(BgpStaticObjectFactory::Create<PeerManager>(this));
2019 128 : 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 0 : string RoutingInstanceMgr::GetPrimaryRoutingInstanceName(const string &name) {
2028 0 : string n = name;
2029 0 : vector<string> tokens;
2030 0 : boost::split(tokens, n, boost::is_any_of(":"));
2031 0 : if (tokens.size() < 3)
2032 0 : return "";
2033 0 : ostringstream os;
2034 0 : os << tokens[0] << ":" << tokens[1] << ":" << tokens[2] << ":" << tokens[2];
2035 0 : return os.str();
2036 0 : }
|