Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include "bgp/bgp_table.h"
7 :
8 : #include <boost/foreach.hpp>
9 :
10 : #include "sandesh/sandesh_trace.h"
11 : #include "base/task_annotations.h"
12 : #include "bgp/bgp_log.h"
13 : #include "bgp/bgp_membership.h"
14 : #include "bgp/bgp_peer.h"
15 : #include "bgp/bgp_peer_types.h"
16 : #include "bgp/bgp_ribout.h"
17 : #include "bgp/bgp_ribout_updates.h"
18 : #include "bgp/bgp_route.h"
19 : #include "bgp/bgp_server.h"
20 : #include "bgp/bgp_update.h"
21 : #include "bgp/inet/inet_table.h"
22 : #include "bgp/routing-instance/iroute_aggregator.h"
23 : #include "bgp/routing-instance/path_resolver.h"
24 : #include "bgp/routing-instance/routing_instance.h"
25 : #include "bgp/routing-instance/rtarget_group_mgr.h"
26 : #include "bgp/tunnel_encap/tunnel_encap.h"
27 : #include "net/community_type.h"
28 :
29 : using std::make_pair;
30 : using std::string;
31 :
32 : class BgpTable::DeleteActor : public LifetimeActor {
33 : public:
34 288571 : explicit DeleteActor(BgpTable *table)
35 288571 : : LifetimeActor(table->rtinstance_->server()->lifetime_manager()),
36 288571 : table_(table) {
37 288596 : }
38 577194 : virtual ~DeleteActor() {
39 577194 : }
40 294964 : virtual bool MayDelete() const {
41 294964 : return table_->MayDelete();
42 : }
43 :
44 288597 : virtual void Shutdown() {
45 288597 : table_->Shutdown();
46 288597 : }
47 :
48 : // Make sure that all notifications have been processed and all db
49 : // state have been cleared for all partitions, before we inform the
50 : // parent instance that this table deletion process is complete.
51 288597 : virtual void Destroy() {
52 288597 : table_->rtinstance_->DestroyDBTable(table_);
53 288597 : }
54 :
55 : private:
56 : BgpTable *table_;
57 : };
58 :
59 296860 : BgpTable::BgpTable(DB *db, const string &name)
60 : : RouteTable(db, name),
61 296793 : rtinstance_(NULL),
62 296793 : path_resolver_(NULL),
63 296860 : instance_delete_ref_(this, NULL) {
64 296800 : primary_path_count_ = 0;
65 296963 : secondary_path_count_ = 0;
66 296964 : infeasible_path_count_ = 0;
67 296938 : stale_path_count_ = 0;
68 296963 : llgr_stale_path_count_ = 0;
69 296968 : }
70 :
71 : //
72 : // Remove the table from the instance dependents before attempting to
73 : // destroy the DeleteActor which can have its Delete() method be called
74 : // via the reference.
75 : //
76 296980 : BgpTable::~BgpTable() {
77 296980 : assert(path_resolver_ == NULL),
78 296980 : instance_delete_ref_.Reset(NULL);
79 296980 : }
80 :
81 288564 : void BgpTable::set_routing_instance(RoutingInstance *rtinstance) {
82 288564 : rtinstance_ = rtinstance;
83 288564 : assert(rtinstance);
84 288564 : deleter_.reset(new DeleteActor(this));
85 288582 : instance_delete_ref_.Reset(rtinstance->deleter());
86 288593 : }
87 :
88 3038184 : BgpServer *BgpTable::server() {
89 3038184 : return rtinstance_->server();
90 : }
91 :
92 1771205 : const BgpServer *BgpTable::server() const {
93 1771205 : return rtinstance_->server();
94 : }
95 :
96 : //
97 : // Find the RibOut for the given RibExportPolicy.
98 : //
99 60 : RibOut *BgpTable::RibOutFind(const RibExportPolicy &policy) {
100 60 : RibOutMap::iterator loc = ribout_map_.find(policy);
101 60 : return (loc != ribout_map_.end()) ? loc->second : NULL;
102 : }
103 :
104 : //
105 : // Find or create the RibOut associated with the given RibExportPolicy.
106 : // If a new RibOut is created, an entry for the pair gets added to the
107 : // RibOutMap.
108 : //
109 82956 : RibOut *BgpTable::RibOutLocate(BgpUpdateSender *sender,
110 : const RibExportPolicy &policy) {
111 82956 : RibOutMap::iterator loc = ribout_map_.find(policy);
112 82956 : if (loc == ribout_map_.end()) {
113 34968 : RibOut *ribout = new RibOut(this, sender, policy);
114 34968 : ribout_map_.insert(make_pair(policy, ribout));
115 34968 : return ribout;
116 : }
117 47988 : return loc->second;
118 : }
119 :
120 : //
121 : // Delete the entry corresponding to the given RibExportPolicy from the
122 : // RibOutMap. Also deletes the RibOut itself.
123 : //
124 34936 : void BgpTable::RibOutDelete(const RibExportPolicy &policy) {
125 34936 : RibOutMap::iterator loc = ribout_map_.find(policy);
126 34936 : assert(loc != ribout_map_.end());
127 34936 : delete loc->second;
128 34936 : ribout_map_.erase(loc);
129 34936 : }
130 :
131 : // If both as2 and as4 aggregators are present then we need to choose one
132 248789 : void BgpTable::CheckAggregatorAttr(BgpAttr *attr) const {
133 248789 : if (attr->aggregator_as_num() && attr->aggregator_as4_num()) {
134 32 : if (attr->aggregator_as_num() != AS_TRANS) {
135 : // If as2 aggregator is not as_trans then we ignore as4 aggregator
136 : // and ignore as4_path also
137 16 : attr->set_as4_path(NULL);
138 16 : attr->set_as4_aggregator(0, attr->aggregator_adderess());
139 : } else {
140 : // If as2 aggregator is as_trans then we use as4 aggregator
141 16 : attr->set_aggregator(attr->aggregator_as4_num(),
142 16 : attr->aggregator_adderess());
143 16 : attr->set_as4_aggregator(0, attr->aggregator_adderess());
144 : }
145 : }
146 248791 : }
147 :
148 204543 : void BgpTable::PrependLocalAs(const RibOut *ribout, BgpAttr *clone,
149 : const IPeer* peer) const {
150 204543 : CheckAggregatorAttr(clone);
151 204545 : as_t local_as = ribout->local_as() ?:
152 466 : clone->attr_db()->server()->local_autonomous_system();
153 204545 : if (!server()->enable_4byte_as())
154 204224 : return PrependAsToAsPath2Byte(clone, (as2_t)local_as);
155 316 : if (ribout->as4_supported()) {
156 121 : if (clone->aspath_4byte())
157 48 : PrependAsToAsPath4Byte(clone, local_as);
158 : else
159 73 : CreateAsPath4Byte(clone, local_as);
160 : } else {
161 195 : if (!clone->as_path())
162 47 : CreateAsPath2Byte(clone);
163 195 : PrependAsToAsPath2Byte(clone, local_as);
164 : }
165 : }
166 :
167 82 : void BgpTable::RemovePrivateAs(const RibOut *ribout, BgpAttr *attr) const {
168 82 : bool all = ribout->remove_private_all();
169 82 : bool replace = ribout->remove_private_replace();
170 82 : bool peer_loop_check = ribout->remove_private_peer_loop_check();
171 :
172 82 : const AsPathSpec &spec = attr->as_path()->path();
173 82 : as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;
174 82 : as_t replace_asn = 0;
175 82 : if (replace) {
176 56 : if (ribout->peer_type() == BgpProto::EBGP) {
177 32 : replace_asn = server()->local_autonomous_system();
178 : } else {
179 24 : replace_asn = spec.AsLeftMostPublic();
180 : }
181 : }
182 82 : if (replace_asn > AS2_MAX) {
183 8 : if (!attr->as4_path())
184 8 : CreateAs4Path(attr);
185 8 : const As4PathSpec &spec = attr->as4_path()->path();
186 8 : As4PathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
187 8 : attr->set_as4_path(new_spec);
188 8 : delete new_spec;
189 8 : replace_asn = AS_TRANS;
190 : }
191 82 : if (peer_asn > AS2_MAX)
192 8 : peer_asn = AS_TRANS;
193 :
194 82 : AsPathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
195 82 : attr->set_as_path(new_spec);
196 82 : delete new_spec;
197 82 : }
198 :
199 24 : void BgpTable::RemovePrivate4ByteAs(const RibOut *ribout, BgpAttr *attr) const {
200 24 : bool all = ribout->remove_private_all();
201 24 : bool replace = ribout->remove_private_replace();
202 24 : bool peer_loop_check = ribout->remove_private_peer_loop_check();
203 :
204 24 : const AsPath4ByteSpec &spec = attr->aspath_4byte()->path();
205 24 : as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;
206 24 : as_t replace_asn = 0;
207 24 : if (replace) {
208 16 : if (ribout->peer_type() == BgpProto::EBGP) {
209 16 : replace_asn = server()->local_autonomous_system();
210 : } else {
211 0 : replace_asn = spec.AsLeftMostPublic();
212 : }
213 : }
214 :
215 24 : AsPath4ByteSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
216 24 : attr->set_aspath_4byte(new_spec);
217 24 : delete new_spec;
218 24 : }
219 :
220 8 : void BgpTable::RemovePrivateAs4(const RibOut *ribout, BgpAttr *attr) const {
221 8 : bool all = ribout->remove_private_all();
222 8 : bool replace = ribout->remove_private_replace();
223 8 : bool peer_loop_check = ribout->remove_private_peer_loop_check();
224 :
225 8 : const As4PathSpec &spec = attr->as4_path()->path();
226 8 : as_t peer_asn = peer_loop_check ? ribout->peer_as() : 0;
227 8 : as_t replace_asn = 0;
228 8 : if (replace) {
229 8 : if (ribout->peer_type() == BgpProto::EBGP) {
230 8 : replace_asn = server()->local_autonomous_system();
231 : } else {
232 0 : replace_asn = spec.AsLeftMostPublic();
233 : }
234 : }
235 :
236 8 : As4PathSpec *new_spec = spec.RemovePrivate(all, replace_asn, peer_asn);
237 8 : attr->set_as4_path(new_spec);
238 8 : delete new_spec;
239 8 : }
240 :
241 : //
242 : // Process Remove Private information.
243 : //
244 248791 : void BgpTable::ProcessRemovePrivate(const RibOut *ribout, BgpAttr *attr) const {
245 248791 : if (!ribout->IsEncodingBgp())
246 0 : return;
247 248790 : if (!ribout->remove_private_enabled())
248 248674 : return;
249 :
250 110 : if (attr->as_path())
251 82 : RemovePrivateAs(ribout, attr);
252 110 : if (attr->aspath_4byte())
253 24 : RemovePrivate4ByteAs(ribout, attr);
254 110 : if (attr->as4_path())
255 8 : RemovePrivateAs4(ribout, attr);
256 : }
257 :
258 : //
259 : // Process Remove Private information.
260 : //
261 204545 : void BgpTable::ProcessAsOverride(const RibOut *ribout, BgpAttr *attr) const {
262 204545 : if (ribout->as_override() && !attr->IsAsPathEmpty()) {
263 52 : as_t replace_as = ribout->local_as() ?:
264 52 : attr->attr_db()->server()->local_autonomous_system();
265 52 : if (attr->as_path()) {
266 44 : const AsPathSpec &as_path = attr->as_path()->path();
267 : // If peer_as is > 0xffff, it can't be in as_path
268 44 : if (ribout->peer_as() <= AS2_MAX) {
269 44 : if (replace_as > AS2_MAX) {
270 : // if replace_as > 0xffff, as4_path should be created if
271 : // not already there by copying data from as_path
272 12 : if (!attr->as4_path()) {
273 12 : CreateAs4Path(attr);
274 : }
275 12 : replace_as = AS_TRANS;
276 : }
277 44 : AsPathSpec *as_path_ptr = as_path.Replace(
278 44 : ribout->peer_as(), replace_as);
279 44 : attr->set_as_path(as_path_ptr);
280 44 : delete as_path_ptr;
281 : }
282 44 : if (attr->as4_path()) {
283 12 : As4PathSpec *as_path_ptr = attr->as4_path()->path().Replace(
284 : ribout->peer_as(), replace_as);
285 12 : attr->set_as4_path(as_path_ptr);
286 12 : delete as_path_ptr;
287 : }
288 : }
289 52 : if (attr->aspath_4byte()) {
290 8 : const AsPath4ByteSpec &as_path = attr->aspath_4byte()->path();
291 : AsPath4ByteSpec *as_path_ptr =
292 8 : as_path.Replace(ribout->peer_as(), replace_as);
293 8 : attr->set_aspath_4byte(as_path_ptr);
294 8 : delete as_path_ptr;
295 : }
296 : }
297 204546 : }
298 :
299 : //
300 : // Process Long Lived Graceful Restart state information.
301 : //
302 : // For LLGR_STALE paths, if the peer supports LLGR then attach LLGR_STALE
303 : // community. Otherwise, strip LLGR_STALE community, reduce LOCAL_PREF and
304 : // attach NO_EXPORT community instead.
305 : //
306 248811 : void BgpTable::ProcessLlgrState(const RibOut *ribout, const BgpPath *path,
307 : BgpAttr *attr, bool llgr_stale_comm) {
308 248811 : if (!server() || !server()->comm_db())
309 0 : return;
310 :
311 : // Skip LLGR specific attributes manipulation for rtarget routes.
312 248812 : if (family() == Address::RTARGET)
313 54352 : return;
314 :
315 : // If the path is not marked as llgr_stale or if it does not have the
316 : // LLGR_STALE community, then no action is necessary.
317 194459 : if (!path->IsLlgrStale() && !llgr_stale_comm)
318 188786 : return;
319 :
320 : // If peers support LLGR, then attach LLGR_STALE community and return.
321 5673 : if (ribout->llgr()) {
322 5661 : if (!llgr_stale_comm) {
323 : CommunityPtr comm = server()->comm_db()->AppendAndLocate(
324 5653 : attr->community(), CommunityType::LlgrStale);
325 5653 : attr->set_community(comm);
326 5653 : }
327 5661 : return;
328 : }
329 :
330 : // Peers do not understand LLGR. Bring down local preference instead to
331 : // make the advertised path less preferred.
332 12 : attr->set_local_pref(0);
333 :
334 : // Remove LLGR_STALE community as the peers do not support LLGR.
335 12 : if (llgr_stale_comm) {
336 : CommunityPtr comm = server()->comm_db()->RemoveAndLocate(
337 8 : attr->community(), CommunityType::LlgrStale);
338 8 : attr->set_community(comm);
339 8 : }
340 :
341 : // Attach NO_EXPORT community as well to make sure that this path does not
342 : // exits local AS, unless it is already present.
343 20 : if (!attr->community() ||
344 8 : !attr->community()->ContainsValue(CommunityType::NoExport)) {
345 : CommunityPtr comm = server()->comm_db()->AppendAndLocate(
346 12 : attr->community(), CommunityType::NoExport);
347 12 : attr->set_community(comm);
348 12 : }
349 : }
350 :
351 248810 : void BgpTable::ProcessDefaultTunnelEncapsulation(const RibOut *ribout,
352 : ExtCommunityDB *extcomm_db, BgpAttr *attr) const {
353 248810 : if (!ribout->ExportPolicy().default_tunnel_encap_list.empty()) {
354 8 : ExtCommunity::ExtCommunityList encap_list;
355 30 : BOOST_FOREACH(const string &encap_string,
356 : ribout->ExportPolicy().default_tunnel_encap_list) {
357 11 : TunnelEncap tunnel_encap(encap_string);
358 11 : encap_list.push_back(tunnel_encap.GetExtCommunity());
359 : }
360 8 : ExtCommunityPtr ext_community = attr->ext_community();
361 : ext_community =
362 16 : extcomm_db->ReplaceTunnelEncapsulationAndLocate(
363 8 : ext_community.get(), encap_list);
364 8 : attr->set_ext_community(ext_community);
365 8 : }
366 248810 : }
367 :
368 204417 : void BgpTable::PrependAsToAsPath2Byte(BgpAttr *attr, as2_t asn) const {
369 204417 : if (attr->as_path()) {
370 71963 : const AsPathSpec &as_path = attr->as_path()->path();
371 71965 : AsPathSpec *as_path_ptr = as_path.Add(asn);
372 71950 : attr->set_as_path(as_path_ptr);
373 71966 : delete as_path_ptr;
374 : } else {
375 132456 : AsPathSpec as_path;
376 132471 : AsPathSpec *as_path_ptr = as_path.Add(asn);
377 132425 : attr->set_as_path(as_path_ptr);
378 132481 : delete as_path_ptr;
379 132481 : }
380 204447 : }
381 :
382 195 : void BgpTable::PrependAsToAsPath2Byte(BgpAttr *attr, as_t asn) const {
383 195 : if (asn <= AS2_MAX) {
384 111 : if (attr->as_path() && attr->as4_path()) {
385 27 : PrependAsToAs4Path(attr, asn);
386 : }
387 111 : return PrependAsToAsPath2Byte(attr, static_cast<as2_t>(asn & AS2_MAX));
388 : }
389 84 : if (attr->as_path() && !attr->as4_path()) {
390 46 : CreateAs4Path(attr);
391 46 : assert(attr->as_path()->path().path_segments.size() ==
392 : attr->as4_path()->path().path_segments.size());
393 : }
394 84 : as2_t as_trans = AS_TRANS;
395 84 : PrependAsToAsPath2Byte(attr, as_trans);
396 84 : PrependAsToAs4Path(attr, asn);
397 : }
398 :
399 48 : void BgpTable::PrependAsToAsPath4Byte(BgpAttr *clone, as_t asn) const {
400 48 : if (clone->aspath_4byte()) {
401 48 : const AsPath4ByteSpec &as4_path = clone->aspath_4byte()->path();
402 48 : AsPath4ByteSpec *as4_path_ptr = as4_path.Add(asn);
403 48 : clone->set_aspath_4byte(as4_path_ptr);
404 48 : delete as4_path_ptr;
405 : } else {
406 0 : AsPath4ByteSpec as_path;
407 0 : AsPath4ByteSpec *as_path_ptr = as_path.Add(asn);
408 0 : clone->set_aspath_4byte(as_path_ptr);
409 0 : delete as_path_ptr;
410 0 : }
411 48 : }
412 :
413 111 : void BgpTable::PrependAsToAs4Path(BgpAttr* attr, as_t asn) const {
414 111 : if (attr->as4_path()) {
415 111 : const As4PathSpec &as4_path = attr->as4_path()->path();
416 111 : As4PathSpec *as4_path_ptr = as4_path.Add(asn);
417 111 : attr->set_as4_path(as4_path_ptr);
418 111 : delete as4_path_ptr;
419 : } else {
420 0 : As4PathSpec as_path;
421 0 : As4PathSpec *as_path_ptr = as_path.Add(asn);
422 0 : attr->set_as4_path(as_path_ptr);
423 0 : delete as_path_ptr;
424 0 : }
425 111 : }
426 :
427 : // Create as4_path by copying data from as_path
428 66 : void BgpTable::CreateAs4Path(BgpAttr *attr) const {
429 66 : if (!attr->as_path()) {
430 0 : return;
431 : }
432 :
433 66 : std::unique_ptr<As4PathSpec> new_as_path(new As4PathSpec);
434 66 : const AsPathSpec &as_path = attr->as_path()->path();
435 107 : for (size_t i = 0; i < as_path.path_segments.size(); i++) {
436 41 : As4PathSpec::PathSegment *ps4 = new As4PathSpec::PathSegment;
437 41 : AsPathSpec::PathSegment *ps = as_path.path_segments[i];
438 41 : ps4->path_segment_type = ps->path_segment_type;
439 108 : for (size_t j = 0; j < ps->path_segment.size(); j++) {
440 67 : as_t as = ps->path_segment[j];
441 67 : ps4->path_segment.push_back(as);
442 : }
443 41 : new_as_path->path_segments.push_back(ps4);
444 : }
445 66 : attr->set_as4_path(new_as_path.get());
446 66 : }
447 :
448 : // Check if aspath_4byte has any asn > 0xFFFF
449 63 : bool BgpTable::Has4ByteAsn(BgpAttr *attr) const {
450 63 : if (!attr->aspath_4byte())
451 12 : return false;
452 51 : const AsPath4ByteSpec &as_path4 = attr->aspath_4byte()->path();
453 71 : for (size_t i = 0; i < as_path4.path_segments.size(); ++i) {
454 51 : AsPath4ByteSpec::PathSegment *ps4 = as_path4.path_segments[i];
455 71 : for (size_t j = 0; j < ps4->path_segment.size(); ++j) {
456 51 : if (ps4->path_segment[j] > AS2_MAX)
457 31 : return true;
458 : }
459 : }
460 20 : return false;
461 : }
462 :
463 : // Create as_path (and as4_path) from as_path4byte
464 63 : void BgpTable::CreateAsPath2Byte(BgpAttr *attr) const {
465 63 : std::unique_ptr<AsPathSpec> new_as_path(new AsPathSpec);
466 63 : As4PathSpec *new_as4_path = NULL;
467 63 : bool has_4byte_asn = Has4ByteAsn(attr);
468 63 : if (has_4byte_asn)
469 31 : new_as4_path = new As4PathSpec;
470 63 : if (attr->aspath_4byte()) {
471 51 : const AsPath4ByteSpec &as_path4 = attr->aspath_4byte()->path();
472 118 : for (size_t i = 0; i < as_path4.path_segments.size(); i++) {
473 67 : AsPathSpec::PathSegment *ps = new AsPathSpec::PathSegment;
474 67 : As4PathSpec::PathSegment *as4_ps = NULL;
475 67 : AsPath4ByteSpec::PathSegment *ps4 = as_path4.path_segments[i];
476 67 : ps->path_segment_type = ps4->path_segment_type;
477 67 : if (has_4byte_asn) {
478 47 : as4_ps = new As4PathSpec::PathSegment;
479 47 : as4_ps->path_segment_type = ps4->path_segment_type;
480 : }
481 180 : for (size_t j = 0; j < ps4->path_segment.size(); ++j) {
482 113 : as_t as4 = ps4->path_segment[j];
483 113 : if (as4 > AS2_MAX) {
484 69 : as2_t as_trans = AS_TRANS;
485 69 : ps->path_segment.push_back(as_trans);
486 : } else {
487 44 : ps->path_segment.push_back(static_cast<as2_t>(
488 : as4 & AS2_MAX));
489 : }
490 113 : if (has_4byte_asn)
491 93 : as4_ps->path_segment.push_back(as4);
492 : }
493 67 : new_as_path->path_segments.push_back(ps);
494 67 : if (has_4byte_asn)
495 47 : new_as4_path->path_segments.push_back(as4_ps);
496 : }
497 51 : attr->set_aspath_4byte(NULL);
498 : }
499 63 : attr->set_as_path(new_as_path.get());
500 63 : if (has_4byte_asn) {
501 31 : attr->set_as4_path(new_as4_path);
502 31 : delete new_as4_path;
503 : }
504 63 : }
505 :
506 : // Create aspath_4byte by merging as_path and as4_path
507 77 : void BgpTable::CreateAsPath4Byte(BgpAttr *attr, as_t local_as) const {
508 77 : int as2_count = attr->as_path_count();
509 77 : int as4_count = attr->as4_path_count();
510 77 : if (as2_count < as4_count) {
511 8 : as4_count = 0;
512 8 : attr->set_as4_path(NULL);
513 : }
514 77 : AsPath4ByteSpec::PathSegment *ps4 = NULL;
515 77 : bool part_segment = false;
516 77 : std::unique_ptr <AsPath4ByteSpec> aspath_4byte(new AsPath4ByteSpec);
517 77 : if (attr->as_path()) {
518 32 : const AsPathSpec &as_path = attr->as_path()->path();
519 32 : int new_as_count = 0;
520 86 : for (size_t i = 0; i < as_path.path_segments.size() &&
521 32 : new_as_count < (as2_count - as4_count) ; ++i) {
522 30 : ps4 = new AsPath4ByteSpec::PathSegment;
523 30 : AsPathSpec::PathSegment *ps = as_path.path_segments[i];
524 30 : ps4->path_segment_type = ps->path_segment_type;
525 30 : if (ps->path_segment_type == AsPathSpec::PathSegment::AS_SET) {
526 0 : new_as_count++;
527 0 : for (size_t j = 0; j < ps->path_segment.size(); ++j) {
528 0 : as2_t as = ps->path_segment[j];
529 0 : ps4->path_segment.push_back(as);
530 : }
531 : } else {
532 130 : for (size_t j = 0; j < ps->path_segment.size() &&
533 54 : new_as_count < (as2_count - as4_count); ++j) {
534 46 : new_as_count++;
535 46 : as2_t as = ps->path_segment[j];
536 46 : ps4->path_segment.push_back(as);
537 : }
538 30 : if (new_as_count == (as2_count - as4_count)) {
539 30 : if (attr->as4_path()) {
540 8 : part_segment = true;
541 8 : break;
542 : }
543 : }
544 : }
545 22 : aspath_4byte->path_segments.push_back(ps4);
546 : }
547 32 : if (attr->as4_path()) {
548 10 : const As4PathSpec &as4_path = attr->as4_path()->path();
549 20 : for (size_t i = 0; i < as4_path.path_segments.size(); ++i) {
550 10 : if (!part_segment) {
551 2 : ps4 = new AsPath4ByteSpec::PathSegment;
552 : }
553 10 : part_segment = false;
554 10 : As4PathSpec::PathSegment *ps = as4_path.path_segments[i];
555 10 : ps4->path_segment_type = ps->path_segment_type;
556 10 : if (ps->path_segment_type == As4PathSpec::PathSegment::AS_SET) {
557 0 : new_as_count++;
558 0 : for (size_t j = 0; j < ps->path_segment.size(); ++j) {
559 0 : as2_t as = ps->path_segment[j];
560 0 : ps4->path_segment.push_back(as);
561 : }
562 : } else {
563 40 : for (size_t j = 0; j < ps->path_segment.size(); ++j) {
564 30 : as_t as = ps->path_segment[j];
565 30 : ps4->path_segment.push_back(as);
566 : }
567 : }
568 10 : aspath_4byte->path_segments.push_back(ps4);
569 : }
570 10 : attr->set_as4_path(NULL);
571 : }
572 32 : attr->set_as_path(NULL);
573 : }
574 77 : if (local_as) {
575 73 : std::unique_ptr<AsPath4ByteSpec> as_path_spec(aspath_4byte->Add(local_as));
576 73 : attr->set_aspath_4byte(as_path_spec.get());
577 73 : } else {
578 4 : attr->set_aspath_4byte(aspath_4byte.get());
579 : }
580 77 : }
581 :
582 898444 : UpdateInfo *BgpTable::GetUpdateInfo(RibOut *ribout, BgpRoute *route,
583 : const RibPeerSet &peerset) {
584 898444 : const BgpPath *path = route->BestPath();
585 :
586 : // Ignore if there is no best-path.
587 898512 : if (!path)
588 16 : return NULL;
589 :
590 : // Don't advertise infeasible paths.
591 898496 : if (!path->IsFeasible())
592 3043 : return NULL;
593 :
594 : // Check whether the route is contributing route
595 895440 : if (IsRouteAggregationSupported() && IsContributingRoute(route))
596 7 : return NULL;
597 :
598 : // Needs to be outside the if block so it's not destroyed prematurely.
599 895369 : BgpAttrPtr attr_ptr;
600 895369 : const BgpAttr *attr = path->GetAttr();
601 :
602 895386 : RibPeerSet new_peerset = peerset;
603 :
604 : // LocalPref, Med and AsPath manipulation is needed only if the RibOut
605 : // has BGP encoding. Similarly, well-known communities do not apply if
606 : // the encoding is not BGP.
607 895283 : if (ribout->IsEncodingBgp()) {
608 : // Handle well-known communities.
609 449572 : if (attr->community() != NULL &&
610 6865 : attr->community()->communities().size()) {
611 20439 : BOOST_FOREACH(uint32_t value, attr->community()->communities()) {
612 6887 : if (value == CommunityType::NoAdvertise)
613 99 : return NULL;
614 :
615 11134 : if ((ribout->peer_type() == BgpProto::EBGP) &&
616 4303 : ((value == CommunityType::NoExport) ||
617 : (value == CommunityType::NoExportSubconfed))) {
618 43 : return NULL;
619 : }
620 : }
621 : }
622 :
623 442616 : const IPeer *peer = path->GetPeer();
624 442609 : BgpAttr *clone = NULL;
625 449372 : bool llgr_stale_comm = attr->community() &&
626 6764 : attr->community()->ContainsValue(CommunityType::LlgrStale);
627 442608 : if (ribout->peer_type() == BgpProto::IBGP) {
628 : // Split horizon check.
629 86648 : if (peer && peer->CheckSplitHorizon(server()->cluster_id(),
630 : ribout->cluster_id()))
631 37534 : return NULL;
632 :
633 : // Handle route-target filtering.
634 49123 : if (IsVpnTable() && attr->ext_community() != NULL) {
635 23634 : server()->rtarget_group_mgr()->GetRibOutInterestedPeers(
636 : ribout, attr->ext_community(), peerset, &new_peerset);
637 23640 : if (new_peerset.empty())
638 4883 : return NULL;
639 : }
640 :
641 44242 : if (server()->cluster_id()) {
642 : // Check if there is a loop in cluster_list
643 8 : if (attr->cluster_list() && attr->cluster_list()->cluster_list()
644 0 : .ClusterListLoop(server()->cluster_id())) {
645 0 : return NULL;
646 : }
647 : }
648 :
649 44241 : if (server()->cluster_id() && (family() != Address::RTARGET)) {
650 : // route reflector should not reflect the route back to the peer
651 : // from which it received that route, for non rtarget routes
652 : // This is done by checking peer_router_id of all the feasible
653 : // paths of this route
654 8 : RibPeerSet route_peerset;
655 16 : for (Route::PathList::iterator it= route->GetPathList().begin();
656 32 : it != route->GetPathList().end(); it++) {
657 8 : BgpPath *ipath = static_cast<BgpPath *>(it.operator->());
658 8 : if (ipath->IsFeasible() && ipath->GetPeer()) {
659 8 : const IPeer *ipeer = ipath->GetPeer();
660 8 : const BgpPeer *bgp_peer = dynamic_cast<
661 8 : const BgpPeer *>(ipeer);
662 8 : if (bgp_peer)
663 2 : route_peerset.set(bgp_peer->GetIndex());
664 : }
665 : }
666 8 : RibOut::PeerIterator iter(ribout, new_peerset);
667 30 : while (iter.HasNext()) {
668 22 : int current_index = iter.index();
669 22 : IPeerUpdate *peer = iter.Next();
670 22 : const BgpPeer *bgp_peer = dynamic_cast<
671 22 : const BgpPeer *>(peer);
672 22 : if (bgp_peer && route_peerset.test(bgp_peer->GetIndex()))
673 2 : new_peerset.reset(current_index);
674 : }
675 8 : if (new_peerset.empty())
676 0 : return NULL;
677 8 : }
678 :
679 44240 : clone = new BgpAttr(*attr);
680 :
681 : // Retain LocalPref value if set, else set default to 100.
682 44249 : if (clone->local_pref() == 0)
683 0 : clone->set_local_pref(100);
684 :
685 : // Check aggregator attributes to identify which ones to be used
686 44249 : CheckAggregatorAttr(clone);
687 :
688 : // Should not normally be needed for iBGP, but there could be
689 : // complex configurations where this is useful.
690 44247 : ProcessRemovePrivate(ribout, clone);
691 :
692 : // Add Originator_Id if acting as route reflector and cluster_id
693 : // is not present
694 44244 : if (server()->cluster_id()) {
695 8 : if (clone->originator_id().is_unspecified()) {
696 8 : if (peer && (peer->bgp_identifier() != 0)) {
697 2 : clone->set_originator_id(Ip4Address(
698 2 : peer->bgp_identifier()));
699 : } else {
700 6 : clone->set_originator_id(Ip4Address(
701 : server()->bgp_identifier()));
702 : }
703 : }
704 8 : if (attr->cluster_list()) {
705 : const ClusterListSpec &cluster =
706 0 : clone->cluster_list()->cluster_list();
707 : ClusterListSpec *cl_ptr = new ClusterListSpec(
708 0 : server()->cluster_id(), &cluster);
709 0 : clone->set_cluster_list(cl_ptr);
710 0 : delete cl_ptr;
711 : } else {
712 : ClusterListSpec *cl_ptr = new ClusterListSpec(
713 8 : server()->cluster_id(), NULL);
714 8 : clone->set_cluster_list(cl_ptr);
715 8 : delete cl_ptr;
716 : }
717 : }
718 : // If the route is locally originated i.e. there's no AsPath,
719 : // then generate a Nil AsPath i.e. one with 0 length. No need
720 : // to modify the AsPath if it already exists since this is an
721 : // iBGP RibOut.
722 44243 : if (ribout->as4_supported() && !clone->aspath_4byte()) {
723 53 : if (attr->as_path()) {
724 4 : CreateAsPath4Byte(clone, 0);
725 : } else {
726 49 : AsPath4ByteSpec as_path;
727 49 : clone->set_aspath_4byte(&as_path);
728 49 : }
729 : }
730 44241 : if (!ribout->as4_supported() && !clone->as_path()) {
731 40362 : if (attr->aspath_4byte()) {
732 16 : CreateAsPath2Byte(clone);
733 : } else {
734 40346 : AsPathSpec as_path;
735 40342 : clone->set_as_path(&as_path);
736 40347 : }
737 : }
738 355949 : } else if (ribout->peer_type() == BgpProto::EBGP) {
739 : // Don't advertise routes from non-master instances if there's
740 : // no nexthop. The ribout has to be for bgpaas-clients because
741 : // that's the only case with bgp peers in non-master instance.
742 358429 : if (!rtinstance_->IsMasterRoutingInstance() &&
743 2488 : ribout->nexthop().is_unspecified()) {
744 0 : return NULL;
745 : }
746 :
747 : // Handle route-target filtering.
748 355937 : if (IsVpnTable() && attr->ext_community() != NULL) {
749 298303 : server()->rtarget_group_mgr()->GetRibOutInterestedPeers(
750 : ribout, attr->ext_community(), peerset, &new_peerset);
751 298545 : if (new_peerset.empty())
752 15216 : return NULL;
753 : }
754 :
755 : // Sender side AS path loop check and split horizon within RibOut.
756 340955 : if (!ribout->as_override()) {
757 340893 : if (attr->IsAsPathLoop(ribout->peer_as()))
758 136404 : return NULL;
759 : } else {
760 60 : if (peer && peer->PeerType() == BgpProto::EBGP) {
761 40 : ribout->GetSubsetPeerSet(&new_peerset, peer);
762 40 : if (new_peerset.empty())
763 0 : return NULL;
764 : }
765 : }
766 :
767 204539 : clone = new BgpAttr(*attr);
768 :
769 : // Remove non-transitive attributes.
770 : // Note that med is handled further down.
771 204565 : clone->set_originator_id(Ip4Address());
772 204562 : clone->set_cluster_list(NULL);
773 :
774 : // Update nexthop.
775 204557 : if (!ribout->nexthop().is_unspecified())
776 1612 : clone->set_nexthop(ribout->nexthop());
777 :
778 : // Reset LocalPref.
779 204555 : if (clone->local_pref())
780 204554 : clone->set_local_pref(0);
781 :
782 : // Reset Med if the path did not originate from an xmpp peer.
783 : // The AS path is NULL if the originating xmpp peer is locally
784 : // connected. It's non-NULL but empty if the originating xmpp
785 : // peer is connected to another bgp speaker in the iBGP mesh.
786 204551 : if (clone->med() && !clone->IsAsPathEmpty())
787 366 : clone->set_med(0);
788 :
789 : // Override the peer AS with local AS in AsPath.
790 204547 : ProcessAsOverride(ribout, clone);
791 :
792 : // Remove private processing must happen before local AS prepend.
793 204544 : ProcessRemovePrivate(ribout, clone);
794 :
795 : // Prepend the local AS to AsPath.
796 204541 : PrependLocalAs(ribout, clone, peer);
797 : }
798 :
799 248812 : assert(clone);
800 :
801 : // Update with the Default tunnel Encapsulation ordered List if
802 : // configured on the peer.
803 : // Note that all peers with the same list share the same Ribout, this is
804 : // ensured by making the Default Encapsulation List part of the Rib
805 : // Export policy.Note that, if there is Default Tunnel Encapsulation
806 : // configuration any tunnel encapsulation present is removed.
807 248812 : ProcessDefaultTunnelEncapsulation(ribout, server()->extcomm_db(),
808 : clone);
809 :
810 248810 : ProcessLlgrState(ribout, path, clone, llgr_stale_comm);
811 :
812 : // Locate the new BgpAttrPtr.
813 248811 : attr_ptr = clone->attr_db()->Locate(clone);
814 248815 : attr = attr_ptr.get();
815 : }
816 :
817 701382 : UpdateInfo *uinfo = new UpdateInfo;
818 701489 : uinfo->target = new_peerset;
819 701492 : uinfo->roattr = RibOutAttr(route, attr, ribout->IsEncodingXmpp());
820 701759 : return uinfo;
821 895895 : }
822 :
823 : // Bgp Path selection..
824 : // Based Attribute weight
825 1808436 : bool BgpTable::PathSelection(const Path &path1, const Path &path2) {
826 1808436 : const BgpPath &l_path = dynamic_cast<const BgpPath &> (path1);
827 1808436 : const BgpPath &r_path = dynamic_cast<const BgpPath &> (path2);
828 :
829 : // Check the weight of Path
830 1808436 : bool res = l_path.PathCompare(r_path, false) < 0;
831 :
832 1808434 : return res;
833 : }
834 :
835 30 : bool BgpTable::DeletePath(DBTablePartBase *root, BgpRoute *rt, BgpPath *path) {
836 60 : return InputCommon(root, rt, path, path->GetPeer(), NULL,
837 60 : DBRequest::DB_ENTRY_DELETE, NULL, path->GetPathId(), 0, 0, 0);
838 : }
839 :
840 538864 : bool BgpTable::InputCommon(DBTablePartBase *root, BgpRoute *rt, BgpPath *path,
841 : const IPeer *peer, DBRequest *req,
842 : DBRequest::DBOperation oper, BgpAttrPtr attrs,
843 : uint32_t path_id, uint32_t flags, uint32_t label,
844 : uint32_t l3_label) {
845 538864 : bool notify_rt = false;
846 :
847 538864 : switch (oper) {
848 287999 : case DBRequest::DB_ENTRY_ADD_CHANGE: {
849 287999 : assert(rt);
850 :
851 : // The entry may currently be marked as deleted.
852 287999 : rt->ClearDelete();
853 287991 : if (peer)
854 243937 : peer->UpdateCloseRouteStats(family(), path, flags);
855 :
856 : // Check whether peer already has a path.
857 287979 : if (path != NULL) {
858 57385 : if ((path->GetAttr() != attrs.get()) ||
859 22628 : (path->GetFlags() != flags) ||
860 59673 : (path->GetLabel() != label) ||
861 2176 : (path->GetL3Label() != l3_label)) {
862 : // Update Attributes and notify (if needed)
863 34876 : if (path->NeedsResolution())
864 1311 : path_resolver_->StopPathResolution(root->index(), path);
865 34876 : rt->DeletePath(path);
866 : } else {
867 : // Ignore duplicate update.
868 2169 : break;
869 : }
870 : }
871 :
872 : BgpPath *new_path;
873 571647 : new_path = new BgpPath(
874 285836 : peer, path_id, BgpPath::BGP_XMPP, attrs, flags, label, l3_label);
875 :
876 : // Start path resolution for the new path if
877 : // (1) Path flag has ResolveNextHop set in which case the path will
878 : // be resolved in the overlay routing table (or)
879 : // (2) Fast convergence knob is enabled in which case the path will
880 : // be marked for resolution in the underlay (default) routing table
881 : // (3) Path resolution in this case is needed only for routes
882 : // in the VRF routing tables and for INET, INET6 and EVPN
883 : // address families.
884 285839 : bool fc_family = false;
885 518512 : if (family() == Address::INET || family() == Address::INET6 ||
886 232669 : family() == Address::EVPN) {
887 99882 : fc_family = true;
888 : }
889 285813 : bool fc_enabled = (server()->IsNextHopCheckEnabled() &&
890 285788 : !rtinstance_->IsMasterRoutingInstance() && fc_family);
891 285788 : if (new_path->NeedsResolution() || fc_enabled) {
892 2860 : if (peer && !(peer->IsXmppPeer()) ) {
893 2735 : rt->add_peer_sources(peer->ToString());
894 : }
895 2860 : Address::Family family = new_path->GetAttr()->nexthop_family();
896 : BgpTable *table;
897 2860 : if (new_path->NeedsResolution()) {
898 2754 : table = rtinstance_->GetTable(family);
899 : } else {
900 : // Fast convergence knob is enabled.
901 : // Update path flag to indicate need for resolution.
902 106 : new_path->SetResolveNextHop();
903 :
904 : // Get the default table.
905 106 : RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
906 106 : assert(mgr);
907 106 : RoutingInstance *master_ri = mgr->GetDefaultRoutingInstance();
908 106 : assert(master_ri);
909 106 : table = master_ri->GetTable(family);
910 : }
911 2859 : path_resolver_->StartPathResolution(rt, new_path, table);
912 : }
913 :
914 285781 : rt->InsertPath(new_path);
915 285821 : notify_rt = true;
916 285821 : break;
917 : }
918 :
919 250866 : case DBRequest::DB_ENTRY_DELETE: {
920 250866 : if (rt && !rt->IsDeleted()) {
921 250859 : if (peer && !(peer->IsXmppPeer()) ) {
922 154102 : rt->del_peer_sources(peer->ToString());
923 : }
924 273193 : BGP_LOG_ROUTE(this, const_cast<IPeer *>(peer), rt,
925 : "Delete BGP path");
926 :
927 : // Remove the Path from the route
928 250864 : if (path->NeedsResolution())
929 1549 : path_resolver_->StopPathResolution(root->index(), path);
930 250865 : rt->DeletePath(path);
931 250913 : notify_rt = true;
932 : }
933 250917 : break;
934 : }
935 :
936 0 : default: {
937 0 : assert(false);
938 : break;
939 : }
940 : }
941 538907 : return notify_rt;
942 : }
943 :
944 466824 : void BgpTable::Input(DBTablePartition *root, DBClient *client,
945 : DBRequest *req) {
946 466824 : const IPeer *peer = (static_cast<RequestKey *>(req->key.get()))->GetPeer();
947 466762 : RequestData *data = static_cast<RequestData *>(req->data.get());
948 :
949 466716 : if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE && peer) {
950 : // Skip if this peer is down.
951 239351 : if (!peer->IsReady())
952 22295 : return;
953 :
954 : // For xmpp peers, verify that agent is subscribed to the table and
955 : // the route add is from the same incarnation of table subscription.
956 229231 : if (peer->IsXmppPeer() && peer->IsRegistrationRequired()) {
957 59151 : BgpMembershipManager *mgr = rtinstance_->server()->membership_mgr();
958 59151 : int instance_id = -1;
959 59151 : uint64_t subscription_gen_id = 0;
960 : bool is_registered =
961 59151 : mgr->GetRegistrationInfo(const_cast<IPeer *>(peer), this,
962 : &instance_id, &subscription_gen_id);
963 86177 : if ((!is_registered && (family() != Address::RTARGET)) ||
964 27026 : (is_registered &&
965 27026 : (subscription_gen_id != data->subscription_gen_id()))) {
966 3 : return;
967 : }
968 : }
969 : }
970 :
971 : // Create route if it's not already present in case of add/change.
972 456591 : BgpRoute *rt = TableFind(root, req->key.get());
973 456600 : if (!rt) {
974 224298 : if ((req->oper == DBRequest::DB_ENTRY_DELETE) ||
975 213128 : (req->oper == DBRequest::DB_ENTRY_NOTIFY))
976 11545 : return;
977 :
978 212753 : rt = static_cast<BgpRoute *>(Add(req));
979 212708 : static_cast<DBTablePartition *>(root)->Add(rt);
980 230532 : BGP_LOG_ROUTE(this, const_cast<IPeer *>(peer), rt,
981 : "Insert new BGP path");
982 : }
983 :
984 445086 : if (req->oper == DBRequest::DB_ENTRY_NOTIFY) {
985 419 : root->Notify(rt);
986 419 : return;
987 : }
988 :
989 444667 : uint32_t path_id = 0;
990 444667 : uint32_t flags = 0;
991 444667 : uint32_t label = 0;
992 444667 : uint32_t l3_label = 0;
993 444667 : BgpPath *path = rt->FindPath(peer);
994 444718 : BgpAttrPtr attr = data ? data->attrs() : NULL;
995 444733 : if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
996 273294 : assert(data);
997 273294 : const RequestData::NextHop &nexthop = data->nexthop();
998 273291 : if (nexthop.address_.is_v4())
999 268750 : path_id = nexthop.address_.to_v4().to_ulong();
1000 273276 : flags = nexthop.flags_;
1001 273276 : label = nexthop.label_;
1002 273276 : l3_label = nexthop.l3_label_;
1003 :
1004 273276 : attr = GetAttributes(rt, attr, peer);
1005 : } else {
1006 171439 : if (!path)
1007 203 : return;
1008 171236 : path_id = path->GetPathId();
1009 : }
1010 :
1011 444513 : bool notify_rt = InputCommon(root, rt, path, peer, req, req->oper,
1012 : attr, path_id, flags, label, l3_label);
1013 444545 : InputCommonPostProcess(root, rt, notify_rt);
1014 444688 : }
1015 :
1016 931293 : void BgpTable::InputCommonPostProcess(DBTablePartBase *root,
1017 : BgpRoute *rt, bool notify_rt) {
1018 931293 : if (!notify_rt)
1019 394975 : return;
1020 :
1021 536318 : if (rt->front() == NULL)
1022 213107 : root->Delete(rt);
1023 : else
1024 323158 : root->Notify(rt);
1025 : }
1026 :
1027 294964 : bool BgpTable::MayDelete() const {
1028 294964 : CHECK_CONCURRENCY("bgp::Config");
1029 :
1030 : // Bail if the table has listeners.
1031 294964 : if (HasListeners()) {
1032 6351 : BGP_LOG_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
1033 : "Paused table deletion due to pending listeners");
1034 6351 : return false;
1035 : }
1036 :
1037 : // Bail if the table has walkers.
1038 288613 : if (HasWalkers()) {
1039 0 : BGP_LOG_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
1040 : "Paused table deletion due to pending walkers");
1041 0 : return false;
1042 : }
1043 :
1044 : // Bail if the table is not empty.
1045 288613 : size_t size = Size();
1046 288613 : if (size > 0) {
1047 16 : BGP_LOG_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
1048 : "Paused table deletion due to " << size <<
1049 : " pending routes");
1050 16 : return false;
1051 : }
1052 :
1053 : // Check the base class at the end so that we add custom checks
1054 : // before this if needed and to get more informative log message.
1055 288597 : if (!DBTableBase::MayDelete())
1056 0 : return false;
1057 :
1058 288597 : return true;
1059 : }
1060 :
1061 288597 : void BgpTable::Shutdown() {
1062 288597 : CHECK_CONCURRENCY("bgp::PeerMembership", "bgp::Config");
1063 288597 : }
1064 :
1065 288597 : void BgpTable::ManagedDelete() {
1066 288597 : BGP_LOG_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1067 : "Received request for table deletion");
1068 288597 : deleter_->Delete();
1069 288597 : }
1070 :
1071 : //
1072 : // Retry deletion of the table if it is pending.
1073 : //
1074 575037 : void BgpTable::RetryDelete() {
1075 575037 : if (!deleter()->IsDeleted())
1076 256114 : return;
1077 318919 : deleter()->RetryDelete();
1078 : }
1079 :
1080 0 : PathResolver *BgpTable::CreatePathResolver() {
1081 0 : return NULL;
1082 : }
1083 :
1084 172735 : void BgpTable::LocatePathResolver() {
1085 172735 : if (path_resolver_)
1086 1102 : return;
1087 171633 : assert(!deleter()->IsDeleted());
1088 171630 : path_resolver_ = CreatePathResolver();
1089 : }
1090 :
1091 171636 : void BgpTable::DestroyPathResolver() {
1092 171636 : if (!path_resolver_)
1093 0 : return;
1094 171636 : delete path_resolver_;
1095 171636 : path_resolver_ = NULL;
1096 : }
1097 :
1098 13663 : size_t BgpTable::GetPendingRiboutsCount(size_t *markers) const {
1099 13663 : CHECK_CONCURRENCY("bgp::ShowCommand", "bgp::Config");
1100 13663 : size_t count = 0;
1101 13663 : *markers = 0;
1102 :
1103 18191 : BOOST_FOREACH(const RibOutMap::value_type &value, ribout_map_) {
1104 2264 : const RibOut *ribout = value.second;
1105 9871 : for (int idx = 0; idx < DB::PartitionCount(); ++idx) {
1106 7607 : const RibOutUpdates *updates = ribout->updates(idx);
1107 22821 : for (int qid = RibOutUpdates::QFIRST; qid < RibOutUpdates::QCOUNT;
1108 : ++qid) {
1109 15214 : count += updates->queue_size(qid);
1110 15214 : *markers += updates->queue_marker_count(qid);
1111 : }
1112 : }
1113 : }
1114 :
1115 13663 : return count;
1116 : }
1117 :
1118 2075028 : LifetimeActor *BgpTable::deleter() {
1119 2075028 : return deleter_.get();
1120 : }
1121 :
1122 292041 : const LifetimeActor *BgpTable::deleter() const {
1123 292041 : return deleter_.get();
1124 : }
1125 :
1126 1930508 : void BgpTable::UpdatePathCount(const BgpPath *path, int count) {
1127 1930508 : if (dynamic_cast<const BgpSecondaryPath *>(path)) {
1128 1158409 : secondary_path_count_ += count;
1129 : } else {
1130 772099 : primary_path_count_ += count;
1131 : }
1132 :
1133 1931478 : if (!path->IsFeasible()) {
1134 8565 : infeasible_path_count_ += count;
1135 : }
1136 :
1137 1931372 : if (path->IsStale()) {
1138 90679 : stale_path_count_ += count;
1139 : }
1140 :
1141 1931294 : if (path->IsLlgrStale()) {
1142 20114 : llgr_stale_path_count_ += count;
1143 : }
1144 1931194 : }
1145 :
1146 : // Check whether the route is aggregate route
1147 0 : bool BgpTable::IsAggregateRoute(const BgpRoute *route) const {
1148 0 : return routing_instance()->IsAggregateRoute(this, route);
1149 : }
1150 :
1151 : // Check whether the route is contributing route to aggregate route
1152 920568 : bool BgpTable::IsContributingRoute(const BgpRoute *route) const {
1153 920568 : return routing_instance()->IsContributingRoute(this, route);
1154 : }
1155 :
1156 18 : void BgpTable::FillRibOutStatisticsInfo(
1157 : vector<ShowRibOutStatistics> *sros_list) const {
1158 22 : BOOST_FOREACH(const RibOutMap::value_type &value, ribout_map_) {
1159 2 : const RibOut *ribout = value.second;
1160 2 : ribout->FillStatisticsInfo(sros_list);
1161 : }
1162 18 : }
|