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 240 : explicit DeleteActor(RoutingInstanceMgr *manager)
47 240 : : LifetimeActor(manager->server_->lifetime_manager()),
48 240 : manager_(manager) {
49 240 : }
50 240 : virtual bool MayDelete() const {
51 240 : return manager_->MayDelete();
52 : }
53 240 : virtual void Shutdown() {
54 240 : manager_->Shutdown();
55 240 : }
56 240 : virtual void Destroy() {
57 240 : manager_->server_delete_ref_.Reset(NULL);
58 240 : }
59 :
60 : private:
61 : RoutingInstanceMgr *manager_;
62 : };
63 :
64 240 : RoutingInstanceMgr::RoutingInstanceMgr(BgpServer *server) :
65 240 : server_(server),
66 480 : instance_config_lists_(
67 240 : TaskScheduler::GetInstance()->HardwareThreadCount()),
68 240 : default_rtinstance_(NULL),
69 240 : deleted_count_(0),
70 240 : asn_listener_id_(server->RegisterASNUpdateCallback(
71 : boost::bind(&RoutingInstanceMgr::ASNUpdateCallback, this, _1, _2))),
72 240 : identifier_listener_id_(server->RegisterIdentifierUpdateCallback(
73 : boost::bind(&RoutingInstanceMgr::IdentifierUpdateCallback,
74 : this, _1))),
75 240 : dormant_trace_buf_size_(
76 240 : GetEnvRoutingInstanceDormantTraceBufferCapacity()),
77 240 : trace_buf_threshold_(
78 240 : GetEnvRoutingInstanceDormantTraceBufferThreshold()),
79 240 : deleter_(new DeleteActor(this)),
80 720 : server_delete_ref_(this, server->deleter()) {
81 240 : int task_id = TaskScheduler::GetInstance()->GetTaskId("bgp::ConfigHelper");
82 240 : int hw_thread_count = TaskScheduler::GetInstance()->HardwareThreadCount();
83 1200 : for (int idx = 0; idx < hw_thread_count; ++idx) {
84 1920 : instance_config_triggers_.push_back(new TaskTrigger(boost::bind(
85 : &RoutingInstanceMgr::ProcessInstanceConfigList, this, idx),
86 960 : task_id, idx));
87 : }
88 480 : neighbor_config_trigger_.reset(new TaskTrigger(
89 : boost::bind(&RoutingInstanceMgr::ProcessNeighborConfigList, this),
90 480 : TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0));
91 240 : }
92 :
93 480 : RoutingInstanceMgr::~RoutingInstanceMgr() {
94 240 : assert(mvpn_project_managers_.empty());
95 240 : assert(virtual_networks_.empty());
96 240 : assert(deleted_count_ == 0);
97 240 : server_->UnregisterASNUpdateCallback(asn_listener_id_);
98 240 : server_->UnregisterIdentifierUpdateCallback(identifier_listener_id_);
99 240 : STLDeleteValues(&instance_config_triggers_);
100 480 : }
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 240 : void RoutingInstanceMgr::ManagedDelete() {
114 240 : deleter_->Delete();
115 240 : }
116 :
117 240 : void RoutingInstanceMgr::Shutdown() {
118 720 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
119 480 : InstanceTargetRemove(it->second);
120 480 : InstanceVnIndexRemove(it->second);
121 : }
122 240 : }
123 :
124 240 : bool RoutingInstanceMgr::MayDelete() const {
125 240 : if (!neighbor_config_list_.empty())
126 0 : return false;
127 1200 : for (size_t idx = 0; idx < instance_config_lists_.size(); ++idx) {
128 960 : if (!instance_config_lists_[idx].empty())
129 0 : return false;
130 : }
131 240 : return true;
132 : }
133 :
134 1328 : LifetimeActor *RoutingInstanceMgr::deleter() {
135 1328 : return deleter_.get();
136 : }
137 :
138 848 : bool RoutingInstanceMgr::deleted() {
139 848 : 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 1136 : void RoutingInstanceMgr::InstanceTargetAdd(RoutingInstance *rti) {
151 1136 : std::scoped_lock lock(mutex_);
152 1136 : for (RoutingInstance::RouteTargetList::const_iterator it =
153 2640 : rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
154 368 : if (rti->GetImportList().find(*it) == rti->GetImportList().end())
155 0 : continue;
156 368 : target_map_.insert(make_pair(*it, rti));
157 : }
158 1136 : }
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 1136 : void RoutingInstanceMgr::InstanceTargetRemove(const RoutingInstance *rti) {
170 1136 : std::scoped_lock lock(mutex_);
171 1136 : for (RoutingInstance::RouteTargetList::const_iterator it =
172 2640 : rti->GetExportList().begin(); it != rti->GetExportList().end(); ++it) {
173 368 : if (rti->GetImportList().find(*it) == rti->GetImportList().end())
174 0 : continue;
175 368 : for (InstanceTargetMap::iterator loc = target_map_.find(*it);
176 368 : loc != target_map_.end() && loc->first == *it; ++loc) {
177 368 : if (loc->second == rti) {
178 368 : target_map_.erase(loc);
179 368 : break;
180 : }
181 : }
182 : }
183 1136 : }
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 1136 : void RoutingInstanceMgr::InstanceVnIndexAdd(RoutingInstance *rti) {
201 1136 : std::scoped_lock lock(mutex_);
202 1136 : if (rti->virtual_network_index())
203 368 : vn_index_map_.insert(make_pair(rti->virtual_network_index(), rti));
204 1136 : }
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 1136 : void RoutingInstanceMgr::InstanceVnIndexRemove(const RoutingInstance *rti) {
212 1136 : std::scoped_lock lock(mutex_);
213 1136 : if (!rti->virtual_network_index())
214 768 : return;
215 :
216 368 : int vn_index = rti->virtual_network_index();
217 368 : for (VnIndexMap::iterator loc = vn_index_map_.find(vn_index);
218 368 : loc != vn_index_map_.end() && loc->first == vn_index; ++loc) {
219 368 : if (loc->second == rti) {
220 368 : vn_index_map_.erase(loc);
221 368 : break;
222 : }
223 : }
224 1136 : }
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 0 : int RoutingInstanceMgr::GetVnIndexByRouteTarget(
254 : const RouteTarget &rtarget) const {
255 0 : int vn_index = 0;
256 0 : for (InstanceTargetMap::const_iterator loc = target_map_.find(rtarget);
257 0 : loc != target_map_.end() && loc->first == rtarget; ++loc) {
258 0 : int ri_vn_index = loc->second->virtual_network_index();
259 0 : if (vn_index && ri_vn_index && ri_vn_index != vn_index)
260 0 : return -1;
261 0 : vn_index = ri_vn_index;
262 : }
263 :
264 0 : 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 0 : int RoutingInstanceMgr::GetVnIndexByExtCommunity(
275 : const ExtCommunity *ext_community) const {
276 0 : int vn_index = 0;
277 0 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
278 : ext_community->communities()) {
279 0 : if (!ExtCommunity::is_route_target(comm))
280 0 : continue;
281 :
282 0 : RouteTarget rtarget(comm);
283 0 : int rtgt_vn_index = GetVnIndexByRouteTarget(rtarget);
284 0 : 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 0 : } else if (rtgt_vn_index) {
289 0 : vn_index = rtgt_vn_index;
290 : }
291 : }
292 :
293 0 : return vn_index;
294 : }
295 :
296 : int
297 1200 : RoutingInstanceMgr::RegisterInstanceOpCallback(RoutingInstanceCb callback) {
298 1200 : std::scoped_lock lock(mutex_);
299 1200 : size_t i = bmap_.find_first();
300 1200 : if (i == bmap_.npos) {
301 1200 : i = callbacks_.size();
302 1200 : 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 1200 : return i;
311 1200 : }
312 :
313 1200 : void RoutingInstanceMgr::UnregisterInstanceOpCallback(int listener) {
314 1200 : std::scoped_lock lock(mutex_);
315 1200 : callbacks_[listener] = NULL;
316 1200 : if ((size_t) listener == callbacks_.size() - 1) {
317 1680 : while (!callbacks_.empty() && callbacks_.back() == NULL) {
318 1200 : callbacks_.pop_back();
319 : }
320 480 : if (bmap_.size() > callbacks_.size()) {
321 240 : bmap_.resize(callbacks_.size());
322 : }
323 : } else {
324 720 : if ((size_t) listener >= bmap_.size()) {
325 720 : bmap_.resize(listener + 1);
326 : }
327 720 : bmap_.set(listener);
328 : }
329 1200 : }
330 :
331 1616 : void RoutingInstanceMgr::NotifyInstanceOp(string name, Operation op) {
332 1616 : std::scoped_lock lock(mutex_);
333 1616 : for (InstanceOpListenersList::iterator iter = callbacks_.begin();
334 6336 : iter != callbacks_.end(); ++iter) {
335 4720 : if (*iter != NULL) {
336 4720 : RoutingInstanceCb cb = *iter;
337 4720 : (cb)(name, op);
338 4720 : }
339 : }
340 1616 : }
341 :
342 368 : bool RoutingInstanceMgr::ProcessInstanceConfigList(int idx) {
343 368 : if (deleted()) {
344 0 : deleter()->RetryDelete();
345 : } else {
346 1104 : BOOST_FOREACH(const string &name, instance_config_lists_[idx]) {
347 : const BgpInstanceConfig *config =
348 368 : server()->config_manager()->FindInstance(name);
349 368 : if (!config)
350 0 : continue;
351 368 : LocateRoutingInstance(config);
352 : }
353 : }
354 :
355 368 : instance_config_lists_[idx].clear();
356 368 : return true;
357 : }
358 :
359 4208 : RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() {
360 4208 : return default_rtinstance_;
361 : }
362 :
363 0 : const RoutingInstance *RoutingInstanceMgr::GetDefaultRoutingInstance() const {
364 0 : return default_rtinstance_;
365 : }
366 :
367 168 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(const string &name) {
368 168 : RoutingInstanceList::iterator iter = instances_.find(name);
369 168 : if (iter != instances_.end())
370 168 : return iter->second;
371 0 : return NULL;
372 : }
373 :
374 0 : const RoutingInstance *RoutingInstanceMgr::GetRoutingInstance(
375 : const string &name) const {
376 0 : RoutingInstanceList::const_iterator iter = instances_.find(name);
377 0 : if (iter != instances_.end())
378 0 : return iter->second;
379 0 : return NULL;
380 : }
381 :
382 1136 : RoutingInstance *RoutingInstanceMgr::GetRoutingInstanceLocked(
383 : const string &name) {
384 1136 : std::scoped_lock lock(mutex_);
385 1136 : RoutingInstanceList::iterator iter = instances_.find(name);
386 1136 : if (iter != instances_.end())
387 656 : return iter->second;
388 480 : return NULL;
389 1136 : }
390 :
391 480 : void RoutingInstanceMgr::InsertRoutingInstance(RoutingInstance *rtinstance) {
392 480 : std::scoped_lock lock(mutex_);
393 480 : instances_.insert(make_pair(rtinstance->config()->name(),
394 : rtinstance));
395 480 : }
396 :
397 1136 : void RoutingInstanceMgr::LocateRoutingInstance(
398 : const BgpInstanceConfig *config) {
399 1136 : RoutingInstance *rtinstance = GetRoutingInstanceLocked(config->name());
400 1136 : if (rtinstance) {
401 656 : 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 656 : UpdateRoutingInstance(rtinstance, config);
408 : }
409 : } else {
410 480 : rtinstance = CreateRoutingInstance(config);
411 : }
412 1136 : }
413 :
414 1888 : void RoutingInstanceMgr::LocateRoutingInstance(const string &name) {
415 : static boost::hash<string> string_hash;
416 :
417 1888 : if (name == BgpConfigManager::kMasterInstance) {
418 : const BgpInstanceConfig *config =
419 768 : server()->config_manager()->FindInstance(name);
420 768 : assert(config);
421 768 : LocateRoutingInstance(config);
422 : } else {
423 1120 : size_t idx = string_hash(name) % instance_config_lists_.size();
424 1120 : instance_config_lists_[idx].insert(name);
425 1120 : instance_config_triggers_[idx]->Set();
426 : }
427 1888 : }
428 :
429 : // Update VirtualNetwork to RoutingInstance name mapping.
430 480 : bool RoutingInstanceMgr::CreateVirtualNetworkMapping(
431 : const string &virtual_network, const string &instance_name) {
432 480 : std::scoped_lock lock(mutex_);
433 :
434 480 : VirtualNetworksMap::iterator iter;
435 : bool inserted;
436 960 : tie(iter, inserted) = virtual_networks_.insert(make_pair(virtual_network,
437 1440 : set<string>()));
438 480 : assert(iter->second.insert(instance_name).second);
439 480 : return true;
440 480 : }
441 :
442 480 : bool RoutingInstanceMgr::DeleteVirtualNetworkMapping(
443 : const string &virtual_network, const string &instance_name) {
444 480 : std::scoped_lock lock(mutex_);
445 :
446 480 : VirtualNetworksMap::iterator iter = virtual_networks_.find(virtual_network);
447 480 : assert(iter != virtual_networks_.end());
448 :
449 : // Delete this instance from the set of virtual-network to instances map.
450 480 : assert(iter->second.erase(instance_name) == 1);
451 :
452 960 : RoutingInstanceStatsData instance_info;
453 480 : bool mapping_deleted = iter->second.empty();
454 :
455 : // Delete the mapping if the member set is empty.
456 480 : if (mapping_deleted) {
457 480 : virtual_networks_.erase(iter);
458 :
459 : // Delete the virtual-network specific UVE.
460 480 : instance_info.set_deleted(true);
461 : } else {
462 :
463 : // Delete this instance's uve, by deleting all table stats.
464 0 : map<string, RoutingTableStats> stats_map;
465 0 : stats_map.insert(make_pair(instance_name, RoutingTableStats()));
466 0 : stats_map[instance_name].set_deleted(true);
467 :
468 : // Delete all uve stats across all address families.
469 0 : for (Address::Family i = Address::UNSPEC; i < Address::NUM_FAMILIES;
470 0 : i = static_cast<Address::Family>(i + 1)) {
471 0 : SetTableStatsUve(i, stats_map, &instance_info);
472 : }
473 0 : }
474 :
475 : // Send delete uve.
476 480 : instance_info.set_name(virtual_network);
477 480 : assert(!instance_info.get_name().empty());
478 480 : BGP_UVE_SEND(RoutingInstanceStats, instance_info);
479 :
480 480 : return mapping_deleted;
481 480 : }
482 :
483 0 : 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 0 : switch (family) {
489 0 : case Address::UNSPEC:
490 0 : break;
491 0 : case Address::INET:
492 : case Address::INETMPLS:
493 0 : instance_info->set_raw_ipv4_stats(stats_map);
494 0 : break;
495 0 : case Address::INET6:
496 0 : instance_info->set_raw_ipv6_stats(stats_map);
497 0 : break;
498 0 : case Address::INETVPN:
499 0 : instance_info->set_raw_inetvpn_stats(stats_map);
500 0 : break;
501 0 : case Address::INET6VPN:
502 0 : instance_info->set_raw_inet6vpn_stats(stats_map);
503 0 : break;
504 0 : case Address::RTARGET:
505 0 : instance_info->set_raw_rtarget_stats(stats_map);
506 0 : break;
507 0 : case Address::EVPN:
508 0 : instance_info->set_raw_evpn_stats(stats_map);
509 0 : break;
510 0 : case Address::ERMVPN:
511 0 : instance_info->set_raw_ermvpn_stats(stats_map);
512 0 : break;
513 0 : case Address::MVPN:
514 0 : instance_info->set_raw_mvpn_stats(stats_map);
515 0 : break;
516 0 : case Address::NUM_FAMILIES:
517 0 : break;
518 : }
519 0 : }
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 480 : RoutingInstance *RoutingInstanceMgr::CreateRoutingInstance(
565 : const BgpInstanceConfig *config) {
566 480 : RoutingInstance *rtinstance = BgpStaticObjectFactory::Create<RoutingInstance>(
567 480 : config->name(), server_, this, config);
568 480 : uint32_t ri_index = config->index();
569 480 : if (config->name() == BgpConfigManager::kMasterInstance) {
570 240 : default_rtinstance_ = rtinstance;
571 240 : ri_index = 0;
572 : }
573 :
574 480 : rtinstance->ProcessConfig();
575 480 : InsertRoutingInstance(rtinstance);
576 480 : rtinstance->set_index(ri_index);
577 :
578 480 : InstanceTargetAdd(rtinstance);
579 480 : InstanceVnIndexAdd(rtinstance);
580 480 : rtinstance->InitAllRTargetRoutes(server_->local_autonomous_system());
581 :
582 : // Notify clients about routing instance create
583 480 : NotifyInstanceOp(config->name(), INSTANCE_ADD);
584 :
585 480 : vector<string> import_rt(config->import_list().begin(),
586 960 : config->import_list().end());
587 480 : vector<string> export_rt(config->export_list().begin(),
588 960 : config->export_list().end());
589 480 : 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 480 : CreateRoutingInstanceNeighbors(config);
595 :
596 : // Update instance to virtual-network mapping structures.
597 480 : CreateVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
598 : rtinstance->name());
599 :
600 : // Create MvpnManager for all children mvpn networks.
601 : MvpnTable *mvpn_table =
602 480 : dynamic_cast<MvpnTable *>(rtinstance->GetTable(Address::MVPN));
603 480 : mvpn_table->CreateMvpnManagers();
604 480 : return rtinstance;
605 480 : }
606 :
607 656 : void RoutingInstanceMgr::UpdateRoutingInstance(RoutingInstance *rtinstance,
608 : const BgpInstanceConfig *config) {
609 656 : bool old_always_subscribe = rtinstance->always_subscribe();
610 :
611 : // Note that InstanceTarget[Remove|Add] depend on the RouteTargetList in
612 : // the RoutingInstance.
613 656 : InstanceTargetRemove(rtinstance);
614 656 : InstanceVnIndexRemove(rtinstance);
615 656 : rtinstance->UpdateConfig(config);
616 656 : InstanceTargetAdd(rtinstance);
617 656 : InstanceVnIndexAdd(rtinstance);
618 :
619 656 : 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 656 : NotifyInstanceOp(config->name(), INSTANCE_UPDATE);
626 :
627 656 : vector<string> import_rt(config->import_list().begin(),
628 1312 : config->import_list().end());
629 656 : vector<string> export_rt(config->export_list().begin(),
630 1312 : config->export_list().end());
631 656 : RTINSTANCE_LOG(Update, rtinstance,
632 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL, import_rt, export_rt,
633 : rtinstance->virtual_network_index());
634 656 : }
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 480 : void RoutingInstanceMgr::DestroyRoutingInstance(RoutingInstance *rtinstance) {
682 480 : CHECK_CONCURRENCY("bgp::Config");
683 :
684 480 : RTINSTANCE_LOG(Destroy, rtinstance,
685 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
686 :
687 480 : DeleteVirtualNetworkMapping(rtinstance->GetVirtualNetworkName(),
688 : rtinstance->name());
689 :
690 : // instance should also be deleted here
691 480 : const string name = rtinstance->name();
692 480 : RoutingInstanceList::iterator loc = instances_.find(rtinstance->name());
693 480 : assert(loc != instances_.end());
694 480 : instances_.erase(loc);
695 480 : int index = rtinstance->index();
696 480 : delete rtinstance;
697 : // disable the TraceBuf for the deleted RoutingInstance
698 480 : DisableTraceBuffer(name);
699 : // index was allocated in Config Manager so needs to be freed
700 480 : if (index >= 0)
701 480 : server()->config_manager()->ResetRoutingInstanceIndexBit(index);
702 :
703 480 : if (deleted())
704 480 : 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 480 : }
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 480 : void RoutingInstanceMgr::DisableTraceBuffer(const std::string &name) {
762 480 : tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
763 480 : SandeshTraceBufferPtr trace_buf;
764 480 : SandeshTraceBufferPtr trace_buf_delete;
765 480 : RoutingInstanceTraceBufferMap::iterator iter;
766 480 : std::pair<RoutingInstanceTraceBufferMap::iterator, bool> ret;
767 480 : std::string ri_name;
768 :
769 : // Moving the trace buff from Active map to Dormant map
770 480 : iter = trace_buffer_active_.find(name);
771 480 : 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 960 : return;
803 480 : }
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 240 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferCapacity() const {
850 240 : 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 240 : 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 240 : return 0;
858 : }
859 :
860 : size_t
861 240 : RoutingInstanceMgr::GetEnvRoutingInstanceDormantTraceBufferThreshold() const {
862 240 : char *buffer_threshold_str = getenv(
863 : "CONTRAIL_ROUTING_INSTANCE_DORMANT_TRACE_BUFFER_THRESHOLD");
864 240 : 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 240 : 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 480 : void RoutingInstanceMgr::CreateRoutingInstanceNeighbors(
882 : const BgpInstanceConfig *config) {
883 480 : if (config->neighbor_list().empty())
884 480 : 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 312 : void RoutingInstanceMgr::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) {
907 312 : if (server_->local_autonomous_system() == old_local_asn)
908 0 : return;
909 696 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
910 384 : it->second->FlushAllRTargetRoutes(old_local_asn);
911 384 : it->second->InitAllRTargetRoutes(server_->local_autonomous_system());
912 : }
913 312 : RoutingInstance *master = GetDefaultRoutingInstance();
914 312 : const Ip4Address old_identifier(server()->bgp_identifier());
915 312 : master->DeleteMvpnRTargetRoute(old_local_asn, old_identifier);
916 312 : master->AddMvpnRTargetRoute(server_->local_autonomous_system());
917 : }
918 :
919 288 : void RoutingInstanceMgr::IdentifierUpdateCallback(Ip4Address old_identifier) {
920 624 : for (RoutingInstanceIterator it = begin(); it != end(); ++it) {
921 336 : it->second->ProcessIdentifierUpdate(server_->local_autonomous_system());
922 : }
923 288 : RoutingInstance *master = GetDefaultRoutingInstance();
924 288 : master->DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
925 : old_identifier);
926 288 : master->AddMvpnRTargetRoute(server_->local_autonomous_system());
927 288 : }
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 480 : DeleteActor(BgpServer *server, RoutingInstance *parent)
968 480 : : LifetimeActor(server ? server->lifetime_manager() : NULL),
969 960 : parent_(parent) {
970 480 : }
971 480 : virtual bool MayDelete() const {
972 480 : return parent_->MayDelete();
973 : }
974 480 : virtual void Shutdown() {
975 480 : parent_->mgr_->increment_deleted_count();
976 480 : parent_->mgr_->NotifyInstanceOp(parent_->name(),
977 : RoutingInstanceMgr::INSTANCE_DELETE);
978 480 : parent_->Shutdown();
979 480 : }
980 480 : virtual void Destroy() {
981 480 : parent_->mgr_->decrement_deleted_count();
982 480 : parent_->mgr_->DestroyRoutingInstance(parent_);
983 480 : }
984 :
985 : private:
986 : RoutingInstance *parent_;
987 : };
988 :
989 480 : RoutingInstance::RoutingInstance(string name, BgpServer *server,
990 : RoutingInstanceMgr *mgr,
991 480 : const BgpInstanceConfig *config)
992 1440 : : name_(name), index_(-1), server_(server), mgr_(mgr), config_(config),
993 960 : is_master_(false), always_subscribe_(false), virtual_network_index_(0),
994 480 : virtual_network_allow_transit_(false),
995 480 : virtual_network_pbb_evpn_enable_(false),
996 480 : vxlan_id_(0),
997 480 : deleter_(new DeleteActor(server, this)),
998 480 : manager_delete_ref_(this, NULL),
999 960 : mvpn_project_manager_network_(BgpConfigManager::kFabricInstance) {
1000 480 : if (mgr) {
1001 480 : std::scoped_lock lock(mgr->mutex());
1002 480 : manager_delete_ref_.Reset(mgr->deleter());
1003 480 : }
1004 480 : }
1005 :
1006 960 : RoutingInstance::~RoutingInstance() {
1007 960 : }
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 480 : void RoutingInstance::ProcessRoutingPolicyConfig() {
1023 480 : RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1024 480 : 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 480 : }
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 128 : void RoutingInstance::UpdateRoutingPolicyConfig() {
1049 128 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1050 128 : RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1051 128 : 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 128 : }
1057 :
1058 1088 : void RoutingInstance::ProcessServiceChainConfig() {
1059 1088 : if (is_master_)
1060 480 : 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 608 : (SCAddress::INET) (SCAddress::INET6)
1075 608 : (SCAddress::EVPN) (SCAddress::EVPN6);
1076 :
1077 5472 : BOOST_FOREACH(SCAddress::Family family, families) {
1078 : const ServiceChainConfig *sc_config =
1079 2432 : config_ ? config_->service_chain_info(family) : NULL;
1080 2432 : IServiceChainMgr *manager = server_->service_chain_mgr(family);
1081 2432 : if (sc_config && !sc_config->routing_instance.empty()) {
1082 0 : manager->LocateServiceChain(this, *sc_config);
1083 : } else {
1084 2432 : manager->StopServiceChain(this);
1085 : }
1086 : }
1087 608 : }
1088 :
1089 480 : void RoutingInstance::ProcessStaticRouteConfig() {
1090 480 : if (is_master_)
1091 240 : return;
1092 :
1093 240 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1094 1200 : BOOST_FOREACH(Address::Family family, families) {
1095 480 : IStaticRouteMgr *manager = static_route_mgr(family);
1096 480 : if (!manager && !config_->static_routes(family).empty())
1097 0 : manager = LocateStaticRouteMgr(family);
1098 480 : if (manager)
1099 0 : manager->ProcessStaticRouteConfig();
1100 : }
1101 240 : }
1102 :
1103 128 : void RoutingInstance::UpdateStaticRouteConfig() {
1104 128 : if (is_master_)
1105 0 : return;
1106 :
1107 128 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1108 640 : BOOST_FOREACH(Address::Family family, families) {
1109 256 : IStaticRouteMgr *manager = static_route_mgr(family);
1110 256 : if (!manager && !config_->static_routes(family).empty())
1111 0 : manager = LocateStaticRouteMgr(family);
1112 256 : if (manager)
1113 0 : manager->UpdateStaticRouteConfig();
1114 : }
1115 128 : }
1116 :
1117 480 : void RoutingInstance::FlushStaticRouteConfig() {
1118 480 : if (is_master_)
1119 240 : return;
1120 :
1121 240 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1122 1200 : BOOST_FOREACH(Address::Family family, families) {
1123 480 : IStaticRouteMgr *manager = static_route_mgr(family);
1124 480 : if (manager)
1125 0 : manager->FlushStaticRouteConfig();
1126 : }
1127 240 : }
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 480 : void RoutingInstance::ProcessRouteAggregationConfig() {
1142 480 : if (is_master_)
1143 240 : return;
1144 :
1145 240 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1146 1200 : BOOST_FOREACH(Address::Family family, families) {
1147 480 : IRouteAggregator *aggregator = route_aggregator(family);
1148 480 : if (!aggregator && !config_->aggregate_routes(family).empty())
1149 0 : aggregator = LocateRouteAggregator(family);
1150 480 : if (aggregator)
1151 0 : aggregator->ProcessAggregateRouteConfig();
1152 : }
1153 240 : }
1154 :
1155 128 : void RoutingInstance::UpdateRouteAggregationConfig() {
1156 128 : if (is_master_)
1157 0 : return;
1158 :
1159 128 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1160 640 : BOOST_FOREACH(Address::Family family, families) {
1161 256 : IRouteAggregator *aggregator = route_aggregator(family);
1162 256 : if (!aggregator && !config_->aggregate_routes(family).empty())
1163 0 : aggregator = LocateRouteAggregator(family);
1164 256 : if (aggregator)
1165 0 : aggregator->UpdateAggregateRouteConfig();
1166 : }
1167 128 : }
1168 :
1169 480 : void RoutingInstance::FlushRouteAggregationConfig() {
1170 480 : if (is_master_)
1171 240 : return;
1172 :
1173 240 : vector<Address::Family> families = list_of(Address::INET)(Address::INET6);
1174 1200 : BOOST_FOREACH(Address::Family family, families) {
1175 480 : IRouteAggregator *aggregator = route_aggregator(family);
1176 480 : if (aggregator)
1177 0 : aggregator->FlushAggregateRouteConfig();
1178 : }
1179 240 : }
1180 :
1181 840 : void RoutingInstance::DeleteMvpnRTargetRoute(as_t asn, Ip4Address old_ip) {
1182 840 : if (asn == 0)
1183 520 : return;
1184 640 : string id_str = "target:" + old_ip.to_string() + ":0";
1185 320 : RouteTarget rtarget = RouteTarget::FromString(id_str);
1186 320 : DeleteRTargetRoute(asn, rtarget);
1187 320 : }
1188 :
1189 600 : void RoutingInstance::AddMvpnRTargetRoute(as_t asn) {
1190 600 : if (asn == 0)
1191 280 : return;
1192 320 : const Ip4Address server_ip(server()->bgp_identifier());
1193 640 : string id_str = "target:" + server_ip.to_string() + ":0";
1194 320 : RouteTarget rtarget = RouteTarget::FromString(id_str);
1195 320 : AddRTargetRoute(asn, rtarget);
1196 320 : }
1197 :
1198 480 : void RoutingInstance::ProcessConfig() {
1199 480 : RoutingInstanceInfo info = GetDataCollection("");
1200 :
1201 : // Initialize virtual network info.
1202 480 : virtual_network_ = config_->virtual_network();
1203 480 : virtual_network_index_ = config_->virtual_network_index();
1204 480 : virtual_network_allow_transit_ = config_->virtual_network_allow_transit();
1205 480 : virtual_network_pbb_evpn_enable_ =
1206 480 : config_->virtual_network_pbb_evpn_enable();
1207 480 : vxlan_id_ = config_->vxlan_id();
1208 480 : routing_instance_vxlan_ = config_->routing_instance_vxlan();
1209 :
1210 : // Always subscribe (using RTF) for RTs of PNF service chain instances.
1211 480 : always_subscribe_ = config_->has_pnf();
1212 :
1213 480 : vector<string> import_rt, export_rt;
1214 1920 : BOOST_FOREACH(string irt, config_->import_list()) {
1215 720 : error_code error;
1216 720 : RouteTarget rt = RouteTarget::FromString(irt, &error);
1217 720 : if (!error) {
1218 720 : import_.insert(rt);
1219 720 : import_rt.push_back(irt);
1220 : }
1221 720 : }
1222 960 : BOOST_FOREACH(string ert, config_->export_list()) {
1223 240 : error_code error;
1224 240 : RouteTarget rt = RouteTarget::FromString(ert, &error);
1225 240 : if (!error) {
1226 240 : export_.insert(rt);
1227 240 : export_rt.push_back(ert);
1228 : }
1229 240 : }
1230 480 : RTINSTANCE_LOG(Update, this,
1231 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL,
1232 : import_rt, export_rt, this->virtual_network_index());
1233 :
1234 480 : if (import_rt.size())
1235 240 : info.set_add_import_rt(import_rt);
1236 480 : if (export_rt.size())
1237 240 : info.set_add_export_rt(export_rt);
1238 480 : if (import_rt.size() || export_rt.size())
1239 240 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1240 :
1241 : // Create BGP Table
1242 480 : if (name_ == BgpConfigManager::kMasterInstance) {
1243 240 : assert(mgr_->count() == 0);
1244 240 : is_master_ = true;
1245 :
1246 240 : LocatePeerManager();
1247 240 : VpnTableCreate(Address::INETVPN);
1248 240 : VpnTableCreate(Address::INET6VPN);
1249 240 : VpnTableCreate(Address::ERMVPN);
1250 240 : VpnTableCreate(Address::MVPN);
1251 240 : VpnTableCreate(Address::EVPN);
1252 240 : RTargetTableCreate();
1253 :
1254 : BgpTable *table_inet = static_cast<BgpTable *>(
1255 240 : server_->database()->CreateTable("inet.0"));
1256 240 : assert(table_inet);
1257 240 : AddTable(table_inet);
1258 :
1259 : BgpTable *table_inetmpls = static_cast<BgpTable *>(
1260 240 : server_->database()->CreateTable("inet.3"));
1261 240 : assert(table_inetmpls);
1262 240 : AddTable(table_inetmpls);
1263 :
1264 : BgpTable *table_inet6 = static_cast<BgpTable *>(
1265 240 : server_->database()->CreateTable("inet6.0"));
1266 240 : assert(table_inet6);
1267 240 : 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 240 : BgpTable *inet_table = VrfTableCreate(Address::INET, Address::INETVPN);
1273 240 : inet_table->LocatePathResolver();
1274 :
1275 : BgpTable *inet6_table =
1276 240 : VrfTableCreate(Address::INET6, Address::INET6VPN);
1277 240 : inet6_table->LocatePathResolver();
1278 :
1279 240 : VrfTableCreate(Address::ERMVPN, Address::ERMVPN);
1280 :
1281 240 : BgpTable *evpn_table = VrfTableCreate(Address::EVPN, Address::EVPN);
1282 240 : evpn_table->LocatePathResolver();
1283 :
1284 240 : BgpTable *table = VrfTableCreate(Address::MVPN, Address::MVPN);
1285 :
1286 : // Create path-resolver in mvpn table.
1287 240 : table->LocatePathResolver();
1288 : }
1289 :
1290 480 : ProcessServiceChainConfig();
1291 480 : ProcessStaticRouteConfig();
1292 480 : ProcessRouteAggregationConfig();
1293 480 : ProcessRoutingPolicyConfig();
1294 480 : }
1295 :
1296 656 : void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) {
1297 656 : 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 656 : config_ = cfg;
1302 :
1303 : // Always subscribe (using RTF) for RTs of PNF service chain instances.
1304 656 : 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 656 : bool notify_routes = false;
1309 656 : if (virtual_network_allow_transit_ != cfg->virtual_network_allow_transit())
1310 0 : notify_routes = true;
1311 656 : if (virtual_network_pbb_evpn_enable_ !=
1312 656 : cfg->virtual_network_pbb_evpn_enable())
1313 0 : notify_routes = true;
1314 656 : if (virtual_network_ != cfg->virtual_network())
1315 0 : notify_routes = true;
1316 656 : if (virtual_network_index_ != cfg->virtual_network_index())
1317 0 : notify_routes = true;
1318 :
1319 : // Trigger notification of all routes in each table.
1320 656 : 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 656 : if (virtual_network_index_ != cfg->virtual_network_index())
1329 0 : UpdateAllStaticRoutes();
1330 :
1331 656 : string prev_vn_name = GetVirtualNetworkName();
1332 :
1333 : // Update virtual network info.
1334 656 : virtual_network_ = cfg->virtual_network();
1335 :
1336 : // Recreate instance stats' UVE, if its key: virtual_network is modified.
1337 656 : if (prev_vn_name != GetVirtualNetworkName()) {
1338 0 : mgr_->DeleteVirtualNetworkMapping(prev_vn_name, name_);
1339 0 : mgr_->CreateVirtualNetworkMapping(GetVirtualNetworkName(), name_);
1340 : }
1341 :
1342 656 : virtual_network_index_ = cfg->virtual_network_index();
1343 656 : virtual_network_allow_transit_ = cfg->virtual_network_allow_transit();
1344 656 : virtual_network_pbb_evpn_enable_ = cfg->virtual_network_pbb_evpn_enable();
1345 656 : vxlan_id_ = cfg->vxlan_id();
1346 656 : 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 656 : if (IsMasterRoutingInstance())
1351 528 : return;
1352 :
1353 128 : RouteTargetList future_import;
1354 128 : vector<string> add_import_rt, remove_import_rt;
1355 896 : BOOST_FOREACH(const string &rtarget_str, cfg->import_list()) {
1356 384 : error_code error;
1357 384 : RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
1358 384 : if (!error)
1359 384 : future_import.insert(rt);
1360 : }
1361 128 : 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 128 : RouteTargetList future_export;
1368 128 : vector<string> add_export_rt, remove_export_rt;
1369 384 : BOOST_FOREACH(const string &rtarget_str, cfg->export_list()) {
1370 128 : error_code error;
1371 128 : RouteTarget rt = RouteTarget::FromString(rtarget_str, &error);
1372 128 : if (!error)
1373 128 : future_export.insert(rt);
1374 : }
1375 128 : 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 128 : RoutingInstanceInfo info = GetDataCollection("");
1382 128 : if (add_import_rt.size())
1383 16 : info.set_add_import_rt(add_import_rt);
1384 128 : if (remove_import_rt.size())
1385 16 : info.set_remove_import_rt(remove_import_rt);
1386 128 : if (add_export_rt.size())
1387 0 : info.set_add_export_rt(add_export_rt);
1388 128 : if (remove_export_rt.size())
1389 0 : info.set_remove_export_rt(remove_export_rt);
1390 352 : if (add_import_rt.size() || remove_import_rt.size() ||
1391 352 : add_export_rt.size() || remove_export_rt.size())
1392 16 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1393 :
1394 128 : ProcessServiceChainConfig();
1395 128 : UpdateStaticRouteConfig();
1396 128 : UpdateRouteAggregationConfig();
1397 128 : UpdateRoutingPolicyConfig();
1398 656 : }
1399 :
1400 480 : void RoutingInstance::ClearConfig() {
1401 480 : CHECK_CONCURRENCY("bgp::Config");
1402 480 : config_ = NULL;
1403 480 : }
1404 :
1405 480 : void RoutingInstance::ManagedDelete() {
1406 : // RoutingInstanceMgr logs the delete for non-master instances.
1407 480 : if (IsMasterRoutingInstance()) {
1408 240 : RTINSTANCE_LOG(Delete, this,
1409 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1410 : }
1411 480 : deleter_->Delete();
1412 480 : }
1413 :
1414 480 : void RoutingInstance::Shutdown() {
1415 480 : CHECK_CONCURRENCY("bgp::Config");
1416 :
1417 480 : RTINSTANCE_LOG(Shutdown, this,
1418 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1419 :
1420 480 : ClearConfig();
1421 480 : FlushAllRTargetRoutes(server_->local_autonomous_system());
1422 480 : if (is_master_) {
1423 240 : const Ip4Address old_identifier(server()->bgp_identifier());
1424 240 : DeleteMvpnRTargetRoute(server_->local_autonomous_system(),
1425 : old_identifier);
1426 : }
1427 480 : ClearRouteTarget();
1428 :
1429 480 : ProcessServiceChainConfig();
1430 480 : FlushStaticRouteConfig();
1431 480 : FlushRouteAggregationConfig();
1432 480 : }
1433 :
1434 480 : bool RoutingInstance::MayDelete() const {
1435 480 : return true;
1436 : }
1437 :
1438 3600 : LifetimeActor *RoutingInstance::deleter() {
1439 3600 : return deleter_.get();
1440 : }
1441 :
1442 896 : const LifetimeActor *RoutingInstance::deleter() const {
1443 896 : return deleter_.get();
1444 : }
1445 :
1446 896 : bool RoutingInstance::deleted() const {
1447 896 : return deleter()->IsDeleted();
1448 : }
1449 :
1450 9600 : const string RoutingInstance::GetVirtualNetworkName() const {
1451 9600 : if (!virtual_network_.empty())
1452 3264 : return virtual_network_;
1453 6336 : size_t pos = name_.rfind(':');
1454 6336 : if (pos == string::npos) {
1455 240 : return name_;
1456 : } else {
1457 6096 : return name_.substr(0, pos);
1458 : }
1459 : }
1460 :
1461 3008 : int RoutingInstance::virtual_network_index() const {
1462 3008 : 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 1200 : void RoutingInstance::ClearFamilyRouteTarget(Address::Family vrf_family,
1478 : Address::Family vpn_family) {
1479 1200 : BgpTable *table = GetTable(vrf_family);
1480 1200 : if (table) {
1481 1200 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1482 8400 : BOOST_FOREACH(RouteTarget rt, import_) {
1483 3600 : replicator->Leave(table, rt, true);
1484 : }
1485 3600 : BOOST_FOREACH(RouteTarget rt, export_) {
1486 1200 : replicator->Leave(table, rt, false);
1487 : }
1488 : }
1489 1200 : }
1490 :
1491 320 : void RoutingInstance::AddRTargetRoute(uint32_t asn,
1492 : const RouteTarget &rtarget) {
1493 320 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1494 :
1495 320 : RTargetPrefix prefix(asn, rtarget);
1496 320 : RTargetRoute rt_key(prefix);
1497 :
1498 320 : RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
1499 320 : BgpTable *table = master->GetTable(Address::RTARGET);
1500 : DBTablePartition *tbl_partition =
1501 320 : static_cast<DBTablePartition *>(table->GetTablePartition(0));
1502 :
1503 320 : std::scoped_lock lock(mgr_->mutex());
1504 : RTargetRoute *route =
1505 320 : static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
1506 320 : if (!route) {
1507 320 : route = new RTargetRoute(prefix);
1508 320 : tbl_partition->Add(route);
1509 : } else {
1510 0 : route->ClearDelete();
1511 : }
1512 :
1513 320 : if (route->FindPath(BgpPath::Local, index_))
1514 0 : return;
1515 :
1516 320 : BgpAttrSpec attr_spec;
1517 320 : BgpAttrNextHop nexthop(server_->bgp_identifier());
1518 320 : attr_spec.push_back(&nexthop);
1519 320 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
1520 320 : attr_spec.push_back(&origin);
1521 320 : BgpAttrPtr attr = server_->attr_db()->Locate(attr_spec);
1522 :
1523 320 : BgpPath *path = new BgpPath(index_, BgpPath::Local, attr);
1524 320 : route->InsertPath(path);
1525 320 : tbl_partition->Notify(route);
1526 320 : BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
1527 : route, "Insert Local path with path id " << index_);
1528 320 : }
1529 :
1530 1416 : void RoutingInstance::DeleteRTargetRoute(as_t asn,
1531 : const RouteTarget &rtarget) {
1532 1416 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1533 :
1534 1416 : if (asn == 0)
1535 1096 : return;
1536 :
1537 1296 : RTargetPrefix prefix(asn, rtarget);
1538 1296 : RTargetRoute rt_key(prefix);
1539 :
1540 1296 : RoutingInstance *master = mgr_->GetDefaultRoutingInstance();
1541 1296 : BgpTable *table = master->GetTable(Address::RTARGET);
1542 : DBTablePartition *tbl_partition =
1543 1296 : static_cast<DBTablePartition *>(table->GetTablePartition(0));
1544 :
1545 1296 : std::scoped_lock lock(mgr_->mutex());
1546 : RTargetRoute *route =
1547 1296 : static_cast<RTargetRoute *>(tbl_partition->Find(&rt_key));
1548 1296 : if (!route || !route->RemovePath(BgpPath::Local, index_))
1549 976 : return;
1550 :
1551 320 : BGP_LOG_ROUTE(table, static_cast<IPeer *>(NULL),
1552 : route, "Delete Local path with path id " << index_);
1553 320 : if (!route->HasPaths()) {
1554 320 : tbl_partition->Delete(route);
1555 : } else {
1556 0 : tbl_partition->Notify(route);
1557 : }
1558 2272 : }
1559 :
1560 1200 : void RoutingInstance::InitAllRTargetRoutes(as_t asn) {
1561 1200 : if (is_master_)
1562 840 : return;
1563 :
1564 360 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1565 2520 : BOOST_FOREACH(RouteTarget rtarget, import_) {
1566 1080 : if (asn != 0 && always_subscribe_)
1567 0 : AddRTargetRoute(asn, rtarget);
1568 : }
1569 : }
1570 :
1571 1200 : void RoutingInstance::FlushAllRTargetRoutes(as_t asn) {
1572 1200 : if (is_master_)
1573 840 : return;
1574 :
1575 360 : CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
1576 2520 : BOOST_FOREACH(RouteTarget rtarget, import_) {
1577 1080 : DeleteRTargetRoute(asn, rtarget);
1578 : }
1579 : }
1580 :
1581 336 : void RoutingInstance::ProcessIdentifierUpdate(as_t asn) {
1582 336 : FlushAllRTargetRoutes(asn);
1583 336 : InitAllRTargetRoutes(asn);
1584 336 : rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index_));
1585 336 : }
1586 :
1587 16 : void RoutingInstance::AddRouteTarget(bool import,
1588 : vector<string> *change_list, RouteTargetList::const_iterator it) {
1589 16 : BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
1590 : RoutePathReplicator *ermvpn_replicator =
1591 16 : server_->replicator(Address::ERMVPN);
1592 16 : BgpTable *mvpn_table = GetTable(Address::MVPN);
1593 : RoutePathReplicator *mvpn_replicator =
1594 16 : server_->replicator(Address::MVPN);
1595 16 : BgpTable *evpn_table = GetTable(Address::EVPN);
1596 : RoutePathReplicator *evpn_replicator =
1597 16 : server_->replicator(Address::EVPN);
1598 16 : BgpTable *inet_table = GetTable(Address::INET);
1599 : RoutePathReplicator *inetvpn_replicator =
1600 16 : server_->replicator(Address::INETVPN);
1601 16 : BgpTable *inet6_table = GetTable(Address::INET6);
1602 : RoutePathReplicator *inet6vpn_replicator =
1603 16 : server_->replicator(Address::INET6VPN);
1604 :
1605 16 : change_list->push_back(it->ToString());
1606 16 : if (import) {
1607 16 : import_.insert(*it);
1608 16 : 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 16 : ermvpn_replicator->Join(ermvpn_table, *it, import);
1615 16 : mvpn_replicator->Join(mvpn_table, *it, import);
1616 16 : evpn_replicator->Join(evpn_table, *it, import);
1617 16 : inetvpn_replicator->Join(inet_table, *it, import);
1618 16 : inet6vpn_replicator->Join(inet6_table, *it, import);
1619 16 : }
1620 :
1621 16 : void RoutingInstance::DeleteRouteTarget(bool import,
1622 : vector<string> *change_list, RouteTargetList::iterator it) {
1623 16 : BgpTable *ermvpn_table = GetTable(Address::ERMVPN);
1624 : RoutePathReplicator *ermvpn_replicator =
1625 16 : server_->replicator(Address::ERMVPN);
1626 16 : BgpTable *mvpn_table = GetTable(Address::MVPN);
1627 : RoutePathReplicator *mvpn_replicator =
1628 16 : server_->replicator(Address::MVPN);
1629 16 : BgpTable *evpn_table = GetTable(Address::EVPN);
1630 : RoutePathReplicator *evpn_replicator =
1631 16 : server_->replicator(Address::EVPN);
1632 16 : BgpTable *inet_table = GetTable(Address::INET);
1633 : RoutePathReplicator *inetvpn_replicator =
1634 16 : server_->replicator(Address::INETVPN);
1635 16 : BgpTable *inet6_table = GetTable(Address::INET6);
1636 : RoutePathReplicator *inet6vpn_replicator =
1637 16 : server_->replicator(Address::INET6VPN);
1638 :
1639 16 : ermvpn_replicator->Leave(ermvpn_table, *it, import);
1640 16 : mvpn_replicator->Leave(mvpn_table, *it, import);
1641 16 : evpn_replicator->Leave(evpn_table, *it, import);
1642 16 : inetvpn_replicator->Leave(inet_table, *it, import);
1643 16 : inet6vpn_replicator->Leave(inet6_table, *it, import);
1644 :
1645 16 : change_list->push_back(it->ToString());
1646 16 : if (import) {
1647 16 : DeleteRTargetRoute(server_->local_autonomous_system(), *it);
1648 16 : import_.erase(it);
1649 : } else {
1650 0 : export_.erase(it);
1651 : }
1652 16 : }
1653 :
1654 480 : void RoutingInstance::ClearRouteTarget() {
1655 480 : CHECK_CONCURRENCY("bgp::Config");
1656 480 : if (IsMasterRoutingInstance()) {
1657 240 : return;
1658 : }
1659 :
1660 240 : ClearFamilyRouteTarget(Address::INET, Address::INETVPN);
1661 240 : ClearFamilyRouteTarget(Address::INET6, Address::INET6VPN);
1662 240 : ClearFamilyRouteTarget(Address::ERMVPN, Address::ERMVPN);
1663 240 : ClearFamilyRouteTarget(Address::MVPN, Address::MVPN);
1664 240 : ClearFamilyRouteTarget(Address::EVPN, Address::EVPN);
1665 :
1666 240 : import_.clear();
1667 240 : export_.clear();
1668 : }
1669 :
1670 240 : BgpTable *RoutingInstance::RTargetTableCreate() {
1671 : BgpTable *rtargettbl = static_cast<BgpTable *>(
1672 240 : server_->database()->CreateTable("bgp.rtarget.0"));
1673 240 : RTINSTANCE_LOG_TABLE(Create, this, rtargettbl, SandeshLevel::SYS_DEBUG,
1674 : RTINSTANCE_LOG_FLAG_ALL);
1675 240 : AddTable(rtargettbl);
1676 240 : return rtargettbl;
1677 : }
1678 :
1679 1200 : BgpTable *RoutingInstance::VpnTableCreate(Address::Family vpn_family) {
1680 1200 : string table_name = GetTableName(name(), vpn_family);
1681 : BgpTable *table = static_cast<BgpTable *>(
1682 1200 : server_->database()->CreateTable(table_name));
1683 1200 : assert(table);
1684 :
1685 1200 : AddTable(table);
1686 1200 : RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
1687 : RTINSTANCE_LOG_FLAG_ALL);
1688 1200 : assert(server_->rtarget_group_mgr()->empty());
1689 1200 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1690 1200 : replicator->Initialize();
1691 1200 : return table;
1692 1200 : }
1693 :
1694 1200 : BgpTable *RoutingInstance::VrfTableCreate(Address::Family vrf_family,
1695 : Address::Family vpn_family) {
1696 1200 : string table_name = GetTableName(name(), vrf_family);
1697 : BgpTable *table = static_cast<BgpTable *>(
1698 1200 : server_->database()->CreateTable(table_name));
1699 1200 : assert(table);
1700 :
1701 1200 : AddTable(table);
1702 1200 : RTINSTANCE_LOG_TABLE(Create, this, table, SandeshLevel::SYS_DEBUG,
1703 : RTINSTANCE_LOG_FLAG_ALL);
1704 1200 : RoutePathReplicator *replicator = server_->replicator(vpn_family);
1705 8400 : BOOST_FOREACH(RouteTarget rt, import_) {
1706 3600 : replicator->Join(table, rt, true);
1707 : }
1708 3600 : BOOST_FOREACH(RouteTarget rt, export_) {
1709 1200 : replicator->Join(table, rt, false);
1710 : }
1711 1200 : return table;
1712 1200 : }
1713 :
1714 3360 : void RoutingInstance::AddTable(BgpTable *tbl) {
1715 3360 : vrf_tables_by_name_.insert(make_pair(tbl->name(), tbl));
1716 3360 : vrf_tables_by_family_.insert(make_pair(tbl->family(), tbl));
1717 3360 : tbl->set_routing_instance(this);
1718 3360 : RoutingInstanceInfo info = GetDataCollection("Add");
1719 3360 : info.set_family(Address::FamilyToString(tbl->family()));
1720 3360 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1721 3360 : }
1722 :
1723 3360 : void RoutingInstance::RemoveTable(BgpTable *tbl) {
1724 3360 : RoutingInstanceInfo info = GetDataCollection("Remove");
1725 3360 : info.set_family(Address::FamilyToString(tbl->family()));
1726 3360 : vrf_tables_by_name_.erase(tbl->name());
1727 3360 : vrf_tables_by_family_.erase(tbl->family());
1728 3360 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
1729 3360 : }
1730 :
1731 : //
1732 : // Concurrency: BGP Config task
1733 : //
1734 : // Remove the table from the map and delete the table data structure
1735 : //
1736 3360 : void RoutingInstance::DestroyDBTable(DBTable *dbtable) {
1737 3360 : CHECK_CONCURRENCY("bgp::Config");
1738 :
1739 3360 : BgpTable *table = static_cast<BgpTable *>(dbtable);
1740 :
1741 3360 : RTINSTANCE_LOG_TABLE(Destroy, this, table,
1742 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
1743 :
1744 : // Remove this table from various data structures
1745 3360 : server_->database()->RemoveTable(table);
1746 3360 : RemoveTable(table);
1747 :
1748 : // Make sure that there are no routes left in this table
1749 3360 : assert(table->Size() == 0);
1750 :
1751 3360 : delete table;
1752 3360 : }
1753 :
1754 2400 : string RoutingInstance::GetTableName(string instance_name,
1755 : Address::Family fmly) {
1756 2400 : string table_name;
1757 2400 : if (instance_name == BgpConfigManager::kMasterInstance) {
1758 1200 : if ((fmly == Address::INET) || (fmly == Address::INET6)) {
1759 0 : table_name = Address::FamilyToTableString(fmly) + ".0";
1760 1200 : } else if (fmly == Address::INETMPLS) {
1761 0 : table_name = Address::FamilyToTableString(fmly) + ".3";
1762 : } else {
1763 1200 : table_name = "bgp." + Address::FamilyToTableString(fmly) + ".0";
1764 : }
1765 : } else {
1766 : table_name =
1767 1200 : instance_name + "." + Address::FamilyToTableString(fmly) + ".0";
1768 : }
1769 2400 : return table_name;
1770 0 : }
1771 :
1772 5432 : BgpTable *RoutingInstance::GetTable(Address::Family fmly) {
1773 5432 : RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
1774 5432 : return (loc != vrf_tables_by_family_.end() ? loc->second : NULL);
1775 : }
1776 :
1777 0 : const BgpTable *RoutingInstance::GetTable(Address::Family fmly) const {
1778 0 : RouteTableFamilyList::const_iterator loc = vrf_tables_by_family_.find(fmly);
1779 0 : 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 480 : void RoutingInstance::set_index(int index) {
1804 480 : index_ = index;
1805 480 : if (is_master_)
1806 240 : return;
1807 :
1808 240 : rd_.reset(new RouteDistinguisher(server_->bgp_identifier(), index));
1809 : }
1810 :
1811 7328 : RoutingInstanceInfo RoutingInstance::GetDataCollection(const char *operation) {
1812 14656 : RoutingInstanceInfo info;
1813 7328 : info.set_name(GetVirtualNetworkName());
1814 7328 : info.set_instance_name(name_);
1815 7328 : info.set_hostname(server_->localname());
1816 7328 : if (rd_.get()) info.set_route_distinguisher(rd_->ToString());
1817 7328 : if (operation) info.set_operation(operation);
1818 7328 : 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 0 : bool RoutingInstance::IsServiceChainRoute(const BgpRoute *route) const {
1843 0 : const BgpTable *table = route->table();
1844 0 : if (!table) {
1845 0 : return false;
1846 : }
1847 0 : const BgpInstanceConfig *rt_config = this->config();
1848 0 : if (!rt_config) {
1849 0 : return false;
1850 : }
1851 : SCAddress::Family sc_family =
1852 0 : SCAddress::AddressFamilyToSCFamily(table->family());
1853 : const ServiceChainConfig *sc_config =
1854 0 : rt_config->service_chain_info(sc_family);
1855 0 : if (!sc_config) {
1856 0 : 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 0 : bool RoutingInstance::ProcessRoutingPolicy(const BgpRoute *route,
1869 : BgpPath *path) const {
1870 0 : ExtCommunityPtr ext_community = path->GetOriginalAttr()->ext_community();
1871 0 : if (path->IsReplicated() &&
1872 0 : 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 0 : 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 0 : const RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr();
1890 : // Take snapshot of original attribute
1891 0 : BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
1892 0 : 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 0 : IPeer *peer = path->GetPeer();
1927 0 : if (peer) {
1928 0 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
1929 0 : server_->extcomm_db(), route->table());
1930 : }
1931 0 : BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr);
1932 0 : path->SetAttr(modified_attr, path->GetOriginalAttr());
1933 : // Clear the reject if marked so in past
1934 0 : if (path->IsPolicyReject()) path->ResetPolicyReject();
1935 0 : return true;
1936 0 : }
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 0 : bool RoutingInstance::IsContributingRoute(const BgpTable *table,
1993 : const BgpRoute *route) const {
1994 0 : 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 256 : PeerManager *RoutingInstance::LocatePeerManager() {
2017 256 : if (!peer_manager_)
2018 240 : peer_manager_.reset(BgpStaticObjectFactory::Create<PeerManager>(this));
2019 256 : 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 : }
|